Added code to calculate the histogram limits
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 4 Dec 2004 09:20:59 +0000 (09:20 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 4 Dec 2004 09:20:59 +0000 (09:20 +0000)
po/pspp.pot
src/ChangeLog
src/chart.c
src/chart.h
src/factor_stats.c
src/frequencies.q
src/histogram.c

index 0f5739fe90f65964932c69bebd71d6ad4e97c399..a74ef27a9c83735b018937a073b1755bdbfb4cd7 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2004-12-02 13:38+0800\n"
+"POT-Creation-Date: 2004-12-02 19:27+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index 3ff990821c0895f8e5b46cac6699848fd7de29c0..8ccbc7ccfa78c4fc2fb5afe0cd907d1cea5a6a93 100644 (file)
@@ -1,3 +1,9 @@
+Sat Dec  4 17:14:45 WST 2004 John Darrington <john@darrington.wattle.id.au>
+
+       * histogram.c chart.[ch] factor_stats.c frequencies.q
+
+       Added code to calculate sensible histogram ranges and limits.
+
 Thu Dec  2 13:37:43 WST 2004 John Darrington <john@darrington.wattle.id.au>
 
        * chart.h Updated to reflect many API changes.
index 3068f3e3ed96ee4299335d61f65e5e7a765b830d..07111ad925b8c864301a42768f54c5b5209d9870 100644 (file)
@@ -183,12 +183,9 @@ chart_finalise(struct chart *chart)
 
 
 
-static double chart_rounded_tick(double tick);
-
-  
 /* Adjust tick to be a sensible value 
    ie:  ... 0.1,0.2,0.5,   1,2,5,  10,20,50 ... */
-static double
+double
 chart_rounded_tick(double tick)
 {
 
index d22c394fdb21a0a21864fcaa26c5c24b5ec5d079..f2c9e501471151cc7282864f05bda72748070e4f 100644 (file)
@@ -77,6 +77,7 @@ int  chart_initialise(struct chart *ch);
 void chart_finalise(struct chart *ch);
 
 
+double chart_rounded_tick(double tick);
 
 void chart_write_xlabel(struct chart *ch, const char *label);
 void chart_write_ylabel(struct chart *ch, const char *label);
@@ -118,10 +119,19 @@ struct normal_curve
 void histogram_write_legend(struct chart *ch, const struct normal_curve *norm);
 
 
+/* Plot a gsl_histogram */
 void histogram_plot(const gsl_histogram *hist, const char *factorname,
                    const struct normal_curve *norm, short show_normal);
 
 
+/* Create a gsl_histogram and set it's parameters based upon 
+   x_min, x_max and bins. 
+   The caller is responsible for freeing the histogram.
+*/
+gsl_histogram * histogram_create(double bins, double x_min, double x_max) ;
+
+
+
 
 
 struct slice {
@@ -158,6 +168,7 @@ void chart_datum(struct chart *ch, int dataset, double x, double y);
 
 
 
+
 enum CHART_DIM
   {
     CHART_DIM_X,
index 2b9c48a6bd01a3e8ff5f0eeb84b2944977ac3ef4..2ba785a7d8e8c7044b2f42fa3ff2c94f96124d02 100644 (file)
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include <math.h>
 #include <float.h>
 #include <assert.h>
-
+#include <chart.h>
 
 
 void
@@ -52,7 +52,7 @@ metrics_precalc(struct metrics *m)
                                (hsh_free_func *) weighted_value_free,
                                (void *) 0);
 
-  m->histogram = gsl_histogram_alloc(10);
+
 
 }
 
@@ -191,8 +191,7 @@ metrics_postcalc(struct metrics *m)
   m->trimmed_mean += (m->wvp[k1 + 1]->cc - tc) * m->wvp[k1 + 1]->v.f ;
   m->trimmed_mean /= 0.9 * m->n ;
 
-
-  gsl_histogram_set_ranges_uniform(m->histogram, m->min, m->max);
+  m->histogram = histogram_create(10, m->min, m->max);
 
   for ( i = 0 ; i < m->n_data ; ++i ) 
     {
index 1484776acb9b40ab4ea983d3c61eb12c2293f753..acfeed86d3c65e2327e2b364def9b0778df614d9 100644 (file)
@@ -279,7 +279,9 @@ static hsh_compare_func compare_freq_numeric_d, compare_freq_alpha_d;
 static void do_piechart(const struct variable *var,
                        const struct freq_tab *frq_tab);
 
-void freq_tab_to_hist(const struct freq_tab *ft, gsl_histogram *hist);
+gsl_histogram * 
+freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var);
+
 
 \f
 /* Parser and outline. */
@@ -629,16 +631,16 @@ postcalc (void *aux UNUSED)
        {
          double d[frq_n_stats];
          struct normal_curve norm;
+         gsl_histogram *hist ;
 
-         gsl_histogram *hist = gsl_histogram_alloc(7);
 
-         norm.N = vf->tab.total_cases;
+         norm.N = vf->tab.valid_cases;
 
          calc_stats(v,d);
          norm.mean = d[frq_mean];
          norm.stddev = d[frq_stddev];
 
-         freq_tab_to_hist(ft, hist);
+         hist = freq_tab_to_hist(ft,v);
 
          histogram_plot(hist, var_to_string(v), &norm, normal);
 
@@ -1537,33 +1539,32 @@ dump_statistics (struct variable *v, int show_varname)
 }
 
 
-
-/* Populate a gsl_histogram from a freq_tab */
-void
-freq_tab_to_hist(const struct freq_tab *ft, gsl_histogram *hist)
+/* Create a gsl_histogram from a freq_tab */
+gsl_histogram *
+freq_tab_to_hist(const struct freq_tab *ft, const struct variable *var)
 {
   int i;
   double x_min = DBL_MAX;
   double x_max = -DBL_MAX;
-  
+
+  gsl_histogram *hist;
+  const double bins = 11;
+
   struct hsh_iterator hi;
   struct hsh_table *fh = ft->data;
   struct freq *frq;
 
-  gsl_histogram_reset(hist);
-
   /* Find out the extremes of the x value */
-
-  for ( frq = hsh_first(fh, &hi); 
-       frq != 0; 
-       frq = hsh_next(fh, &hi) ) 
+  for ( frq = hsh_first(fh, &hi); frq != 0; frq = hsh_next(fh, &hi) ) 
     {
+      if ( is_missing(&frq->v, var))
+       continue;
+
       if ( frq->v.f < x_min ) x_min = frq->v.f ;
       if ( frq->v.f > x_max ) x_max = frq->v.f ;
     }
 
-
-  gsl_histogram_set_ranges_uniform(hist, x_min, x_max);
+  hist = histogram_create(bins, x_min, x_max);
 
   for( i = 0 ; i < ft->n_valid ; ++i ) 
     {
@@ -1571,8 +1572,10 @@ freq_tab_to_hist(const struct freq_tab *ft, gsl_histogram *hist)
       gsl_histogram_accumulate(hist, frq->v.f, frq->c);
     }
 
+  return hist;
 }
 
+
 static struct slice *
 freq_tab_to_slice_array(const struct freq_tab *frq_tab, 
                        const struct variable *var,
@@ -1602,10 +1605,8 @@ freq_tab_to_slice_array(const struct freq_tab *frq_tab,
       slices[i].label = value_to_string(&frq->v, var);
 
       slices[i].magnetude = frq->c;
-
     }
 
-
   return slices;
 }
 
@@ -1622,11 +1623,8 @@ do_piechart(const struct variable *var, const struct freq_tab *frq_tab)
   piechart_plot(var_to_string(var), slices, n_slices);
 
   free(slices);
-  
 }
 
-
-
 /* 
    Local Variables:
    mode: c
index 0d90edd5ec0db23b49039fe20003592dad0413ff..9a3b9264acaa063fa659610257f9bd4d759d660a 100644 (file)
@@ -23,6 +23,7 @@
 #include <plot.h>
 #include <math.h>
 #include <gsl/gsl_histogram.h>
+#include <gsl/gsl_randist.h>
 #include <assert.h>
 
 #include "hash.h"
 #include "var.h"
 #include "chart.h"
 
-/* Number of bins in which to divide data */
-#define BINS 7
-
-/* The approximate no of ticks on the y axis */
-#define YTICKS 10
-
-#ifndef M_PI 
-#define M_PI ( 22.0 / 7.0 )
-#endif
-
-
-static double gaussian(double x, double mu, double sigma ) ;
-
-
-static double
-gaussian(double x, double mu, double sigma )
-{
-  return (exp( - (( x - mu )* (x - mu) / (2.0 * sigma * sigma)  ))
-    / ( sigma * sqrt( M_PI * 2.0) ))  ;
-}
-
-
-
 /* Write the legend of the chart */
 void
 histogram_write_legend(struct chart *ch, const struct normal_curve *norm)
@@ -116,7 +94,6 @@ hist_draw_bar(struct chart *ch, const gsl_histogram *hist, int bar)
            x_pos + width / 2.0, buf);
   }
 
-
 }
 
 
@@ -155,11 +132,13 @@ histogram_plot(const gsl_histogram *hist,
     double x_min, x_max, not_used ;
     double abscissa_scale ;
     double ordinate_scale ;
-
+    double range ;
 
     gsl_histogram_get_range(hist, 0, &x_min, &not_used);
-    gsl_histogram_get_range(hist, bins - 1, &x_max, &not_used);
-    
+    range = not_used - x_min;
+    gsl_histogram_get_range(hist, bins - 1, &not_used, &x_max);
+    assert(range == x_max - not_used);
+
     abscissa_scale = (ch.data_right - ch.data_left) / (x_max - x_min);
     ordinate_scale = (ch.data_top - ch.data_bottom) / 
       gsl_histogram_max_val(hist) ;
@@ -170,11 +149,11 @@ histogram_plot(const gsl_histogram *hist,
         d += (ch.data_right - ch.data_left) / 100.0)
       {    
        const double x = (d - ch.data_left) / abscissa_scale + x_min ; 
-       
-       pl_fcont_r(ch.lp,  d, 
-                  ch.data_bottom  + norm->N * ordinate_scale *
-                  gaussian(x, norm->mean, norm->stddev) 
-                  );
+       const double y = norm->N * range * 
+         gsl_ran_gaussian_pdf(x - norm->mean, norm->stddev);
+
+       pl_fcont_r(ch.lp,  d,  ch.data_bottom  + y * ordinate_scale);
+
       }
     pl_endpath_r(ch.lp);
 
@@ -182,3 +161,32 @@ histogram_plot(const gsl_histogram *hist,
   chart_finalise(&ch);
 }
 
+
+gsl_histogram *
+histogram_create(double bins, double x_min, double x_max)
+{
+  int n;
+  double bin_width ;
+  double bin_width_2 ;
+  double upper_limit, lower_limit;
+
+  gsl_histogram *hist = gsl_histogram_alloc(bins);
+
+
+  bin_width = chart_rounded_tick((x_max - x_min)/ bins);
+  bin_width_2 = bin_width / 2.0;
+    
+  n =  ceil( x_max / (bin_width_2) ) ; 
+  if ( ! (n % 2 ) ) n++;
+  upper_limit = n * bin_width_2;
+
+  n =  floor( x_min / (bin_width_2) ) ; 
+  if ( ! (n % 2 ) ) n--;
+  lower_limit = n * bin_width_2;
+
+  gsl_histogram_set_ranges_uniform(hist, lower_limit, upper_limit);
+
+
+  return hist;
+}
+