stat.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   stat.c
00004   an heraia plugin to calculate some stats on the opened file
00005 
00006   (C) Copyright 2007 - 2009 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009 
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option)
00013   any later version.
00014 
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019 
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023 */
00024 /**
00025  * @file stat.c
00026  * does some basic statistics on the file and displays them
00027  * in a numerical or graphical way (histograms : 1D and 2D)
00028  */
00029 #include "stat.h"
00030 
00031 /* The functions for the plugin's usage */
00032 static void stat_window_connect_signals(heraia_plugin_t *plugin);
00033 
00034 static void statw_close_clicked(GtkWidget *widget, gpointer data);
00035 static void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data);
00036 
00037 static void statw_save_as_clicked(GtkWidget *widget, gpointer data);
00038 static void statw_export_to_csv_clicked(GtkWidget *widget, gpointer data);
00039 static void statw_export_to_gnuplot_clicked(GtkWidget *widget, gpointer data);
00040 static void statw_export_to_pcv_clicked(GtkWidget *widget, gpointer data);
00041 
00042 static gchar *stat_select_file_to_save(gchar *window_text, stat_t *extra);
00043 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data);
00044 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data );
00045 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00046 static void init_stats_histos(heraia_plugin_t *plugin);
00047 static void set_statw_button_state(GladeXML *xml, gboolean sensitive);
00048 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00049 static void calc_infos_histo_1D(stat_t *extra);
00050 static void calc_infos_histo_2D(stat_t *extra);
00051 static void init_stats_pixbufs(stat_t *extra);
00052 static void make_pixbufs_from_histos(stat_t *extra);
00053 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha);
00054 static void do_pixbuf_1D_from_histo1D(stat_t *extra);
00055 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D);
00056 
00057 
00058 /**
00059  *  Initialisation plugin function called when the plugin is loaded
00060  *  (some sort of pre-init)
00061  *  @param[in,out] plugin : plugin's structure
00062  *  @return returns the plugin structure
00063  */
00064 heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00065 {
00066         stat_t *extra = NULL;            /**< extra structure specific to this plugin */
00067         window_prop_t *stat_prop = NULL; /**< window properties                       */
00068 
00069         plugin->state             = PLUGIN_STATE_INITIALIZING;
00070         plugin->xml = NULL;
00071 
00072         plugin->info->api_version = API_VERSION;
00073         plugin->info->type        = PLUGIN_TYPE;
00074         plugin->info->priority    = HERAIA_PRIORITY_DEFAULT;
00075         plugin->info->name        = PLUGIN_NAME;
00076         plugin->info->version     = PLUGIN_VERSION;
00077         plugin->info->summary     = PLUGIN_SUMMARY;
00078         plugin->info->description = PLUGIN_DESCRIPTION;
00079         plugin->info->author      = PLUGIN_AUTHOR;
00080         plugin->info->homepage    = PLUGIN_HOMEPAGE;
00081 
00082         plugin->init_proc    = init;
00083         plugin->quit_proc    = quit;
00084         plugin->run_proc     = run;
00085         plugin->refresh_proc = refresh;
00086 
00087         plugin->filter->extensions = NULL;
00088         plugin->filter->import     = NULL;
00089         plugin->filter->export     = NULL;
00090 
00091         /* add the extra struct to the plugin one */
00092         extra = (stat_t *) g_malloc0 (sizeof(stat_t));
00093         extra->infos_1D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00094         extra->infos_2D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00095         extra->dirname = NULL;
00096 
00097         /* window properties */
00098         stat_prop = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00099         stat_prop->displayed = FALSE; /* by default, it might be anything else */
00100         stat_prop->x = 0;
00101         stat_prop->y = 0;
00102 
00103         plugin->win_prop = stat_prop;
00104 
00105         plugin->extra = extra;
00106 
00107 
00108         return plugin;
00109 }
00110 
00111 /* the plugin interface functions */
00112 /**
00113  *  The real init function of the plugin (called at init time)
00114  * @param main_struct : main structure
00115  */
00116 void init(heraia_window_t *main_struct)
00117 {
00118         heraia_plugin_t *plugin = NULL;
00119 
00120         log_message(main_struct, G_LOG_LEVEL_INFO, "Initializing plugin %s", PLUGIN_NAME);
00121         /* first, know who we are ! */
00122         plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00123 
00124         if (plugin != NULL)
00125                 {
00126                         /* load the xml interface */
00127                         log_message(main_struct, G_LOG_LEVEL_INFO, "Plugin from %s found !", plugin->info->author);
00128                         if (load_plugin_glade_xml(main_struct, plugin) == TRUE)
00129                         {
00130                                 log_message(main_struct, G_LOG_LEVEL_INFO, "%s xml interface loaded.", plugin->info->name);
00131                         }
00132                         else
00133                         {
00134                                 log_message(main_struct, G_LOG_LEVEL_WARNING, "Unable to load %s xml interface.", plugin->info->name);
00135                         }
00136 
00137                         /* greyed save as button and others */
00138                         set_statw_button_state(plugin->xml, FALSE);
00139 
00140                         /* shows or hide the interface (hides it at first as all windows shows up) */
00141                         if (plugin->win_prop->displayed == FALSE)
00142                         {
00143                                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")));
00144                         }
00145                         else
00146                         {
00147                                 gtk_check_menu_item_set_active(plugin->cmi_entry, TRUE);
00148                         }
00149 
00150                         /* connect some signals handlers */
00151                         stat_window_connect_signals(plugin);
00152 
00153                 }
00154 }
00155 
00156 
00157 /**
00158  *  Normaly this is called when the plugin is unloaded
00159  *  One may wait it's entire life for this to be called !! ;)
00160  */
00161 void quit(void)
00162 {
00163         g_print("Quitting %s\n", PLUGIN_NAME);
00164 }
00165 
00166 
00167 /**
00168  *  This function is called via a signal handler when the menu entry is toggled
00169  * @param widget : widget which called the function (unused)
00170  * @param data : user data for the plugin, here MUST be heraia_window_t * main
00171  *        structure
00172  */
00173 void run(GtkWidget *widget, gpointer data)
00174 {
00175         heraia_window_t *main_struct = (heraia_window_t *) data; /* the signal send the pointer to this structure */
00176         heraia_plugin_t *plugin = NULL;
00177 
00178         /* first, know who we are ! */
00179         plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00180 
00181         if (plugin != NULL)
00182                 {
00183                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00184                                                          gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00185                         if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00186                                 {
00187                                         plugin->state = PLUGIN_STATE_RUNNING;
00188                                         realize_some_numerical_stat(main_struct, plugin);
00189                                 }
00190                         else
00191                                 {
00192                                         plugin->state = PLUGIN_STATE_NONE;
00193                                 }
00194                 }
00195 }
00196 
00197 
00198 /**
00199  * Sets stat window's button's sensitive property
00200  * @param xml : The plugin's xml description
00201  * @param sensitive : whether the buttons are greyed (FALSE) or not (TRUE)
00202  */
00203 static void set_statw_button_state(GladeXML *xml, gboolean sensitive)
00204 {
00205         if (xml != NULL)
00206         {
00207                 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_save_as"), sensitive);
00208                 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_csv"), sensitive);
00209                 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_gnuplot"), sensitive);
00210                 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_pcv"), sensitive);
00211         }
00212 }
00213 
00214 /**
00215  *  The refresh function is called when a new file is loaded or when the cursor is moved
00216  *  Here we want to refresh the plugin only if a new file is loaded AND if the plugin
00217  *  is already displayed (running)
00218  * @param main_struct : main structure
00219  * @param data : user data (the plugin itself) MUST be heraia_plugin_t *plugin
00220  *               structure
00221  */
00222 void refresh(heraia_window_t *main_struct, void *data)
00223 {
00224         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00225 
00226         if (main_struct != NULL && plugin != NULL)
00227                 {
00228                         if (main_struct->event == HERAIA_REFRESH_NEW_FILE || main_struct->event == HERAIA_REFRESH_TAB_CHANGED) /* && plugin->state == PLUGIN_STATE_RUNNING) */
00229                                 {
00230                                         set_statw_button_state(plugin->xml, TRUE);
00231                                         plugin->run_proc(NULL, (gpointer) main_struct);
00232                                 }
00233                 }
00234 }
00235 
00236 /* end of the plugin interface functions */
00237 
00238 /**
00239  *  Usefull functions for the stat plugin
00240  *  those may be included in an another .c source file ?!
00241  */
00242 
00243 /**
00244  * Closes stat window
00245  * @param widget : the widget which called this function
00246  * @param event : the event that issued the signal (unused here)
00247  * @param data : user data, MUST be heraia_plugin_t *plugin
00248  * @return resturns always FALSE (does not propagate the signal)
00249  */
00250 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00251 {
00252         statw_close_clicked(widget, data);
00253 
00254         return TRUE;
00255 }
00256 
00257 
00258 /**
00259 
00260  * Closes stat window
00261  * @param widget : the widget which called this function
00262  * @param event : the event that issued the signal (unused here)
00263  * @param data : user data, MUST be heraia_plugin_t *plugin
00264  */
00265 static void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00266 {
00267         statw_close_clicked(widget, data);
00268 }
00269 
00270 
00271 /**
00272  *  What to do when the window is closed
00273  * @param widget : the widget which called this function (unused here)
00274  * @param data : user data, MUST be heraia_plugin_t *plugin
00275  */
00276 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00277 {
00278         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00279 
00280         if (plugin != NULL)
00281                 {
00282                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00283                         gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00284                 }
00285 }
00286 
00287 
00288 /**
00289  *  What to do when the save as button is clicked
00290  * @param widget : the widget which called this function (unused here)
00291  * @param data : user data, MUST be heraia_plugin_t *plugin
00292  */
00293 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00294 {
00295         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00296         stat_t *extra = NULL;
00297         GtkImage *image = NULL;
00298         GdkPixbuf *pixbuf = NULL;
00299         gchar *filename = NULL;
00300         GError **error = NULL;
00301 
00302         if (plugin != NULL)
00303                 {
00304                         extra = (stat_t *) plugin->extra;
00305                         
00306                         image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00307                         pixbuf = gtk_image_get_pixbuf(image);
00308 
00309                         filename = stat_select_file_to_save("Enter filename's to save the image to", extra);
00310                         if (filename != NULL)
00311                         {
00312                                 gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00313                                 g_free(filename);
00314                         }
00315                 }
00316 }
00317 
00318 /**
00319  *  Selecting the file filename where to save the file
00320  * @param window_text : text to be displayed in the selection window
00321  * @return returns the new filename where to save a file
00322  */
00323 static gchar *stat_select_file_to_save(gchar *window_text, stat_t *extra)
00324 {
00325         GtkFileChooser *file_chooser = NULL;
00326         gint response_id = 0;
00327         gchar *filename;
00328 
00329         file_chooser = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(window_text, NULL,
00330                                                                                                                                 GTK_FILE_CHOOSER_ACTION_SAVE,
00331                                                                                                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00332                                                                                                                                 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
00333                                                                                                                                 NULL));
00334 
00335         /* for the moment we do not want to retrieve multiples selections */
00336         gtk_window_set_modal(GTK_WINDOW(file_chooser), TRUE);
00337         gtk_file_chooser_set_select_multiple(file_chooser, FALSE);
00338         gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, TRUE);
00339 
00340     /* If it exists define a new directory name */
00341         if (extra != NULL && extra->dirname != NULL)
00342         {
00343                 gtk_file_chooser_set_current_folder(file_chooser, extra->dirname);
00344         }
00345 
00346         response_id = gtk_dialog_run(GTK_DIALOG(file_chooser));
00347 
00348         switch (response_id)
00349                 {
00350                 case GTK_RESPONSE_OK:
00351                         filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
00352                         
00353                         /* Saving directory name in order to use it at a later call */
00354                         if (filename != NULL) 
00355                         {
00356                                 if (extra->dirname != NULL)
00357                                 {
00358                                         g_free(extra->dirname);
00359                                 }
00360                                 extra->dirname = g_path_get_dirname(filename);
00361                         }
00362                         
00363                         break;
00364                 case GTK_RESPONSE_CANCEL:
00365                 default:
00366                         filename = NULL;
00367                         break;
00368                 }
00369 
00370         gtk_widget_destroy(GTK_WIDGET(file_chooser));
00371         return filename;
00372 }
00373 
00374 /**
00375  * What to do when "export to csv" button is clicked
00376  * @param widget : the widget which called this function
00377  * @param data : user data, MUST be heraia_plugin_t *plugin
00378  */
00379 static void statw_export_to_csv_clicked(GtkWidget *widget, gpointer data)
00380 {
00381         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00382         stat_t *extra = NULL;
00383         gchar *filename = NULL;
00384         FILE *fp = NULL;
00385         guint i = 0;
00386         guint j = 0;
00387 
00388         if (plugin != NULL)
00389                 {
00390                         extra = (stat_t *) plugin->extra;
00391 
00392                         filename = stat_select_file_to_save("Enter filename to export data as CSV to", extra);
00393 
00394                         if (filename != NULL)
00395                         {
00396                                 fp = g_fopen(filename, "w+");
00397                         }
00398 
00399                         if (fp != NULL && extra != NULL)
00400                         {
00401                                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00402                                 {
00403                                         /* 1D display */
00404                                         fprintf(fp, "\"Byte\";\"Count\"\n");
00405 
00406                                         for (i=0; i<=255; i++)
00407                                         {
00408                                                 fprintf(fp, "%d;%Ld\n", i, extra->histo1D[i]);
00409                                         }
00410 
00411                                 }
00412                                 else
00413                                 {
00414                                         /* 2D display */
00415                                         fprintf(fp, "\"Byte/Byte\";");
00416                                         for (j=0; j<255; j++)
00417                                         {
00418                                                 fprintf(fp, "\"%d\";", j);
00419                                         }
00420                                         fprintf(fp, "\"%d\"\n", 255);
00421 
00422                                         for (i=0; i<=255; i++)
00423                                         {
00424                                                 fprintf(fp, "\"%d\";", i);
00425                                                 for (j=0 ; j<255; j++)
00426                                                 {
00427                                                         fprintf(fp, "\"%Ld\";", extra->histo2D[i][j]);
00428                                                 }
00429                                                 fprintf(fp, "\"%Ld\"\n", extra->histo2D[i][255]);
00430                                         }
00431                                 }
00432                                 fclose(fp);
00433                         }
00434                         if (filename != NULL)
00435                         {
00436                                 g_free(filename);
00437                         }
00438                 }
00439 }
00440 
00441 /**
00442  * What to do when "export to gnuplot" button is clicked
00443  * @param widget : the widget which called this function
00444  * @param data : user data, MUST be heraia_plugin_t *plugin
00445  */
00446 static void statw_export_to_gnuplot_clicked(GtkWidget *widget, gpointer data)
00447 {
00448         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00449         stat_t *extra = NULL;
00450         gchar *filename = NULL;
00451         FILE *fp = NULL;
00452         guint i = 0;
00453         guint j = 0;
00454 
00455         if (plugin != NULL)
00456                 {
00457                         extra = (stat_t *) plugin->extra;
00458 
00459                         filename = stat_select_file_to_save("Enter filename to export data as gnuplot to", extra);
00460 
00461                         if (filename != NULL)
00462                         {
00463                                 fp = g_fopen(filename, "w+");
00464                         }
00465 
00466                         if (fp != NULL && extra != NULL)
00467                         {
00468                                 /* common settings */
00469                                 fprintf(fp, "set terminal png transparent nocrop enhanced small size 1280,960\n");
00470                                 fprintf(fp, "set output '%s.png'\n", g_path_get_basename(filename));
00471                                 fprintf(fp, "set xrange [-10:265]\n");
00472                                 fprintf(fp, "set xlabel 'Bytes'\n");
00473 
00474                                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00475                                 {
00476                                         /* 1D display */
00477                                         fprintf(fp, "set title 'Classical histogram'\n");  /**< @todo we might add here the name of the file being edited */
00478                                         fprintf(fp, "set ylabel 'Count'\n");
00479                                         fprintf(fp, "plot '-' title 'Byte count' with impulses\n");
00480 
00481                                         for (i=0; i<=255; i++)
00482                                         {
00483                                                 fprintf(fp, "%Ld\n", extra->histo1D[i]);
00484                                         }
00485                                         fprintf(fp, "e\n");
00486                                 }
00487                                 else
00488                                 {
00489                                         /* 2D display */
00490                                         fprintf(fp, "set title 'Heatmap histogram'\n");  /**< @todo we might add here the name of the file being edited */
00491                                         fprintf(fp, "set bar 1.000000\n");
00492                                         fprintf(fp, "set style rectangle back fc lt -3 fillstyle solid 1.00 border -1\n");
00493                                         fprintf(fp, "unset key\n");
00494                                         fprintf(fp, "set view map\n");
00495                                         fprintf(fp, "set yrange [-10:265]\n");
00496                                         fprintf(fp, "set ylabel 'Bytes'\n");
00497                                         fprintf(fp, "set palette rgbformulae 36, 13, 15\n");
00498                                         fprintf(fp, "splot '-' matrix with image\n");
00499 
00500                                         for (i=0; i<=255; i++)
00501                                         {
00502                                                 for (j=0; j<=255; j++)
00503                                                 {
00504                                                         fprintf(fp, "%Ld ", extra->histo2D[i][j]);
00505                                                 }
00506                                                 fprintf(fp, "\n");
00507                                         }
00508 
00509                                         fprintf(fp, "e\n");
00510                                         fprintf(fp, "e\n");
00511                                 }
00512                                 fclose(fp);
00513                         }
00514                         if (filename != NULL)
00515                         {
00516                                 g_free(filename);
00517                         }
00518                 }
00519 }
00520 
00521 /**
00522  * What to do when "export to pcv" button is clicked
00523  * @param widget : the widget which called this function
00524  * @param data : user data, MUST be heraia_plugin_t *plugin
00525  */
00526 static void statw_export_to_pcv_clicked(GtkWidget *widget, gpointer data)
00527 {
00528         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00529         stat_t *extra = NULL;
00530         gchar *filename = NULL;
00531         FILE *fp = NULL;
00532         guint i = 0;
00533         guint j = 0;
00534 
00535         if (plugin != NULL)
00536                 {
00537                         extra = (stat_t *) plugin->extra;
00538 
00539                         filename = stat_select_file_to_save("Enter filename to export data as PCV to", extra);
00540 
00541                         if (filename != NULL)
00542                         {
00543                                 fp = g_fopen(filename, "w+");
00544                         }
00545 
00546                         if (fp != NULL && extra != NULL)
00547                         {
00548                                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00549                                 {
00550                                         /* 1D display */
00551                                         fprintf(fp, "header {\n");
00552                                         fprintf(fp, "\theight = \"960\";\n");
00553                                         fprintf(fp, "\twidth = \"1280\";\n");
00554                                         fprintf(fp, "\ttitle = \"Classical histogram\";\n");
00555                                         fprintf(fp, "}\n");
00556                                         fprintf(fp, "axes {\n");
00557                                         fprintf(fp, "\tinteger b [label=\"Bytes\"];\n");
00558                                         fprintf(fp, "\tinteger c [label=\"Byte count\"];\n");
00559                                         fprintf(fp, "}\n");
00560                                         fprintf(fp, "data {\n");
00561 
00562                                         for (i=0; i<=255; i++)
00563                                         {
00564                                                 fprintf(fp, "\tb=\"%d\", c=\"%Ld\";\n", i, extra->histo1D[i]);
00565                                         }
00566                                         fprintf(fp, "}\n");
00567                                 }
00568                                 else
00569                                 {
00570                                         /* 2D display */
00571                                         fprintf(fp, "header {\n");
00572                                         fprintf(fp, "\theight = \"960\";\n");
00573                                         fprintf(fp, "\twidth = \"1280\";\n");
00574                                         fprintf(fp, "\ttitle = \"Classical histogram\";\n");
00575                                         fprintf(fp, "}\n");
00576                                         fprintf(fp, "axes {\n");
00577                                         fprintf(fp, "\tchar a [label=\"Bytes\"];\n");
00578                                         fprintf(fp, "\tport c [label=\"Byte count\"];\n");
00579                                         fprintf(fp, "\tchar b [label=\"Bytes\"];\n");
00580                                         fprintf(fp, "}\n");
00581                                         fprintf(fp, "data {\n");
00582 
00583                                         for (i=0; i<=255; i++)
00584                                         {
00585                                                 for (j=0; j<=255; j++)
00586                                                 {
00587                                                         if (extra->histo2D[i][j] == extra->infos_2D->max)
00588                                                                 {
00589                                                                         fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\" [color=\"red\"];\n", i, extra->histo2D[i][j], j);
00590                                                                 }
00591                                                                 else
00592                                                                 {
00593                                                                         if (extra->histo2D[i][j] == extra->infos_2D->min)
00594                                                                                 {
00595                                                                                         fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\" [color=\"green\"];\n", i, extra->histo2D[i][j], j);
00596                                                                                 }
00597                                                                                 else
00598                                                                                 {
00599                                                                                         fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\";\n", i, extra->histo2D[i][j], j);
00600                                                                                 }
00601                                                                 }
00602                                                 }
00603                                         }
00604                                         fprintf(fp, "}\n");
00605                                 }
00606                                 fclose(fp);
00607                         }
00608                         if (filename != NULL)
00609                         {
00610                                 g_free(filename);
00611                         }
00612                 }
00613 }
00614 
00615 
00616 
00617 /**
00618  *  What to do when the user chooses a 1D or 2D histo
00619  * @param widget : the widget which called this function (unused here)
00620  * @param data : user data, MUST be heraia_plugin_t *plugin
00621  */
00622 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00623 {
00624         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00625 
00626         if (plugin != NULL)
00627                 {
00628                         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00629                         stat_t *extra = (stat_t *) plugin->extra;
00630 
00631                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00632                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00633                         else
00634                                 {
00635                                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00636                                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00637                                 }
00638                 }
00639 }
00640 
00641 
00642 /**
00643  *  Connects all the signals to the correct functions
00644  * @param plugin : main plugin structure
00645  */
00646 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00647 {
00648 
00649         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event",
00650                                          G_CALLBACK(delete_stat_window_event), plugin);
00651 
00652         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy",
00653                                          G_CALLBACK(destroy_stat_window), plugin);
00654 
00655         /* Close Button */
00656         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked",
00657                                          G_CALLBACK(statw_close_clicked), plugin);
00658 
00659         /* RadioButton */
00660         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled",
00661                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00662 
00663         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled",
00664                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00665 
00666         /* Save As Button */
00667         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked",
00668                                          G_CALLBACK(statw_save_as_clicked), plugin);
00669 
00670         /* CVS button */
00671         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_csv")), "clicked",
00672                                          G_CALLBACK(statw_export_to_csv_clicked), plugin);
00673 
00674         /* Gnuplot button */
00675         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_gnuplot")), "clicked",
00676                                          G_CALLBACK(statw_export_to_gnuplot_clicked), plugin);
00677 
00678         /* PCV button */
00679         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_pcv")), "clicked",
00680                                          G_CALLBACK(statw_export_to_pcv_clicked), plugin);
00681 
00682         /* the toogle button is already connected to the run_proc function ! */
00683 }
00684 
00685 
00686 /**
00687  * Do some stats on the selected file (entire file is used)
00688  * @param main_struct : main structure from heraia
00689  * @param plugin : main plugin structure (the plugin itself in fact)
00690  */
00691 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00692 {
00693         struct stat *stat_buf;
00694         gchar buf[42];           /**< used for date printing */
00695         gchar *filename = NULL;
00696         stat_t *extra = NULL;
00697         GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00698 
00699         if (main_struct != NULL && main_struct->current_doc != NULL)
00700         {
00701                 filename = doc_t_document_get_filename(main_struct->current_doc);
00702         }
00703 
00704         if (filename != NULL)
00705                 {
00706                         log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s",  filename);
00707 
00708                         stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00709                         g_lstat(filename, stat_buf);
00710                         if (S_ISREG(stat_buf->st_mode))
00711                                 {
00712                                         kill_text_from_textview(textview);
00713                                         add_text_to_textview(textview, "File size : %Ld bytes\n\n", stat_buf->st_size);
00714                                         ctime_r(&(stat_buf->st_mtime), buf);
00715                                         add_text_to_textview(textview, "Last intern modification : %s", buf);
00716                                         ctime_r(&(stat_buf->st_atime), buf);
00717                                         add_text_to_textview(textview, "Last acces to the file   : %s", buf);
00718                                         ctime_r(&(stat_buf->st_ctime), buf);
00719                                         add_text_to_textview(textview, "Last extern modification : %s", buf);
00720 
00721                                         populate_stats_histos(main_struct, plugin);
00722 
00723                                         extra = (stat_t *) plugin->extra;
00724 
00725                                         add_text_to_textview(textview, "\n1D histogram statistics :\n");
00726                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_1D->min);
00727                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_1D->max);
00728                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_1D->mean);
00729                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_1D->nb_val);
00730                                         add_text_to_textview(textview, "\n2D histogram statistics :\n");
00731                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_2D->min);
00732                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_2D->max);
00733                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_2D->mean);
00734                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_2D->nb_val);
00735                                         log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00736                                 }
00737                 }
00738 }
00739 
00740 
00741 /**
00742  *  Inits the histograms
00743  */
00744 static void init_stats_histos(heraia_plugin_t *plugin)
00745 {
00746         guint i = 0;
00747         guint j = 0;
00748         stat_t *extra = NULL;
00749 
00750         /* inits the structures */
00751         extra = (stat_t *) plugin->extra;
00752         for (i=0; i<=255; i++)
00753                 {
00754                         extra->histo1D[i] = 0 ;
00755                         for (j=0; j<=255; j++)
00756                                 extra->histo2D[i][j] = 0 ;
00757                 }
00758 }
00759 
00760 
00761 /**
00762  *  Populates the histograms
00763  */
00764 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00765 {
00766         GtkHex *gh = GTK_HEX(main_struct->current_doc->hex_widget);
00767         guint64 i = 0;
00768         guint64 taille = ghex_file_size(gh);
00769         guchar c1, c2;
00770         stat_t *extra = (stat_t *) plugin->extra;
00771         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00772         GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00773         GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00774 
00775         init_stats_histos(plugin);
00776 
00777         while (i < taille)
00778                 {
00779                         c1 = gtk_hex_get_byte(gh, i);
00780                         extra->histo1D[c1]++;
00781                         if (i+1 < taille)
00782                                 {
00783                                         i++;
00784                                         c2 = gtk_hex_get_byte(gh, i);
00785                                         extra->histo1D[c2]++;
00786                                         extra->histo2D[c1][c2]++;
00787                                 }
00788                         i++;
00789                 }
00790 
00791         make_pixbufs_from_histos(extra);
00792 
00793         if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00794                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00795         else
00796                 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00797                         gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00798 }
00799 
00800 
00801 /**
00802  *  Seeks the histo1D struct to find the maximum value
00803  */
00804 static void calc_infos_histo_1D(stat_t *extra)
00805 {
00806         guint i = 0;
00807         gint64 n = 1;
00808         guint64 max = 0;
00809         guint64 min = G_MAXUINT64;
00810         gint64 mean = extra->histo1D[0];
00811         gint64 diff = 0;
00812 
00813         extra->infos_1D->nb_val = 0;
00814 
00815         for (i=0; i<=255; i++)
00816                 {
00817                         /* maximum value */
00818                         if (extra->histo1D[i] > max)
00819                                 max = extra->histo1D[i];
00820 
00821                         /* minimum value */
00822                         if (extra->histo1D[i] < min)
00823                                 min = extra->histo1D[i];
00824 
00825                         /* number of different values */
00826                         if (extra->histo1D[i] > 0)
00827                                 extra->infos_1D->nb_val++;
00828 
00829                         /* mean calculation */
00830                         diff = extra->histo1D[i] - mean;
00831                         mean = mean + diff/n;
00832                         n++;
00833                 }
00834 
00835         extra->infos_1D->min = min;
00836         extra->infos_1D->max = max;
00837         extra->infos_1D->mean = (guint64) mean;
00838 }
00839 
00840 
00841 /**
00842  *  Seeks the histo2D struct to find the maximum value
00843  */
00844 static void calc_infos_histo_2D(stat_t *extra)
00845 {
00846         guint i = 0;
00847         guint j = 0;
00848         gint64 n = 1;
00849         guint64 max = 0;
00850         guint64 min = G_MAXUINT;
00851         gint64 mean = extra->histo2D[0][0];
00852         gint64 diff = 0;
00853 
00854         extra->infos_2D->nb_val = 0;
00855 
00856         for (i=0; i<=255; i++)
00857                 {
00858                         for (j=0; j<=255; j++)
00859                                 {
00860                                         /* maximum value */
00861                                         if (extra->histo2D[i][j] > max)
00862                                                 max = extra->histo2D[i][j];
00863 
00864                                         /* minimum value */
00865                                         if (extra->histo2D[i][j] < min)
00866                                                 min = extra->histo2D[i][j];
00867 
00868                                         /* number of different values */
00869                                         if (extra->histo2D[i][j] > 0)
00870                                                 extra->infos_2D->nb_val++;
00871 
00872                                         /* mean calculation */
00873                                         diff = extra->histo2D[i][j] - mean;
00874                                         mean = mean + diff/n;
00875                                         n++;
00876                                 }
00877                 }
00878 
00879         extra->infos_2D->min = min;
00880         extra->infos_2D->max = max;
00881         extra->infos_2D->mean = (guint64) mean;
00882 }
00883 
00884 
00885 /**
00886  *  Inits the image buffers
00887  */
00888 static void init_stats_pixbufs(stat_t *extra)
00889 {
00890 
00891         extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00892         gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00893         gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00894 
00895         extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00896         gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00897         gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00898 
00899 }
00900 
00901 
00902 /**
00903  *  Makes the pixbufs from the histograms values
00904  */
00905 static void make_pixbufs_from_histos(stat_t *extra)
00906 {
00907         init_stats_pixbufs(extra);
00908         calc_infos_histo_1D(extra);
00909         calc_infos_histo_2D(extra);
00910 
00911         if (extra->infos_1D->max > 0)
00912                 do_pixbuf_1D_from_histo1D(extra);
00913         if (extra->infos_2D->max > 0)
00914                 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00915 }
00916 
00917 
00918 /**
00919  *  Prints a pixel in the corresponding pixbuf
00920  */
00921 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00922 {
00923   guchar *pixels = NULL;
00924   guchar *p = NULL;
00925 
00926   pixels = gdk_pixbuf_get_pixels(pixbuf);
00927 
00928   p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00929 
00930   p[0] = red;
00931   p[1] = green;
00932   p[2] = blue;
00933   p[3] = alpha;
00934 
00935 }
00936 
00937 
00938 /**
00939  *  Prints a line of pixels in the corresponding pixbuf (1D histo)
00940  */
00941 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00942 {
00943         guchar *pixels = NULL;
00944         guchar *p = NULL;
00945 
00946         if (pixbuf != NULL)
00947                 {
00948 
00949                         gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00950                         gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00951 
00952                         pixels = gdk_pixbuf_get_pixels(pixbuf);
00953 
00954                         while (y<255)
00955                                 {
00956                                         p = pixels + y * rowstride + x * n_channels;
00957                                         p[0] = (guchar) 255-(y/2);
00958                                         p[1] = (guchar) 16;
00959                                         p[2] = (guchar) y/2;
00960                                         p[3] = (guchar) 255;
00961                                         y++;
00962                                 }
00963                 }
00964 }
00965 
00966 
00967 /**
00968  *  Fills the pixbuf with the corresponding data from the
00969  *  histo1D struct
00970  */
00971 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00972 {
00973         guint i = 0;
00974         gint64 y = 0;
00975         gdouble inter = 0;
00976         gdouble y_norm = 0;
00977 
00978         for (i=0; i<=255; i++)
00979                 {
00980                         /* normalisation (here we know that max != 0 (cf make_pixbufs_from_histos) */
00981                         y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00982                         inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00983                         y = (gint64) inter;
00984                         line_in_pixbuf(extra->pixbuf_1D, i, y);
00985                 }
00986 }
00987 
00988 
00989 /**
00990  *  Fills the pixbuf with the corresponding data from the
00991  *  histo2D struct
00992  *  It is really hard to make something very visible (to make colors
00993  *  look really different between to height values)
00994  */
00995 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00996 {
00997         /* A sort of color 'normalization' */
00998         guint i = 0;
00999         guint j = 0;
01000         guchar red;
01001         guchar green;
01002         guchar blue;
01003         gdouble height = 0;
01004         gdouble max = 0;
01005         gdouble min = 0;
01006         gdouble mean = 0;
01007         gdouble threshold1 = 0;
01008         gdouble threshold2 = 0;
01009         guchar ceill;
01010         guchar floor;
01011 
01012         max = extra->infos_2D->max;
01013         min = extra->infos_2D->min;
01014         mean = extra->infos_2D->mean;
01015 
01016         threshold1 = min + (mean - min) / 2;
01017         threshold2 = mean + (max - mean) / 2;
01018 
01019         floor = (guchar) 50;
01020         ceill = (guchar) 200;
01021 
01022         for (i=0; i<=255; i++)
01023         {
01024                         for (j=0; j<=255; j++)
01025                         {
01026                                         height = extra->histo2D[i][j];  /* min .. max */
01027 
01028                                 if (height > 0)
01029                                 {
01030 
01031                                         if (height >= min && height <= threshold1)
01032                                         {
01033                                                 red = floor;
01034                                                 green = floor;
01035                                                 blue = (guchar) (height - min)*(ceill-floor) / threshold1;
01036                                                 /*
01037                                                  * height = (gdouble) (height*255) / (gdouble) extra->infos_2D->max;
01038                                                  * red = (guchar)  height;
01039                                                  * green = (guchar) 255 - (height);
01040                                                  * blue = (guchar) height/2;
01041                                                  */
01042                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01043                                         }
01044                                         else if (height > threshold1 && height <= threshold2)
01045                                         {
01046                                                 red = (guchar) floor;
01047                                                 green = (guchar) (height - threshold1)*(ceill-floor) / (threshold2 - threshold1);
01048                                                 blue = (guchar) floor; /* ceill - green;*/
01049                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01050                                         }
01051                                         else if (height > threshold2 && height <= max)
01052                                         {
01053                                                 red = (guchar) (height - threshold2)*(ceill-floor) / (max - threshold2);
01054                                                 green = floor; /* ceill - red; */
01055                                                 blue = floor;
01056                                                 /*
01057                                                  * height = (gdouble) height*255 / (gdouble) extra->infos_2D->max;
01058                                                  * red = (guchar)  255 - (height);
01059                                                  * green = (guchar) height/2;
01060                                                  * blue = (guchar) height;
01061                                                  */
01062                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01063                                         }
01064                                 }
01065                         }
01066         }
01067 }
01068 
01069 

Generated on Tue Jun 30 23:18:17 2009 for Heraia by  doxygen 1.5.8