Added an optional --without-libplot flag to configure
authorJohn Darrington <john@darrington.wattle.id.au>
Fri, 7 Jan 2005 00:17:19 +0000 (00:17 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Fri, 7 Jan 2005 00:17:19 +0000 (00:17 +0000)
16 files changed:
ChangeLog
configure.ac
po/en_GB.po
po/pspp.pot
pref.h.orig
src/ChangeLog
src/Makefile.am
src/chart.c
src/chart.h
src/examine.q
src/frequencies.q
src/histogram.c
src/histogram.h [new file with mode: 0644]
src/piechart.c
src/plot-chart.c [new file with mode: 0644]
src/plot-hist.c [new file with mode: 0644]

index 347e81ca9bb21eadc9f9a69482b044d2d98c231e..fb7208f55219e9761bc1787664a18738e1c1378e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Jan  7 08:01:02 WST 2005 John Darrington <john@darrington.wattle.id.au> 
+
+       * configure.ac pref.h.orig: Compilation with libplot is now optional
+       by sacrificing the chart features.
+
 Sun Nov 28 19:24:02 2004  Ben Pfaff  <blp@gnu.org>
 
        * Smake: Change -a to -pR in cp invocations for SUSv3 compliance.
index 7921bcc345025de9b01a823645cbd76b31711801..49f3a0b321a88051c1bc9c080cc351ac492efb0c 100644 (file)
@@ -22,6 +22,16 @@ dnl Checks for libraries.
 AC_SYS_LARGEFILE
 AC_FUNC_FSEEKO
 AC_CHECK_LIB(m, sin)
+AC_ARG_WITH(libplot, [  --without-libplot         don't compile in support of charts (using libplot)])
+
+if test x"$with_libplot" != x"no" ; then 
+       AC_CHECK_LIB(plot, pl_newpl_r,,
+         AC_MSG_ERROR([You must install libplot (or use --without-libplot)])
+       )
+fi
+AM_CONDITIONAL(WITHCHARTS, test x"$with_libplot" != x"no")
+
+
 AC_CHECK_LIB(gmp, mpf_get_str,,
        AC_CHECK_LIB(gmp, __gmpf_get_str,,
           AC_MSG_ERROR([You must install libgmp])
index defa88591af0ec1ff499c56e30a5467cdb6e0a9a..726a6be8747d933a82547086bce4dfe859aa6b78 100644 (file)
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.3.1\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2005-01-05 22:50+0800\n"
+"POT-Creation-Date: 2005-01-06 13:08+0800\n"
 "PO-Revision-Date: 2004-01-23 13:04+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
index 7cf0a1d61ba57bde05c4c13ae6488b250b24c814..8a01629b080ff78500108cb5d9463b33618444cb 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: 2005-01-05 22:50+0800\n"
+"POT-Creation-Date: 2005-01-06 13:08+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 6ae2299720c115667a136d430f554b796aad1d81..ed5c53fe44c4e1432a9642d039885aa5b37b9de9 100644 (file)
 #define GLOBAL_DEBUGGING 1
 #endif
 
+#if !HAVE_LIBPLOT
+#define NO_CHARTS 1
+#endif
+
 /* Define these if DEBUGGING is off and you want to make certain
    additional optimizations. */
 #if !DEBUGGING
index 3f3e65bc6a8d5ff6f0e463a9c54982f14f3a5190..b3548aa2b64f6f5ab80a9c455ddc689a86febc82 100644 (file)
@@ -1,3 +1,13 @@
+Fri Jan  7 08:00:05 WST 2005 John Darrington <john@darrington.wattle.id.au>
+
+       * Makefile.am chart.[ch]  histogram.[ch] piechart.c (Modified);
+          plot-hist.c plot-chart.c (Added) Reorganised these files in an
+          attempt to seperate the creation and processing of charts from their
+          actuall renedering.
+
+        * examine.q frequencies.q generated charts conditional upon the NO_CHARTS
+          macro.
+
 Thu Jan  6 18:48:58 WST 2005 John Darrington <john@darrington.wattle.id.au>
 
        * main.c Added a signal handler for SIGFPE
index 1afb336efb407a1000d63fa50a08f9a8b0bf9b07..354c320390e610da40559b78b89ab400d7c5e7ef 100644 (file)
@@ -48,10 +48,20 @@ frequencies.c list.c means.c oneway.c set.c  t-test.c
 q_sources_q = correlations.q crosstabs.q examine.q file-handle.q       \
 frequencies.q list.q means.q oneway.q set.q  t-test.q
 
-pspp_SOURCES = $(q_sources_c) aggregate.c algorithm.c algorithm.h      \
+if WITHCHARTS
+chart_sources = barchart.c \
+       box-whisker.c \
+       cartesian.c \
+       plot-chart.c \
+       plot-hist.c \
+       piechart.c 
+endif
+
+pspp_SOURCES = $(q_sources_c) $(chart_sources) \
+aggregate.c algorithm.c algorithm.h    \
 alloc.c alloc.h apply-dict.c ascii.c autorecode.c bitvector.h          \
-case.c case.h \
-casefile.c casefile.h cmdline.c cmdline.h command.c command.def                \
+case.c case.h casefile.c casefile.h chart.c  chart.h  \
+cmdline.c cmdline.h command.c command.def              \
 command.h compute.c copyleft.c copyleft.h count.c data-in.c data-in.h  \
 data-list.c data-list.h data-out.c date.c debug-print.h descript.c     \
 devind.c devind.h dfm-read.c dfm-read.h dfm-write.c dfm-write.h        \
@@ -61,7 +71,8 @@ factor_stats.c factor_stats.h file-handle.h   \
 file-type.c filename.c filename.h flip.c font.h format.c format.def    \
 format.h formats.c get.c getline.c getline.h glob.c glob.h             \
 groff-font.c group.c group.h group_proc.h \
-hash.c hash.h html.c htmlP.h include.c inpt-pgm.c lexer.c      \
+hash.c hash.h histogram.c histogram.h \
+html.c htmlP.h include.c inpt-pgm.c lexer.c    \
 lexer.h levene.c levene.h log.h loop.c magic.c magic.h main.c main.h   \
 matrix-data.c mis-val.c misc.c misc.h modify-vars.c                    \
 moments.c moments.h numeric.c output.c output.h \
@@ -76,14 +87,8 @@ split-file.c str.c str.h subclist.c subclist.h \
 sysfile-info.c tab.c tab.h temporary.c stat.h \
 title.c  val.h val-labs.c value-labels.c value-labels.h                \
 var-labs.c var.h vars-atr.c vars-prs.c vector.c version.c version.h    \
-vfm.c vfm.h vfmP.h weight.c \
-barchart.c \
-box-whisker.c \
-cartesian.c \
-chart.c \
-chart.h \
-histogram.c \
-piechart.c 
+vfm.c vfm.h vfmP.h weight.c 
+
 
 pspp_LDADD = ../lib/julcal/libjulcal.a         \
        ../lib/misc/libmisc.a                   \
index 07111ad925b8c864301a42768f54c5b5209d9870..178788255744468d36aa3b42cfb3916b9343f989 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-#include <config.h>
-#include <stdio.h>
-#include <plot.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <float.h>
-#include <assert.h>
+
 #include <math.h>
+#include <float.h>
 
 #include "chart.h"
-#include "str.h"
-
-
-const char *data_colour[] = {
-  "brown",
-  "red",
-  "orange",
-  "yellow",
-  "green",
-  "blue",
-  "violet",
-  "grey",
-  "pink"
-};
-
-
-
-int
-chart_initialise(struct chart *chart)
-{
-
-  chart->pl_params = pl_newplparams();
-
-  chart->lp = pl_newpl_r ("X",0,stdout,stderr,chart->pl_params);
-
-  if (pl_openpl_r (chart->lp) < 0)      /* open Plotter */
-      return 1;
-
-  pl_fspace_r (chart->lp, 0.0, 0.0, 1000.0, 1000.0); /* set coordinate system */
-  pl_flinewidth_r (chart->lp, 0.25);    /* set line thickness */
-  pl_pencolorname_r (chart->lp, "black"); 
-
-  pl_erase_r (chart->lp);               /* erase graphics display */
-  pl_filltype_r(chart->lp,0);
-
-
-
-  pl_savestate_r(chart->lp);
-
-  /* Set default chartetry */
-  chart->data_top =   900;
-  chart->data_right = 800;
-  chart->data_bottom = 120;
-  chart->data_left = 150;
-  chart->abscissa_top = 70;
-  chart->ordinate_right = 120;
-  chart->title_bottom = 920;
-  chart->legend_left = 810;
-  chart->legend_right = 1000;
-  chart->font_size = 0;
-  strcpy(chart->fill_colour,"red");
-
-
-  /* Get default font size */
-  if ( !chart->font_size) 
-    chart->font_size = pl_fontsize_r(chart->lp, -1);
-
-  /* Draw the data area */
-  pl_box_r(chart->lp, 
-          chart->data_left, chart->data_bottom, 
-          chart->data_right, chart->data_top);
-
-  return 0;
-
-}
-
-
-
-/* Draw a tick mark at position
-   If label is non zero, then print it at the tick mark
-*/
-void
-draw_tick(struct chart *chart, 
-         enum tick_orientation orientation, 
-         double position, 
-         const char *label, ...)
-{
-  const int tickSize = 10;
-
-  pl_savestate_r(chart->lp);
-
-  pl_move_r(chart->lp, chart->data_left, chart->data_bottom);
-
-  if ( orientation == TICK_ABSCISSA ) 
-    pl_flinerel_r(chart->lp, position, 0, position, -tickSize);
-  else if (orientation == TICK_ORDINATE ) 
-      pl_flinerel_r(chart->lp, 0, position, -tickSize, position);
-  else
-    assert(0);
-
-  if ( label ) {
-    char buf[10];
-    va_list ap;
-    va_start(ap,label);
-    vsnprintf(buf,10,label,ap);
-
-    if ( orientation == TICK_ABSCISSA ) 
-      pl_alabel_r(chart->lp, 'c','t', buf);
-    else if (orientation == TICK_ORDINATE ) 
-      {
-       if ( fabs(position) < DBL_EPSILON )
-           pl_moverel_r(chart->lp, 0, 10);
-
-       pl_alabel_r(chart->lp, 'r','c', buf);
-      }
-
-    va_end(ap);
-  }
-    
-  pl_restorestate_r(chart->lp);
-}
-
-
-
-
-/* Write the title on a chart*/
-void  
-chart_write_title(struct chart *chart, const char *title, ...)
-{
-  va_list ap;
-  char buf[100];
-
-  pl_savestate_r(chart->lp);
-  pl_ffontsize_r(chart->lp,chart->font_size * 1.5);
-  pl_move_r(chart->lp,chart->data_left, chart->title_bottom);
-
-  va_start(ap,title);
-  vsnprintf(buf,100,title,ap);
-  pl_alabel_r(chart->lp,0,0,buf);
-  va_end(ap);
-
-  pl_restorestate_r(chart->lp);
-}
-
-
-
-void
-chart_finalise(struct chart *chart)
-{
-  pl_restorestate_r(chart->lp);
-
-  if (pl_closepl_r (chart->lp) < 0)     /* close Plotter */
-    {
-      fprintf (stderr, "Couldn't close Plotter\n");
-    }
-
-
-  pl_deletepl_r(chart->lp);
-
-  pl_deleteplparams(chart->pl_params);
-
-}
-
-
 
 /* Adjust tick to be a sensible value 
    ie:  ... 0.1,0.2,0.5,   1,2,5,  10,20,50 ... */
@@ -213,51 +53,3 @@ chart_rounded_tick(double tick)
     
 }
 
-
-/* Set the scale for the abscissa */
-void 
-chart_write_xscale(struct chart *ch, double min, double max, int ticks)
-{
-  double x;
-
-  const double tick_interval = 
-    chart_rounded_tick( (max - min) / (double) ticks);
-
-  ch->x_max = ceil( max / tick_interval ) * tick_interval ; 
-  ch->x_min = floor ( min / tick_interval ) * tick_interval ;
-
-  ch->abscissa_scale = fabs(ch->data_right - ch->data_left) / 
-    fabs(ch->x_max - ch->x_min);
-
-  for(x = ch->x_min ; x <= ch->x_max; x += tick_interval )
-    {
-      draw_tick (ch, TICK_ABSCISSA, 
-                (x - ch->x_min) * ch->abscissa_scale, "%g", x);
-    }
-
-}
-
-
-/* Set the scale for the ordinate */
-void 
-chart_write_yscale(struct chart *ch, double smin, double smax, int ticks)
-{
-  double y;
-
-  const double tick_interval = 
-    chart_rounded_tick( (smax - smin) / (double) ticks);
-
-  ch->y_max = ceil  ( smax / tick_interval ) * tick_interval ; 
-  ch->y_min = floor ( smin / tick_interval ) * tick_interval ;
-
-  ch->ordinate_scale = 
-    fabs(ch->data_top -  ch->data_bottom) / fabs(ch->y_max - ch->y_min) ;
-
-  for(y = ch->y_min ; y <= ch->y_max; y += tick_interval )
-    {
-    draw_tick (ch, TICK_ORDINATE, 
-              (y - ch->y_min) * ch->ordinate_scale, "%g", y);
-    }
-
-}
-
index eec5bff5b847a1d6d3b679c28156919c1b8651bd..8d1a914691f7cfae70589aa27408ef15966de123 100644 (file)
 #ifndef CHART_H
 #define CHART_H
 
+#include <config.h>
 #include <stdio.h>
-#include <plot.h>
 #include <gsl/gsl_histogram.h>
-
 #include "var.h"
 
+#ifndef NO_CHARTS
+#include <plot.h>
+#endif
+
 
 /* Array of standard colour names */
 extern const char *data_colour[];
@@ -34,8 +37,10 @@ extern const char *data_colour[];
 
 struct chart {
 
+#ifndef NO_CHARTS
   plPlotter *lp ;
   plPlotterParams *pl_params;
+#endif
 
   /* The geometry of the chart 
      See diagram at the foot of this file.
index 5cb89af2ab58cdb368da64f154d1d77999376862..517b24f9b4b22329229084ade60461b2c7db989e 100644 (file)
@@ -264,6 +264,7 @@ output_examine(void)
                                   cmd.v_id);
            }
 
+#ifndef NO_CHARTS
          if ( cmd.a_plot[XMN_PLT_HISTOGRAM] ) 
            {
              for ( v = 0 ; v < n_dependent_vars; ++v ) 
@@ -279,6 +280,7 @@ output_examine(void)
                                 &normal, 0);
                }
            }
+#endif
 
        }
 
@@ -330,6 +332,7 @@ output_examine(void)
                  if ( cmd.a_plot[XMN_PLT_NPPLOT] ) 
                    np_plot(&(*fs)->m[v], s);
 
+#ifndef NO_CHARTS
                  if ( cmd.a_plot[XMN_PLT_HISTOGRAM] ) 
                    {
                      struct normal_curve normal;
@@ -341,6 +344,7 @@ output_examine(void)
                      histogram_plot((*fs)->m[v].histogram, 
                                     s,  &normal, 0);
                    }
+#endif
                  
                } /* for ( fs .... */
 
@@ -1626,6 +1630,7 @@ box_plot_variables(const struct factor *fctr,
                   struct variable **vars, int n_vars, 
                   const struct variable *id)
 {
+#ifndef NO_CHARTS
   int i;
   struct factor_statistics **fs ;
 
@@ -1675,7 +1680,7 @@ box_plot_variables(const struct factor *fctr,
       chart_finalise(&ch);
 
     }
-
+#endif
 }
 
 
@@ -1689,6 +1694,7 @@ box_plot_group(const struct factor *fctr,
               int n_vars,
               const struct variable *id)
 {
+#ifndef NO_CHARTS
   int i;
 
   for ( i = 0 ; i < n_vars ; ++i ) 
@@ -1743,7 +1749,7 @@ box_plot_group(const struct factor *fctr,
 
       chart_finalise(&ch);
     }
-
+#endif
 }
 
 
@@ -1752,6 +1758,7 @@ box_plot_group(const struct factor *fctr,
 void
 np_plot(const struct metrics *m, const char *factorname)
 {
+#ifndef NO_CHARTS
   int i;
   double yfirst=0, ylast=0;
 
@@ -1830,7 +1837,7 @@ np_plot(const struct metrics *m, const char *factorname)
 
   chart_finalise(&np_chart);
   chart_finalise(&dnp_chart);
-
+#endif
 }
 
 
index acfeed86d3c65e2327e2b364def9b0778df614d9..b5da79bde62b83545e563e5bbd0fde8a5bde8171 100644 (file)
@@ -627,6 +627,7 @@ postcalc (void *aux UNUSED)
        dump_statistics (v, !dumped_freq_tab);
 
 
+#ifndef NO_CHARTS
       if ( chart == GFT_HIST) 
        {
          double d[frq_n_stats];
@@ -652,6 +653,7 @@ postcalc (void *aux UNUSED)
        {
          do_piechart(v_variables[i], ft);
        }
+#endif
 
 
       cleanup_freq_tab (v);
@@ -1612,6 +1614,7 @@ freq_tab_to_slice_array(const struct freq_tab *frq_tab,
 
 
 
+#ifndef NO_CHARTS
 static void
 do_piechart(const struct variable *var, const struct freq_tab *frq_tab)
 {
@@ -1624,6 +1627,7 @@ do_piechart(const struct variable *var, const struct freq_tab *frq_tab)
 
   free(slices);
 }
+#endif
 
 /* 
    Local Variables:
index 9a3b9264acaa063fa659610257f9bd4d759d660a..f334745647b62793239e62f4d4c4fc9d77531b77 100644 (file)
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA. */
 
-#include <config.h>
-
-#include <stdio.h>
-#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 "histogram.h"
 #include "chart.h"
 
-/* Write the legend of the chart */
-void
-histogram_write_legend(struct chart *ch, const struct normal_curve *norm)
-{
-  char buf[100];
-  pl_savestate_r(ch->lp);
-
-  sprintf(buf,"N = %.2f",norm->N);
-  pl_move_r(ch->lp, ch->legend_left, ch->data_bottom);
-  pl_alabel_r(ch->lp,0,'b',buf);
-
-  sprintf(buf,"Mean = %.1f",norm->mean);
-  pl_fmove_r(ch->lp,ch->legend_left,ch->data_bottom + ch->font_size * 1.5);
-  pl_alabel_r(ch->lp,0,'b',buf);
-
-  sprintf(buf,"Std. Dev = %.2f",norm->stddev);
-  pl_fmove_r(ch->lp,ch->legend_left,ch->data_bottom + ch->font_size * 1.5 * 2);
-  pl_alabel_r(ch->lp,0,'b',buf);
-
-  pl_restorestate_r(ch->lp);    
-}
-
-static void hist_draw_bar(struct chart *ch, const gsl_histogram *hist, int bar);
-
-
-static void
-hist_draw_bar(struct chart *ch, const gsl_histogram *hist, int bar)
-{
-  double upper;
-  double lower;
-  double height;
-
-  const size_t bins = gsl_histogram_bins(hist);
-  const double x_pos = (ch->data_right - ch->data_left) * bar / (double) bins ;
-  const double width = (ch->data_right - ch->data_left) / (double) bins ;
-
-
-  assert ( 0 == gsl_histogram_get_range(hist, bar, &lower, &upper));
-
-  assert( upper >= lower);
-
-  height = gsl_histogram_get(hist, bar) * 
-    (ch->data_top - ch->data_bottom) / gsl_histogram_max_val(hist);
-
-  pl_savestate_r(ch->lp);
-  pl_move_r(ch->lp,ch->data_left, ch->data_bottom);
-  pl_fillcolorname_r(ch->lp, ch->fill_colour); 
-  pl_filltype_r(ch->lp,1);
-
-
-  pl_fboxrel_r(ch->lp,
-              x_pos, 0,
-              x_pos + width, height);
-
-  pl_restorestate_r(ch->lp);
-
-  {
-  char buf[5];
-  snprintf(buf,5,"%g",(upper + lower) / 2.0);
-  draw_tick(ch, TICK_ABSCISSA,
-           x_pos + width / 2.0, buf);
-  }
-
-}
-
-
-
-
-void
-histogram_plot(const gsl_histogram *hist,
-              const char *factorname,
-              const struct normal_curve *norm, short show_normal)
-{
-  int i;
-  int bins;
-  
-  struct chart ch;
-
-  bins = gsl_histogram_bins(hist);
-
-  chart_initialise(&ch);
-  chart_write_title(&ch, _("HISTOGRAM"));
-
-  chart_write_ylabel(&ch, _("Frequency"));
-  chart_write_xlabel(&ch, factorname);
-
-  chart_write_yscale(&ch, 0, gsl_histogram_max_val(hist), 5);
-
-  for ( i = 0 ; i < bins ; ++i ) 
-      hist_draw_bar(&ch, hist, i);
-
-  histogram_write_legend(&ch, norm);
-
-  if ( show_normal  )
-  {
-    /* Draw the normal curve */    
-
-    double d ;
-    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);
-    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) ;
-
-    pl_move_r(ch.lp, ch.data_left, ch.data_bottom);    
-    for( d = ch.data_left; 
-        d <= ch.data_right ; 
-        d += (ch.data_right - ch.data_left) / 100.0)
-      {    
-       const double x = (d - ch.data_left) / abscissa_scale + x_min ; 
-       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);
-
-  }
-  chart_finalise(&ch);
-}
-
 
 gsl_histogram *
 histogram_create(double bins, double x_min, double x_max)
diff --git a/src/histogram.h b/src/histogram.h
new file mode 100644 (file)
index 0000000..4f146b7
--- /dev/null
@@ -0,0 +1,28 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by John Darrington <john@darrington.wattle.id.au>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA. */
+
+#ifndef HISTOGRAM_H
+#define HISTOGRAM_H
+
+#include <gsl/gsl_histogram.h>
+
+
+gsl_histogram * histogram_create(double bins, double x_min, double x_max);
+
+#endif
index 53c2b5fdb56aa7273d5335e1270ae63c368ab0e8..35e5e0ba4d0ee8bb8a849eebdbe5913d8df679af 100644 (file)
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA. */
 
 
-#include <config.h>
+#include "config.h"
 #include "chart.h"
 #include <float.h>
 #include <assert.h>
@@ -47,6 +47,8 @@ draw_segment(struct chart *ch,
 
 
 
+#ifndef NO_CHARTS
+
 /* Draw a piechart */
 void
 piechart_plot(const char *title, const struct slice *slices, int n_slices)
@@ -208,3 +210,13 @@ draw_segment(struct chart *ch,
 
   pl_restorestate_r(ch->lp);
 }
+
+#else
+
+
+void
+piechart_plot(const char *title, const struct slice *slices, int n_slices)
+{
+}
+
+#endif
diff --git a/src/plot-chart.c b/src/plot-chart.c
new file mode 100644 (file)
index 0000000..ddbb360
--- /dev/null
@@ -0,0 +1,231 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by John Darrington <john@darrington.wattle.id.au>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA. */
+
+#include <config.h>
+#include <stdio.h>
+#include <plot.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <float.h>
+#include <assert.h>
+#include <math.h>
+
+#include "chart.h"
+#include "str.h"
+
+
+const char *data_colour[] = {
+  "brown",
+  "red",
+  "orange",
+  "yellow",
+  "green",
+  "blue",
+  "violet",
+  "grey",
+  "pink"
+};
+
+
+
+int
+chart_initialise(struct chart *chart)
+{
+
+  chart->pl_params = pl_newplparams();
+
+  chart->lp = pl_newpl_r ("X",0,stdout,stderr,chart->pl_params);
+
+  if (pl_openpl_r (chart->lp) < 0)      /* open Plotter */
+      return 1;
+
+  pl_fspace_r (chart->lp, 0.0, 0.0, 1000.0, 1000.0); /* set coordinate system */
+  pl_flinewidth_r (chart->lp, 0.25);    /* set line thickness */
+  pl_pencolorname_r (chart->lp, "black"); 
+
+  pl_erase_r (chart->lp);               /* erase graphics display */
+  pl_filltype_r(chart->lp,0);
+
+
+
+  pl_savestate_r(chart->lp);
+
+  /* Set default chartetry */
+  chart->data_top =   900;
+  chart->data_right = 800;
+  chart->data_bottom = 120;
+  chart->data_left = 150;
+  chart->abscissa_top = 70;
+  chart->ordinate_right = 120;
+  chart->title_bottom = 920;
+  chart->legend_left = 810;
+  chart->legend_right = 1000;
+  chart->font_size = 0;
+  strcpy(chart->fill_colour,"red");
+
+
+  /* Get default font size */
+  if ( !chart->font_size) 
+    chart->font_size = pl_fontsize_r(chart->lp, -1);
+
+  /* Draw the data area */
+  pl_box_r(chart->lp, 
+          chart->data_left, chart->data_bottom, 
+          chart->data_right, chart->data_top);
+
+  return 0;
+
+}
+
+
+
+/* Draw a tick mark at position
+   If label is non zero, then print it at the tick mark
+*/
+void
+draw_tick(struct chart *chart, 
+         enum tick_orientation orientation, 
+         double position, 
+         const char *label, ...)
+{
+  const int tickSize = 10;
+
+  pl_savestate_r(chart->lp);
+
+  pl_move_r(chart->lp, chart->data_left, chart->data_bottom);
+
+  if ( orientation == TICK_ABSCISSA ) 
+    pl_flinerel_r(chart->lp, position, 0, position, -tickSize);
+  else if (orientation == TICK_ORDINATE ) 
+      pl_flinerel_r(chart->lp, 0, position, -tickSize, position);
+  else
+    assert(0);
+
+  if ( label ) {
+    char buf[10];
+    va_list ap;
+    va_start(ap,label);
+    vsnprintf(buf,10,label,ap);
+
+    if ( orientation == TICK_ABSCISSA ) 
+      pl_alabel_r(chart->lp, 'c','t', buf);
+    else if (orientation == TICK_ORDINATE ) 
+      {
+       if ( fabs(position) < DBL_EPSILON )
+           pl_moverel_r(chart->lp, 0, 10);
+
+       pl_alabel_r(chart->lp, 'r','c', buf);
+      }
+
+    va_end(ap);
+  }
+    
+  pl_restorestate_r(chart->lp);
+}
+
+
+
+
+/* Write the title on a chart*/
+void  
+chart_write_title(struct chart *chart, const char *title, ...)
+{
+  va_list ap;
+  char buf[100];
+
+  pl_savestate_r(chart->lp);
+  pl_ffontsize_r(chart->lp,chart->font_size * 1.5);
+  pl_move_r(chart->lp,chart->data_left, chart->title_bottom);
+
+  va_start(ap,title);
+  vsnprintf(buf,100,title,ap);
+  pl_alabel_r(chart->lp,0,0,buf);
+  va_end(ap);
+
+  pl_restorestate_r(chart->lp);
+}
+
+
+
+void
+chart_finalise(struct chart *chart)
+{
+  pl_restorestate_r(chart->lp);
+
+  if (pl_closepl_r (chart->lp) < 0)     /* close Plotter */
+    {
+      fprintf (stderr, "Couldn't close Plotter\n");
+    }
+
+
+  pl_deletepl_r(chart->lp);
+
+  pl_deleteplparams(chart->pl_params);
+
+}
+
+
+/* Set the scale for the abscissa */
+void 
+chart_write_xscale(struct chart *ch, double min, double max, int ticks)
+{
+  double x;
+
+  const double tick_interval = 
+    chart_rounded_tick( (max - min) / (double) ticks);
+
+  ch->x_max = ceil( max / tick_interval ) * tick_interval ; 
+  ch->x_min = floor ( min / tick_interval ) * tick_interval ;
+
+  ch->abscissa_scale = fabs(ch->data_right - ch->data_left) / 
+    fabs(ch->x_max - ch->x_min);
+
+  for(x = ch->x_min ; x <= ch->x_max; x += tick_interval )
+    {
+      draw_tick (ch, TICK_ABSCISSA, 
+                (x - ch->x_min) * ch->abscissa_scale, "%g", x);
+    }
+
+}
+
+
+/* Set the scale for the ordinate */
+void 
+chart_write_yscale(struct chart *ch, double smin, double smax, int ticks)
+{
+  double y;
+
+  const double tick_interval = 
+    chart_rounded_tick( (smax - smin) / (double) ticks);
+
+  ch->y_max = ceil  ( smax / tick_interval ) * tick_interval ; 
+  ch->y_min = floor ( smin / tick_interval ) * tick_interval ;
+
+  ch->ordinate_scale = 
+    fabs(ch->data_top -  ch->data_bottom) / fabs(ch->y_max - ch->y_min) ;
+
+  for(y = ch->y_min ; y <= ch->y_max; y += tick_interval )
+    {
+    draw_tick (ch, TICK_ORDINATE, 
+              (y - ch->y_min) * ch->ordinate_scale, "%g", y);
+    }
+
+}
+
diff --git a/src/plot-hist.c b/src/plot-hist.c
new file mode 100644 (file)
index 0000000..7208d3f
--- /dev/null
@@ -0,0 +1,163 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by John Darrington <john@darrington.wattle.id.au>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA. */
+
+#include <config.h>
+
+#include <stdio.h>
+#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"
+
+/* Write the legend of the chart */
+void
+histogram_write_legend(struct chart *ch, const struct normal_curve *norm)
+{
+  char buf[100];
+  pl_savestate_r(ch->lp);
+
+  sprintf(buf,"N = %.2f",norm->N);
+  pl_move_r(ch->lp, ch->legend_left, ch->data_bottom);
+  pl_alabel_r(ch->lp,0,'b',buf);
+
+  sprintf(buf,"Mean = %.1f",norm->mean);
+  pl_fmove_r(ch->lp,ch->legend_left,ch->data_bottom + ch->font_size * 1.5);
+  pl_alabel_r(ch->lp,0,'b',buf);
+
+  sprintf(buf,"Std. Dev = %.2f",norm->stddev);
+  pl_fmove_r(ch->lp,ch->legend_left,ch->data_bottom + ch->font_size * 1.5 * 2);
+  pl_alabel_r(ch->lp,0,'b',buf);
+
+  pl_restorestate_r(ch->lp);    
+}
+
+static void hist_draw_bar(struct chart *ch, const gsl_histogram *hist, int bar);
+
+
+static void
+hist_draw_bar(struct chart *ch, const gsl_histogram *hist, int bar)
+{
+  double upper;
+  double lower;
+  double height;
+
+  const size_t bins = gsl_histogram_bins(hist);
+  const double x_pos = (ch->data_right - ch->data_left) * bar / (double) bins ;
+  const double width = (ch->data_right - ch->data_left) / (double) bins ;
+
+
+  assert ( 0 == gsl_histogram_get_range(hist, bar, &lower, &upper));
+
+  assert( upper >= lower);
+
+  height = gsl_histogram_get(hist, bar) * 
+    (ch->data_top - ch->data_bottom) / gsl_histogram_max_val(hist);
+
+  pl_savestate_r(ch->lp);
+  pl_move_r(ch->lp,ch->data_left, ch->data_bottom);
+  pl_fillcolorname_r(ch->lp, ch->fill_colour); 
+  pl_filltype_r(ch->lp,1);
+
+
+  pl_fboxrel_r(ch->lp,
+              x_pos, 0,
+              x_pos + width, height);
+
+  pl_restorestate_r(ch->lp);
+
+  {
+  char buf[5];
+  snprintf(buf,5,"%g",(upper + lower) / 2.0);
+  draw_tick(ch, TICK_ABSCISSA,
+           x_pos + width / 2.0, buf);
+  }
+
+}
+
+
+
+
+void
+histogram_plot(const gsl_histogram *hist,
+              const char *factorname,
+              const struct normal_curve *norm, short show_normal)
+{
+  int i;
+  int bins;
+  
+  struct chart ch;
+
+  bins = gsl_histogram_bins(hist);
+
+  chart_initialise(&ch);
+  chart_write_title(&ch, _("HISTOGRAM"));
+
+  chart_write_ylabel(&ch, _("Frequency"));
+  chart_write_xlabel(&ch, factorname);
+
+  chart_write_yscale(&ch, 0, gsl_histogram_max_val(hist), 5);
+
+  for ( i = 0 ; i < bins ; ++i ) 
+      hist_draw_bar(&ch, hist, i);
+
+  histogram_write_legend(&ch, norm);
+
+  if ( show_normal  )
+  {
+    /* Draw the normal curve */    
+
+    double d ;
+    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);
+    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) ;
+
+    pl_move_r(ch.lp, ch.data_left, ch.data_bottom);    
+    for( d = ch.data_left; 
+        d <= ch.data_right ; 
+        d += (ch.data_right - ch.data_left) / 100.0)
+      {    
+       const double x = (d - ch.data_left) / abscissa_scale + x_min ; 
+       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);
+
+  }
+  chart_finalise(&ch);
+}
+