From: John Darrington Date: Fri, 7 Jan 2005 00:17:19 +0000 (+0000) Subject: Added an optional --without-libplot flag to configure X-Git-Tag: v0.4.0~202 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp-builds.git;a=commitdiff_plain;h=72318eac4782acf0215da8dfd4575ac66a9a9f74 Added an optional --without-libplot flag to configure --- diff --git a/ChangeLog b/ChangeLog index 347e81ca..fb7208f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri Jan 7 08:01:02 WST 2005 John Darrington + + * 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 * Smake: Change -a to -pR in cp invocations for SUSv3 compliance. diff --git a/configure.ac b/configure.ac index 7921bcc3..49f3a0b3 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/po/en_GB.po b/po/en_GB.po index defa8859..726a6be8 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -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 \n" "Language-Team: John Darrington \n" diff --git a/po/pspp.pot b/po/pspp.pot index 7cf0a1d6..8a01629b 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -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 \n" "Language-Team: LANGUAGE \n" diff --git a/pref.h.orig b/pref.h.orig index 6ae22997..ed5c53fe 100644 --- a/pref.h.orig +++ b/pref.h.orig @@ -16,6 +16,10 @@ #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 diff --git a/src/ChangeLog b/src/ChangeLog index 3f3e65bc..b3548aa2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +Fri Jan 7 08:00:05 WST 2005 John Darrington + + * 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 * main.c Added a signal handler for SIGFPE diff --git a/src/Makefile.am b/src/Makefile.am index 1afb336e..354c3203 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/chart.c b/src/chart.c index 07111ad9..17878825 100644 --- a/src/chart.c +++ b/src/chart.c @@ -17,171 +17,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#include -#include -#include -#include -#include -#include + #include +#include #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); - } - -} - diff --git a/src/chart.h b/src/chart.h index eec5bff5..8d1a9146 100644 --- a/src/chart.h +++ b/src/chart.h @@ -21,12 +21,15 @@ #ifndef CHART_H #define CHART_H +#include #include -#include #include - #include "var.h" +#ifndef NO_CHARTS +#include +#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. diff --git a/src/examine.q b/src/examine.q index 5cb89af2..517b24f9 100644 --- a/src/examine.q +++ b/src/examine.q @@ -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 } diff --git a/src/frequencies.q b/src/frequencies.q index acfeed86..b5da79bd 100644 --- a/src/frequencies.q +++ b/src/frequencies.q @@ -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: diff --git a/src/histogram.c b/src/histogram.c index 9a3b9264..f3347456 100644 --- a/src/histogram.c +++ b/src/histogram.c @@ -17,150 +17,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include - -#include -#include #include #include -#include #include - -#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, ¬_used); - range = not_used - x_min; - gsl_histogram_get_range(hist, bins - 1, ¬_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 index 00000000..4f146b77 --- /dev/null +++ b/src/histogram.h @@ -0,0 +1,28 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by John Darrington + + 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_histogram * histogram_create(double bins, double x_min, double x_max); + +#endif diff --git a/src/piechart.c b/src/piechart.c index 53c2b5fd..35e5e0ba 100644 --- a/src/piechart.c +++ b/src/piechart.c @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include "config.h" #include "chart.h" #include #include @@ -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 index 00000000..ddbb3608 --- /dev/null +++ b/src/plot-chart.c @@ -0,0 +1,231 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by John Darrington + + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..7208d3fa --- /dev/null +++ b/src/plot-hist.c @@ -0,0 +1,163 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by John Darrington + + 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 + +#include +#include +#include +#include +#include +#include + +#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, ¬_used); + range = not_used - x_min; + gsl_histogram_get_range(hist, bins - 1, ¬_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); +} +