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

Generated on Tue May 19 20:01:37 2009 for Heraia by  doxygen 1.5.8