gnome-power-manager r3170 - in trunk: . src



Author: rhughes
Date: Thu Jan 22 14:07:53 2009
New Revision: 3170
URL: http://svn.gnome.org/viewvc/gnome-power-manager?rev=3170&view=rev

Log:
2009-01-22  Richard Hughes  <richard hughsie com>

* src/Makefile.am:
* src/gpm-self-test.c: (main):
Add in egg-array-float to the self checks;

* src/egg-array-float.c: (egg_array_float_compute_gaussian),
(powfi), (egg_array_float_remove_outliers), (egg_array_float_test):
Add in a simple outlier removal function, and add some more unit tests.

* src/egg-array-float.h:
* src/gpm-statistics.c: (gpm_stats_update_smooth_data),
(gpm_stats_update_info_page_history),
(gpm_stats_update_info_page_stats), (main):
Remove outliers from the data, and smooth with different values of
sigma for the different graph tabs.


Modified:
   trunk/ChangeLog
   trunk/src/Makefile.am
   trunk/src/egg-array-float.c
   trunk/src/egg-array-float.h
   trunk/src/gpm-self-test.c
   trunk/src/gpm-statistics.c

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Thu Jan 22 14:07:53 2009
@@ -281,6 +281,8 @@
 	egg-precision.c					\
 	egg-discrete.h					\
 	egg-discrete.c					\
+	egg-array-float.h				\
+	egg-array-float.c				\
 	gpm-ac-adapter.h				\
 	gpm-ac-adapter.c				\
 	gpm-prefs-server.h				\

Modified: trunk/src/egg-array-float.c
==============================================================================
--- trunk/src/egg-array-float.c	(original)
+++ trunk/src/egg-array-float.c	Thu Jan 22 14:07:53 2009
@@ -140,13 +140,17 @@
 	guint half_length;
 	guint i;
 	gfloat division;
+	gfloat value;
+
+	g_return_val_if_fail (length % 2 == 1, NULL);
 
 	array = egg_array_float_new (length);
 
-	/* array positions 0..10, has to be an odd number */
+	/* array positions 0..length, has to be an odd number */
 	half_length = (length / 2) + 1;
 	for (i=0; i<half_length; i++) {
 		division = half_length - (i + 1);
+	egg_debug ("half_length=%i, div=%f, sigma=%f", half_length, division, sigma);
 		g_array_index (array, gfloat, i) = egg_array_float_guassian_value (division, sigma);
 	}
 
@@ -155,6 +159,15 @@
 		division = g_array_index (array, gfloat, length-(i+1));
 		g_array_index (array, gfloat, i) = division;
 	}
+
+	/* make sure we get an accurate gaussian */
+	value = egg_array_float_sum (array);
+	if (fabs (value - 1.0f) > 0.01f) {
+		egg_warning ("got wrong sum (%f), perhaps sigma too high for size?", value);
+		egg_array_float_free (array);
+		array = NULL;
+	}
+
 	return array;
 }
 
@@ -265,6 +278,97 @@
 	return value;
 }
 
+/**
+ * powfi:
+ **/
+static gfloat
+powfi (gfloat base, guint n)
+{
+	guint i;
+	gfloat retval = 1;
+	for (i=1; i <= n; i++)
+		retval *= base;
+	return retval;
+}
+
+/**
+ * egg_array_float_remove_outliers:
+ *
+ * @data: input array
+ * @size: size to analyse
+ * @sigma: sigma for standard deviation
+ * Return value: Data with outliers removed
+ *
+ * Compares local sections of the data, removing outliers if they fall
+ * ouside of sigma, and using the average of the other points in it's place.
+ **/
+EggArrayFloat *
+egg_array_float_remove_outliers (EggArrayFloat *data, guint length, gfloat sigma)
+{
+	guint i;
+	guint j;
+	guint half_length;
+	gfloat value;
+	gfloat average;
+	gfloat average_not_inc;
+	gfloat average_square;
+	gfloat biggest_difference;
+	gfloat outlier_value;
+	EggArrayFloat *result;
+
+	g_return_val_if_fail (length % 2 == 1, NULL);
+
+	result = egg_array_float_new (data->len);
+	half_length = (length - 1) / 2;
+
+	/* copy start and end of array */
+	for (i=0; i < half_length; i++)
+		g_array_index (result, gfloat, i) = g_array_index (data, gfloat, i);
+	for (i=data->len-half_length; i < data->len; i++)
+		g_array_index (result, gfloat, i) = g_array_index (data, gfloat, i);
+
+	/* find the standard deviation of a block off data */
+	for (i=half_length; i < data->len-half_length; i++) {
+		average = 0;
+		average_square = 0;
+
+		/* find the average and the squared average */
+		for (j=i-half_length; j<i+half_length+1; j++) {
+			value = g_array_index (data, gfloat, j);
+			average += value;
+			average_square += powfi (value, 2);
+		}
+
+		/* divide by length to get average */
+		average /= length;
+		average_square /= length;
+
+		/* find the standard deviation */
+		value = sqrtf (average_square - powfi (average, 2));
+
+		/* stddev is okay */
+		if (value < sigma) {
+			g_array_index (result, gfloat, i) = g_array_index (data, gfloat, i);
+		} else {
+			/* ignore the biggest difference from the average */
+			biggest_difference = 0;
+			outlier_value = 0;
+			for (j=i-half_length; j<i+half_length+1; j++) {
+				value = fabs (g_array_index (data, gfloat, j) - average);
+				if (value > biggest_difference) {
+					biggest_difference = value;
+					outlier_value = g_array_index (data, gfloat, j);
+				}
+			}
+			average_not_inc = (average * length) - outlier_value;
+			average_not_inc /= length - 1;
+			g_array_index (result, gfloat, i) = average_not_inc;
+		}
+	}
+
+	return result;
+}
+
 /***************************************************************************
  ***                          MAKE CHECK TESTS                           ***
  ***************************************************************************/
@@ -311,30 +415,117 @@
 		egg_test_failed (test, "got wrong sum (%f)", value);
 
 	/************************************************************/
-	egg_test_title (test, "get gaussian 0.0, sigma 1.0");
-	value = egg_array_float_guassian_value (0.0, 1.0);
-	if (value - 0.398942 < 0.0001)
+	egg_test_title (test, "remove outliers");
+	egg_array_float_set (array, 0, 30.0);
+	egg_array_float_set (array, 1, 29.0);
+	egg_array_float_set (array, 2, 31.0);
+	egg_array_float_set (array, 3, 33.0);
+	egg_array_float_set (array, 4, 100.0);
+	egg_array_float_set (array, 5, 27.0);
+	egg_array_float_set (array, 6, 30.0);
+	egg_array_float_set (array, 7, 29.0);
+	egg_array_float_set (array, 8, 31.0);
+	egg_array_float_set (array, 9, 30.0);
+	kernel = egg_array_float_remove_outliers (array, 3, 10.0);
+	if (kernel != NULL && kernel->len == 10) 
+		egg_test_success (test, "got correct length outlier array");
+	else
+		egg_test_failed (test, "got gaussian array length (%i)", array->len);
+	egg_array_float_print (array);
+	egg_array_float_print (kernel);
+
+	/************************************************************/
+	egg_test_title (test, "make sure we removed the outliers");
+	value = egg_array_float_sum (kernel);
+	if (fabs(value - 30*10) < 1)
+		egg_test_success (test, "got sum (%f)", value);
+	else
+		egg_test_failed (test, "got wrong sum (%f)", value);
+	egg_array_float_free (kernel);
+
+	/************************************************************/
+	egg_test_title (test, "remove outliers step");
+	egg_array_float_set (array, 0, 0.0);
+	egg_array_float_set (array, 1, 0.0);
+	egg_array_float_set (array, 2, 0.0);
+	egg_array_float_set (array, 3, 0.0);
+	egg_array_float_set (array, 4, 0.0);
+	egg_array_float_set (array, 5, 0.0);
+	egg_array_float_set (array, 6, 0.0);
+	egg_array_float_set (array, 7, 10.0);
+	egg_array_float_set (array, 8, 20.0);
+	egg_array_float_set (array, 9, 50.0);
+	kernel = egg_array_float_remove_outliers (array, 3, 20.0);
+	if (kernel != NULL && kernel->len == 10) 
+		egg_test_success (test, "got correct length outlier array");
+	else
+		egg_test_failed (test, "got gaussian array length (%i)", array->len);
+	egg_array_float_print (array);
+	egg_array_float_print (kernel);
+
+	/************************************************************/
+	egg_test_title (test, "make sure we removed the outliers");
+	value = egg_array_float_sum (kernel);
+	if (fabs(value - 80) < 1)
+		egg_test_success (test, "got sum (%f)", value);
+	else
+		egg_test_failed (test, "got wrong sum (%f)", value);
+	egg_array_float_free (kernel);
+
+	/************************************************************/
+	egg_test_title (test, "get gaussian 0.0, sigma 1.1");
+	value = egg_array_float_guassian_value (0.0, 1.1);
+	if (fabs (value - 0.36267) < 0.0001)
+		egg_test_success (test, "got correct gaussian");
+	else
+		egg_test_failed (test, "got wrong gaussian (%f)", value);
+
+	/************************************************************/
+	egg_test_title (test, "get gaussian 0.5, sigma 1.1");
+	value = egg_array_float_guassian_value (0.5, 1.1);
+	if (fabs (value - 0.32708) < 0.0001)
+		egg_test_success (test, "got correct gaussian");
+	else
+		egg_test_failed (test, "got wrong gaussian (%f)", value);
+
+	/************************************************************/
+	egg_test_title (test, "get gaussian 1.0, sigma 1.1");
+	value = egg_array_float_guassian_value (1.0, 1.1);
+	if (fabs (value - 0.23991) < 0.0001)
 		egg_test_success (test, "got correct gaussian");
 	else
 		egg_test_failed (test, "got wrong gaussian (%f)", value);
 
 	/************************************************************/
-	egg_test_title (test, "get gaussian 1.0, sigma 1.0");
-	value = egg_array_float_guassian_value (1.0, 1.0);
-	if (value - 0.241971 < 0.0001)
+	egg_test_title (test, "get gaussian 0.5, sigma 4.5");
+	value = egg_array_float_guassian_value (0.5, 4.5);
+	if (fabs (value - 0.088108) < 0.0001)
 		egg_test_success (test, "got correct gaussian");
 	else
 		egg_test_failed (test, "got wrong gaussian (%f)", value);
 
 	/************************************************************/
+	size = 5;
+	sigma = 1.1;
+	egg_test_title (test, "get inprecise gaussian array (%i), sigma %f", size, sigma);
+	kernel = egg_array_float_compute_gaussian (size, sigma);
+	if (kernel == NULL) 
+		egg_test_success (test, NULL);
+	else {
+		egg_test_failed (test, "got gaussian array length (%i)", array->len);
+		egg_array_float_print (kernel);
+	}
+
+	/************************************************************/
 	size = 9;
 	sigma = 1.1;
-	egg_test_title (test, "get gaussian array (%i), sigma %f", size, sigma);
+	egg_test_title (test, "get gaussian-9 array (%i), sigma %f", size, sigma);
 	kernel = egg_array_float_compute_gaussian (size, sigma);
 	if (kernel != NULL && kernel->len == size) 
 		egg_test_success (test, "got correct length gaussian array");
 	else
 		egg_test_failed (test, "got gaussian array length (%i)", array->len);
+	egg_array_float_print (kernel);
 
 	/************************************************************/
 	egg_test_title (test, "make sure we get an accurate gaussian");
@@ -343,7 +534,6 @@
 		egg_test_success (test, "got sum (%f)", value);
 	else
 		egg_test_failed (test, "got wrong sum (%f)", value);
-	egg_array_float_print (kernel);
 
 	/************************************************************/
 	egg_test_title (test, "make sure we get get and set");
@@ -355,11 +545,20 @@
 		egg_test_failed (test, "got wrong value (%f)", value);
 	egg_array_float_print (array);
 
-
 	/************************************************************/
 	egg_test_title (test, "make sure we get the correct array sum (2)");
+	egg_array_float_set (array, 0, 20.0);
+	egg_array_float_set (array, 1, 44.0);
+	egg_array_float_set (array, 2, 45.0);
+	egg_array_float_set (array, 3, 89.0);
+	egg_array_float_set (array, 4, 100.0);
+	egg_array_float_set (array, 5, 12.0);
+	egg_array_float_set (array, 6, 76.0);
+	egg_array_float_set (array, 7, 78.0);
+	egg_array_float_set (array, 8, 1.20);
+	egg_array_float_set (array, 9, 3.0);
 	value = egg_array_float_sum (array);
-	if (value == 100.0)
+	if (fabs (value - 468.2) < 0.0001f)
 		egg_test_success (test, "got correct sum");
 	else
 		egg_test_failed (test, "got wrong sum (%f)", value);

Modified: trunk/src/egg-array-float.h
==============================================================================
--- trunk/src/egg-array-float.h	(original)
+++ trunk/src/egg-array-float.h	Thu Jan 22 14:07:53 2009
@@ -46,6 +46,8 @@
 void	 egg_array_float_set				(EggArrayFloat	*array,
 							 guint		 i,
 							 gfloat		 value);
+EggArrayFloat *
+egg_array_float_remove_outliers (EggArrayFloat *data, guint length, gfloat sigma);
 
 G_END_DECLS
 

Modified: trunk/src/gpm-self-test.c
==============================================================================
--- trunk/src/gpm-self-test.c	(original)
+++ trunk/src/gpm-self-test.c	Thu Jan 22 14:07:53 2009
@@ -31,6 +31,7 @@
 void egg_precision_test (EggTest *test);
 void egg_discrete_test (EggTest *test);
 void egg_color_test (EggTest *test);
+void egg_array_float_test (EggTest *test);
 
 void gpm_common_test (EggTest *test);
 void gpm_cell_unit_test (EggTest *test);
@@ -62,6 +63,7 @@
 	egg_precision_test (test);
 	egg_discrete_test (test);
 	egg_color_test (test);
+	egg_array_float_test (test);
 
 	gpm_common_test (test);
 #ifndef HAVE_DK_POWER

Modified: trunk/src/gpm-statistics.c
==============================================================================
--- trunk/src/gpm-statistics.c	(original)
+++ trunk/src/gpm-statistics.c	Thu Jan 22 14:07:53 2009
@@ -55,7 +55,7 @@
 static const gchar *stats_type;
 static guint history_time;
 static GConfClient *gconf_client;
-static EggArrayFloat *gaussian = NULL;
+static gfloat sigma_smoothing = 0.0f;
 
 enum {
 	GPM_INFO_COLUMN_TEXT,
@@ -182,6 +182,8 @@
 	EggObjList *new;
 	EggArrayFloat *raw;
 	EggArrayFloat *convolved;
+	EggArrayFloat *outliers;
+	EggArrayFloat *gaussian = NULL;
 
 	/* convert the y data to a EggArrayFloat array */
 	raw = egg_array_float_new (list->len);
@@ -191,8 +193,12 @@
 		egg_array_float_set (raw, i, point->y);
 	}
 
+	/* remove any outliers */
+	outliers = egg_array_float_remove_outliers (raw, 3, 0.1);
+
 	/* convolve with gaussian */
-	convolved = egg_array_float_convolve (raw, gaussian);
+	gaussian = egg_array_float_compute_gaussian (11, sigma_smoothing);
+	convolved = egg_array_float_convolve (outliers, gaussian);
 
 	/* add the smoothed data back into a new array */
 	new = egg_obj_list_new ();
@@ -207,8 +213,10 @@
 	}
 
 	/* free data */
+	egg_array_float_free (gaussian);
 	egg_array_float_free (raw);
 	egg_array_float_free (convolved);
+	egg_array_float_free (outliers);
 
 	return new;
 }
@@ -443,6 +451,8 @@
 		dkp_point_obj_free (point);
 	}
 
+	/* render */
+	sigma_smoothing = 2.0;
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_smooth_history");
 	checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_points_history");
@@ -522,6 +532,7 @@
 	}
 
 	/* render */
+	sigma_smoothing = 1.1;
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_smooth_stats");
 	checked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 	widget = glade_xml_get_widget (glade_xml, "checkbutton_points_stats");
@@ -1034,9 +1045,6 @@
 	/* get data from gconf */
 	gconf_client = gconf_client_get_default ();
 
-	/* create the gaussian dataset */
-	gaussian = egg_array_float_compute_gaussian (35, 4.5);
-
 	/* add application specific icons to search path */
 	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
                                            GPM_DATA G_DIR_SEPARATOR_S "icons");
@@ -1235,7 +1243,6 @@
 	gtk_main ();
 
 out:
-	egg_array_float_free (gaussian);
 	g_object_unref (gconf_client);
 	g_object_unref (client);
 	g_object_unref (glade_xml);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]