--- /dev/null
+## Process this file with automake to produce Makefile.in -*- makefile -*-
+
+
+include $(top_srcdir)/src/output/charts/automake.mk
+
+
+src/output/%: AM_CPPFLAGS += \
+ -I$(top_srcdir)/src/math \
+ -I$(top_srcdir)/src/libpspp \
+ -I$(top_srcdir)/src/data
+
+noinst_LIBRARIES += src/output/liboutput.a
+
+
+
+
+output_sources = \
+ src/output/ascii.c \
+ src/output/font.h \
+ src/output/groff-font.c \
+ src/output/html.c \
+ src/output/htmlP.h \
+ src/output/output.c \
+ src/output/output.h \
+ src/output/postscript.c \
+ src/output/manager.c \
+ src/output/manager.h \
+ src/output/chart.h \
+ src/output/table.c src/output/table.h
+
+
+if WITHCHARTS
+src_output_liboutput_a_SOURCES = $(output_sources) src/output/chart.c
+ EXTRA_DIST += src/output/dummy-chart.c
+else
+src_output_liboutput_a_SOURCES = $(output_sources) src/output/dummy-chart.c
+ EXTRA_DIST += src/output/chart.c
+endif
+
+
--- /dev/null
+Thu Mar 2 08:40:33 WST 2006 John Darrington <john@darrington.wattle.id.au>
+
+ * Moved files from src directory
--- /dev/null
+all:
+ $(MAKE) -C /home/res/jmd/PSPP/pspp
--- /dev/null
+## Process this file with automake to produce Makefile.in -*- makefile -*-
+
+
+
+noinst_LIBRARIES += src/output/charts/libcharts.a
+
+
+src/output/charts/%: AM_CPPFLAGS += \
+ -I$(top_srcdir)/src/libpspp \
+ -I$(top_srcdir)/src/output \
+ -I$(top_srcdir)/src/data \
+ -I$(top_srcdir)/src/math
+
+chart_sources = \
+ src/output/charts/barchart.c \
+ src/output/charts/barchart.h \
+ src/output/charts/box-whisker.c \
+ src/output/charts/box-whisker.h \
+ src/output/charts/cartesian.c \
+ src/output/charts/cartesian.h \
+ src/output/charts/piechart.c \
+ src/output/charts/piechart.h \
+ src/output/charts/plot-chart.h \
+ src/output/charts/plot-chart.c \
+ src/output/charts/plot-hist.c \
+ src/output/charts/plot-hist.h
+
+if WITHCHARTS
+src_output_charts_libcharts_a_SOURCES = \
+ $(chart_sources)
+
+EXTRA_DIST += src/output/charts/dummy-chart.c
+else
+src_output_charts_libcharts_a_SOURCES = \
+ src/output/charts/dummy-chart.c
+
+EXTRA_DIST += $(chart_sources)
+
+endif
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include <stdio.h>
+#include <plot.h>
+#include <stdarg.h>
+#include <math.h>
+#include "barchart.h"
+#include "chart.h"
+#include "plot-chart.h"
+
+#define CATAGORIES 6
+#define SUB_CATAGORIES 3
+
+static const double x_min = 0;
+static const double x_max = 15.0;
+
+static const char *cat_labels[] =
+ {
+ "Age",
+ "Intelligence",
+ "Wealth",
+ "Emotional",
+ "cat 5",
+ "cat 6",
+ "cat 7",
+ "cat 8",
+ "cat 9",
+ "cat 10",
+ "cat 11"
+ };
+
+
+
+
+/* Subcatagories */
+static const double data1[] =
+{
+ 28,83,
+ 34,
+ 29,13,
+ 9,4,
+ 3,3,
+ 2,0,
+ 1,0,
+ 0,
+ 1,1
+};
+
+
+static const double data2[] =
+{
+ 45,13,
+ 9,4,
+ 3,43,
+ 2,0,
+ 1,20,
+ 0,0,
+ 1,1,
+ 0,0
+};
+
+static const double data3[] =
+ {
+ 23,18,
+ 0, 45,23, 9, 40, 24,4, 8
+ };
+
+
+static const char subcat_name[]="Gender";
+
+
+struct subcat {
+ const double *data;
+ const char *label;
+};
+
+static const struct subcat sub_catagory[SUB_CATAGORIES] =
+ {
+ {data1, "male"},
+ {data2, "female"},
+ {data3, "47xxy"}
+ };
+
+
+
+static const double y_min = 0;
+static const double y_max = 120.0;
+static const double y_tick = 20.0;
+
+
+
+static void write_legend(struct chart *chart) ;
+
+
+void
+draw_barchart(struct chart *ch, const char *title,
+ const char *xlabel, const char *ylabel, enum bar_opts opt)
+{
+ double d;
+ int i;
+
+ double interval_size = fabs(ch->data_right - ch->data_left) / ( CATAGORIES );
+
+ double bar_width = interval_size / 1.1 ;
+
+ double ordinate_scale = fabs(ch->data_top - ch->data_bottom) /
+ fabs(y_max - y_min) ;
+
+ if ( opt != BAR_STACKED )
+ bar_width /= SUB_CATAGORIES;
+
+ /* Move to data bottom-left */
+ pl_move_r(ch->lp, ch->data_left, ch->data_bottom);
+
+ pl_savestate_r(ch->lp);
+ pl_filltype_r(ch->lp,1);
+
+ /* Draw the data */
+ for (i = 0 ; i < CATAGORIES ; ++i )
+ {
+ int sc;
+ double ystart=0.0;
+ double x = i * interval_size;
+
+ pl_savestate_r(ch->lp);
+
+ draw_tick (ch, TICK_ABSCISSA, x + (interval_size/2 ),
+ cat_labels[i]);
+
+ for(sc = 0 ; sc < SUB_CATAGORIES ; ++sc )
+ {
+
+ pl_savestate_r(ch->lp);
+ pl_fillcolorname_r(ch->lp,data_colour[sc]);
+
+ switch ( opt )
+ {
+ case BAR_GROUPED:
+ pl_fboxrel_r(ch->lp,
+ x + (sc * bar_width ), 0,
+ x + (sc + 1) * bar_width,
+ sub_catagory[sc].data[i] * ordinate_scale );
+ break;
+
+
+ case BAR_STACKED:
+
+ pl_fboxrel_r(ch->lp,
+ x, ystart,
+ x + bar_width,
+ ystart + sub_catagory[sc].data[i] * ordinate_scale );
+
+ ystart += sub_catagory[sc].data[i] * ordinate_scale ;
+
+ break;
+
+ default:
+ break;
+ }
+ pl_restorestate_r(ch->lp);
+ }
+
+ pl_restorestate_r(ch->lp);
+ }
+ pl_restorestate_r(ch->lp);
+
+ for ( d = y_min; d <= y_max ; d += y_tick )
+ {
+
+ draw_tick (ch, TICK_ORDINATE,
+ (d - y_min ) * ordinate_scale, "%g", d);
+
+ }
+
+ /* Write the abscissa label */
+ pl_move_r(ch->lp,ch->data_left, ch->abscissa_top);
+ pl_alabel_r(ch->lp,0,'t',xlabel);
+
+
+ /* Write the ordinate label */
+ pl_savestate_r(ch->lp);
+ pl_move_r(ch->lp,ch->data_bottom, ch->ordinate_right);
+ pl_textangle_r(ch->lp,90);
+ pl_alabel_r(ch->lp,0,0,ylabel);
+ pl_restorestate_r(ch->lp);
+
+
+ chart_write_title(ch, title);
+
+ write_legend(ch);
+
+
+}
+
+
+
+
+
+static void
+write_legend(struct chart *chart)
+{
+ int sc;
+
+ pl_savestate_r(chart->lp);
+
+ pl_filltype_r(chart->lp,1);
+
+ pl_move_r(chart->lp, chart->legend_left,
+ chart->data_bottom + chart->font_size * SUB_CATAGORIES * 1.5);
+
+ pl_alabel_r(chart->lp,0,'b',subcat_name);
+
+ for (sc = 0 ; sc < SUB_CATAGORIES ; ++sc )
+ {
+ pl_fmove_r(chart->lp,
+ chart->legend_left,
+ chart->data_bottom + chart->font_size * sc * 1.5);
+
+ pl_savestate_r(chart->lp);
+ pl_fillcolorname_r(chart->lp,data_colour[sc]);
+ pl_fboxrel_r (chart->lp,
+ 0,0,
+ chart->font_size, chart->font_size);
+ pl_restorestate_r(chart->lp);
+
+ pl_fmove_r(chart->lp,
+ chart->legend_left + chart->font_size * 1.5,
+ chart->data_bottom + chart->font_size * sc * 1.5);
+
+ pl_alabel_r(chart->lp,'l','b',sub_catagory[sc].label);
+ }
+
+
+ pl_restorestate_r(chart->lp);
+}
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef BARCHART_H
+#define BARCHART_H
+
+#include "chart.h"
+
+enum bar_opts {
+ BAR_GROUPED = 0,
+ BAR_STACKED,
+ BAR_RANGE
+};
+
+void draw_barchart(struct chart *ch, const char *title,
+ const char *xlabel, const char *ylabel, enum bar_opts opt);
+
+#endif
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include "chart.h"
+#include "chart-geometry.h"
+#include <math.h>
+#include <assert.h>
+#include "misc.h"
+
+#include "factor-stats.h"
+#include "box-whisker.h"
+#include "plot-chart.h"
+
+
+/* Draw a box-and-whiskers plot
+*/
+
+/* Draw an outlier on the plot CH
+ * at CENTRELINE
+ * The outlier is in (*wvp)[idx]
+ * If EXTREME is non zero, then consider it to be an extreme
+ * value
+ */
+void
+draw_outlier(struct chart *ch, double centreline,
+ struct weighted_value **wvp,
+ int idx,
+ short extreme);
+
+
+void
+draw_outlier(struct chart *ch, double centreline,
+ struct weighted_value **wvp,
+ int idx,
+ short extreme
+ )
+{
+ char label[10];
+
+#define MARKER_CIRCLE 4
+#define MARKER_STAR 3
+
+ pl_fmarker_r(ch->lp,
+ centreline,
+ ch->data_bottom +
+ (wvp[idx]->v.f - ch->y_min ) * ch->ordinate_scale,
+ extreme?MARKER_STAR:MARKER_CIRCLE,
+ 20);
+
+ pl_moverel_r(ch->lp, 10,0);
+
+ snprintf(label, 10, "%d", wvp[idx]->case_nos->num);
+
+ pl_alabel_r(ch->lp, 'l', 'c', label);
+
+}
+
+
+void
+boxplot_draw_boxplot(struct chart *ch,
+ double box_centre,
+ double box_width,
+ struct metrics *m,
+ const char *name)
+{
+ double whisker[2];
+ int i;
+
+ const double *hinge = m->hinge;
+ struct weighted_value **wvp = m->wvp;
+ const int n_data = m->n_data;
+
+ const double step = (hinge[2] - hinge[0]) * 1.5;
+
+
+ const double box_left = box_centre - box_width / 2.0;
+
+ const double box_right = box_centre + box_width / 2.0;
+
+
+ const double box_bottom =
+ ch->data_bottom + ( hinge[0] - ch->y_min ) * ch->ordinate_scale;
+
+
+ const double box_top =
+ ch->data_bottom + ( hinge[2] - ch->y_min ) * ch->ordinate_scale;
+
+ assert(m);
+
+ /* Can't really draw a boxplot if there's no data */
+ if ( n_data == 0 )
+ return ;
+
+ whisker[1] = hinge[2];
+ whisker[0] = wvp[0]->v.f;
+
+ for ( i = 0 ; i < n_data ; ++i )
+ {
+ if ( hinge[2] + step > wvp[i]->v.f)
+ whisker[1] = wvp[i]->v.f;
+
+ if ( hinge[0] - step > wvp[i]->v.f)
+ whisker[0] = wvp[i]->v.f;
+
+ }
+
+ {
+ const double bottom_whisker =
+ ch->data_bottom + ( whisker[0] - ch->y_min ) * ch->ordinate_scale;
+
+ const double top_whisker =
+ ch->data_bottom + ( whisker[1] - ch->y_min ) * ch->ordinate_scale;
+
+
+ pl_savestate_r(ch->lp);
+
+
+ /* Draw the box */
+ pl_savestate_r(ch->lp);
+ pl_fillcolorname_r(ch->lp,ch->fill_colour);
+ pl_filltype_r(ch->lp,1);
+ pl_fbox_r(ch->lp,
+ box_left,
+ box_bottom,
+ box_right,
+ box_top);
+
+ pl_restorestate_r(ch->lp);
+
+
+
+ /* Draw the median */
+ pl_savestate_r(ch->lp);
+ pl_linewidth_r(ch->lp,5);
+ pl_fline_r(ch->lp,
+ box_left,
+ ch->data_bottom + ( hinge[1] - ch->y_min ) * ch->ordinate_scale,
+ box_right,
+ ch->data_bottom + ( hinge[1] - ch->y_min ) * ch->ordinate_scale);
+ pl_restorestate_r(ch->lp);
+
+
+ /* Draw the bottom whisker */
+ pl_fline_r(ch->lp,
+ box_left,
+ bottom_whisker,
+ box_right,
+ bottom_whisker);
+
+ /* Draw top whisker */
+ pl_fline_r(ch->lp,
+ box_left,
+ top_whisker,
+ box_right,
+ top_whisker);
+
+
+
+ /* Draw centre line.
+ (bottom half) */
+ pl_fline_r(ch->lp,
+ box_centre, bottom_whisker,
+ box_centre, box_bottom);
+
+ /* (top half) */
+ pl_fline_r(ch->lp,
+ box_centre, top_whisker,
+ box_centre, box_top);
+ }
+
+ /* Draw outliers */
+ for ( i = 0 ; i < n_data ; ++i )
+ {
+ if ( wvp[i]->v.f >= hinge[2] + step )
+ draw_outlier(ch, box_centre, wvp, i,
+ ( wvp[i]->v.f > hinge[2] + 2 * step )
+ );
+
+ if ( wvp[i]->v.f <= hinge[0] - step )
+ draw_outlier(ch, box_centre, wvp, i,
+ ( wvp[i]->v.f < hinge[0] - 2 * step )
+ );
+ }
+
+
+ /* Draw tick mark on x axis */
+ draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, name);
+
+ pl_restorestate_r(ch->lp);
+
+}
+
+
+
+void
+boxplot_draw_yscale(struct chart *ch , double y_max, double y_min)
+{
+ double y_tick;
+ double d;
+
+ if ( !ch )
+ return ;
+
+ ch->y_max = y_max;
+ ch->y_min = y_min;
+
+ y_tick = chart_rounded_tick(fabs(ch->y_max - ch->y_min) / 5.0);
+
+ ch->y_min = (ceil( ch->y_min / y_tick ) - 1.0 ) * y_tick;
+
+ ch->y_max = ( floor( ch->y_max / y_tick ) + 1.0 ) * y_tick;
+
+ ch->ordinate_scale = fabs(ch->data_top - ch->data_bottom)
+ / fabs(ch->y_max - ch->y_min) ;
+
+
+ /* Move to data bottom-left */
+ pl_move_r(ch->lp,
+ ch->data_left, ch->data_bottom);
+
+ for ( d = ch->y_min; d <= ch->y_max ; d += y_tick )
+ {
+ draw_tick (ch, TICK_ORDINATE, (d - ch->y_min ) * ch->ordinate_scale, "%g", d);
+ }
+
+}
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef BOX_WHISKER_H
+#define BOX_WHISKER_H
+
+#include <config.h>
+
+struct chart ;
+
+/* Draw an outlier on the plot CH
+ * at CENTRELINE
+ * The outlier is in (*wvp)[idx]
+ * If EXTREME is non zero, then consider it to be an extreme
+ * value
+ */
+void draw_outlier(struct chart *ch, double centreline,
+ struct weighted_value **wvp,
+ int idx,
+ short extreme);
+
+
+void boxplot_draw_boxplot(struct chart *ch,
+ double box_centre,
+ double box_width,
+ struct metrics *m,
+ const char *name);
+
+
+void boxplot_draw_yscale(struct chart *ch , double y_max, double y_min);
+
+#endif
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include <math.h>
+#include "chart.h"
+#include <assert.h>
+#include "plot-chart.h"
+#include "cartesian.h"
+
+
+
+struct dataset
+{
+ int n_data;
+ const char *label;
+};
+
+
+#define DATASETS 2
+
+static const struct dataset dataset[DATASETS] =
+ {
+ { 13, "male"},
+ { 11, "female"},
+ };
+
+
+
+
+static void
+write_legend(struct chart *chart, const char *heading, int n);
+
+
+
+/* Write the abscissa label */
+void
+chart_write_xlabel(struct chart *ch, const char *label)
+{
+ if ( ! ch )
+ return ;
+
+ pl_savestate_r(ch->lp);
+
+ pl_move_r(ch->lp,ch->data_left, ch->abscissa_top);
+ pl_alabel_r(ch->lp,0,'t',label);
+
+ pl_restorestate_r(ch->lp);
+
+}
+
+
+
+/* Write the ordinate label */
+void
+chart_write_ylabel(struct chart *ch, const char *label)
+{
+ if ( ! ch )
+ return ;
+
+ pl_savestate_r(ch->lp);
+
+ pl_move_r(ch->lp, ch->data_bottom, ch->ordinate_right);
+ pl_textangle_r(ch->lp, 90);
+ pl_alabel_r(ch->lp, 0, 0, label);
+
+ pl_restorestate_r(ch->lp);
+}
+
+
+
+static void
+write_legend(struct chart *chart, const char *heading,
+ int n)
+{
+ int ds;
+
+ if ( ! chart )
+ return ;
+
+
+ pl_savestate_r(chart->lp);
+
+ pl_filltype_r(chart->lp,1);
+
+ pl_move_r(chart->lp, chart->legend_left,
+ chart->data_bottom + chart->font_size * n * 1.5);
+
+ pl_alabel_r(chart->lp,0,'b',heading);
+
+ for (ds = 0 ; ds < n ; ++ds )
+ {
+ pl_fmove_r(chart->lp,
+ chart->legend_left,
+ chart->data_bottom + chart->font_size * ds * 1.5);
+
+ pl_savestate_r(chart->lp);
+ pl_fillcolorname_r(chart->lp,data_colour[ds]);
+ pl_fboxrel_r (chart->lp,
+ 0,0,
+ chart->font_size, chart->font_size);
+ pl_restorestate_r(chart->lp);
+
+ pl_fmove_r(chart->lp,
+ chart->legend_left + chart->font_size * 1.5,
+ chart->data_bottom + chart->font_size * ds * 1.5);
+
+ pl_alabel_r(chart->lp,'l','b',dataset[ds].label);
+ }
+
+
+ pl_restorestate_r(chart->lp);
+}
+
+
+/* Plot a data point */
+void
+chart_datum(struct chart *ch, int dataset UNUSED, double x, double y)
+{
+ if ( ! ch )
+ return ;
+
+ {
+ const double x_pos =
+ (x - ch->x_min) * ch->abscissa_scale + ch->data_left ;
+
+ const double y_pos =
+ (y - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
+
+ pl_savestate_r(ch->lp);
+
+ pl_fmarker_r(ch->lp, x_pos, y_pos, 6, 15);
+
+ pl_restorestate_r(ch->lp);
+ }
+}
+
+/* Draw a line with slope SLOPE and intercept INTERCEPT.
+ between the points limit1 and limit2.
+ If lim_dim is CHART_DIM_Y then the limit{1,2} are on the
+ y axis otherwise the x axis
+*/
+void
+chart_line(struct chart *ch, double slope, double intercept,
+ double limit1, double limit2, enum CHART_DIM lim_dim)
+{
+ double x1, y1;
+ double x2, y2 ;
+
+ if ( ! ch )
+ return ;
+
+
+ if ( lim_dim == CHART_DIM_Y )
+ {
+ x1 = ( limit1 - intercept ) / slope ;
+ x2 = ( limit2 - intercept ) / slope ;
+ y1 = limit1;
+ y2 = limit2;
+ }
+ else
+ {
+ x1 = limit1;
+ x2 = limit2;
+ y1 = slope * x1 + intercept;
+ y2 = slope * x2 + intercept;
+ }
+
+ y1 = (y1 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
+ y2 = (y2 - ch->y_min) * ch->ordinate_scale + ch->data_bottom ;
+ x1 = (x1 - ch->x_min) * ch->abscissa_scale + ch->data_left ;
+ x2 = (x2 - ch->x_min) * ch->abscissa_scale + ch->data_left ;
+
+ pl_savestate_r(ch->lp);
+
+ pl_fline_r(ch->lp, x1, y1, x2, y2);
+
+ pl_restorestate_r(ch->lp);
+
+}
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+
+#ifndef CARTESIAN_H
+#define CARTESIAN_H
+
+
+enum CHART_DIM
+ {
+ CHART_DIM_X,
+ CHART_DIM_Y
+ };
+
+
+/* Write the abscissa label */
+void chart_write_xlabel(struct chart *ch, const char *label);
+
+
+/* Write the ordinate label */
+void chart_write_ylabel(struct chart *ch, const char *label);
+
+/* Plot a data point */
+void chart_datum(struct chart *ch, int dataset UNUSED, double x, double y);
+
+/* Draw a line with slope SLOPE and intercept INTERCEPT.
+ between the points limit1 and limit2.
+ If lim_dim is CHART_DIM_Y then the limit{1,2} are on the
+ y axis otherwise the x axis
+*/
+void chart_line(struct chart *ch, double slope, double intercept,
+ double limit1, double limit2, enum CHART_DIM lim_dim);
+
+
+#endif
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include <math.h>
+#include <float.h>
+
+#include "chart-geometry.h"
+
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#ifndef CHART_GEOMETRY_H
+#define CHART_GEOMETRY_H
+
+#endif
--- /dev/null
+/* PSPP - computes sample statistics.
+ Copyright (C) 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+/* Stubs for plotting routines.
+ This module is linked only when charts are not supported */
+
+#include "config.h"
+#include "chart.h"
+#include "plot-chart.h"
+#include "cartesian.h"
+#include <gsl/gsl_histogram.h>
+
+
+#ifndef NO_CHARTS
+#error This file should be used only when compiling without charts.
+#endif
+
+struct chart *
+chart_create(void)
+{
+ return 0;
+}
+
+
+void
+chart_write_title(struct chart *chart, const char *title, ...)
+{
+}
+
+
+void
+chart_submit(struct chart *chart)
+{
+}
+
+
+void
+chart_write_xscale(struct chart *ch, double min, double max, int ticks)
+{
+}
+
+
+void
+chart_write_yscale(struct chart *ch, double smin, double smax, int ticks)
+{
+}
+
+
+void
+chart_write_xlabel(struct chart *ch, const char *label)
+{
+}
+
+void
+chart_write_ylabel(struct chart *ch, const char *label)
+{
+}
+
+
+void
+chart_line(struct chart *ch, double slope, double intercept,
+ double limit1, double limit2, enum CHART_DIM lim_dim)
+{
+}
+
+
+void
+chart_datum(struct chart *ch, int dataset UNUSED, double x, double y)
+{
+}
+
+struct normal_curve;
+
+void
+histogram_plot(const gsl_histogram *hist,
+ const char *factorname,
+ const struct normal_curve *norm, short show_normal)
+{
+}
+
+void
+boxplot_draw_yscale(struct chart *ch , double y_max, double y_min)
+{
+}
+
+void
+boxplot_draw_boxplot(struct chart *ch,
+ double box_centre,
+ double box_width,
+ struct metrics *m,
+ const char *name)
+{
+}
+
+
+
+void
+piechart_plot(const char *title, const struct slice *slices, int n_slices)
+{
+}
--- /dev/null
+/* PSPP - draws pie charts of 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+
+#include "config.h"
+#include "piechart.h"
+#include "chart.h"
+#include <float.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include "str.h"
+#include "value-labels.h"
+#include "misc.h"
+#include "plot-chart.h"
+
+/* Pie charts of course need to know Pi :) */
+#ifndef M_PI
+#define M_PI ( 22.0 / 7.0 )
+#endif
+
+
+
+/* Draw a single slice of the pie */
+static void
+draw_segment(struct chart *ch,
+ double centre_x, double centre_y,
+ double radius,
+ double start_angle, double segment_angle,
+ const char *colour) ;
+
+
+
+/* Draw a piechart */
+void
+piechart_plot(const char *title, const struct slice *slices, int n_slices)
+{
+ int i;
+ double total_magnetude=0;
+
+ struct chart *ch = chart_create();
+
+ const double left_label = ch->data_left +
+ (ch->data_right - ch->data_left)/10.0;
+
+ const double right_label = ch->data_right -
+ (ch->data_right - ch->data_left)/10.0;
+
+ const double centre_x = (ch->data_right + ch->data_left ) / 2.0 ;
+ const double centre_y = (ch->data_top + ch->data_bottom ) / 2.0 ;
+
+ const double radius = min(
+ 5.0 / 12.0 * (ch->data_top - ch->data_bottom),
+ 1.0 / 4.0 * (ch->data_right - ch->data_left)
+ );
+
+
+ chart_write_title(ch, title);
+
+ for (i = 0 ; i < n_slices ; ++i )
+ total_magnetude += slices[i].magnetude;
+
+ for (i = 0 ; i < n_slices ; ++i )
+ {
+ static double angle=0.0;
+
+ const double segment_angle =
+ slices[i].magnetude / total_magnetude * 2 * M_PI ;
+
+ const double label_x = centre_x -
+ radius * sin(angle + segment_angle/2.0);
+
+ const double label_y = centre_y +
+ radius * cos(angle + segment_angle/2.0);
+
+ /* Fill the segment */
+ draw_segment(ch,
+ centre_x, centre_y, radius,
+ angle, segment_angle,
+ data_colour[i]);
+
+ /* Now add the labels */
+ if ( label_x < centre_x )
+ {
+ pl_line_r(ch->lp, label_x, label_y,
+ left_label, label_y );
+ pl_moverel_r(ch->lp,0,5);
+ pl_alabel_r(ch->lp,0,0,slices[i].label);
+ }
+ else
+ {
+ pl_line_r(ch->lp,
+ label_x, label_y,
+ right_label, label_y
+ );
+ pl_moverel_r(ch->lp,0,5);
+ pl_alabel_r(ch->lp,'r',0,slices[i].label);
+ }
+
+ angle += segment_angle;
+
+ }
+
+ /* Draw an outline to the pie */
+ pl_filltype_r(ch->lp,0);
+ pl_fcircle_r (ch->lp, centre_x, centre_y, radius);
+
+ chart_submit(ch);
+}
+
+static void
+fill_segment(struct chart *ch,
+ double x0, double y0,
+ double radius,
+ double start_angle, double segment_angle) ;
+
+
+/* Fill a segment with the current fill colour */
+static void
+fill_segment(struct chart *ch,
+ double x0, double y0,
+ double radius,
+ double start_angle, double segment_angle)
+{
+
+ const double start_x = x0 - radius * sin(start_angle);
+ const double start_y = y0 + radius * cos(start_angle);
+
+ const double stop_x =
+ x0 - radius * sin(start_angle + segment_angle);
+
+ const double stop_y =
+ y0 + radius * cos(start_angle + segment_angle);
+
+ assert(segment_angle <= 2 * M_PI);
+ assert(segment_angle >= 0);
+
+ if ( segment_angle > M_PI )
+ {
+ /* Then we must draw it in two halves */
+ fill_segment(ch, x0, y0, radius, start_angle, segment_angle / 2.0 );
+ fill_segment(ch, x0, y0, radius, start_angle + segment_angle / 2.0,
+ segment_angle / 2.0 );
+ }
+ else
+ {
+ pl_move_r(ch->lp, x0, y0);
+
+ pl_cont_r(ch->lp, stop_x, stop_y);
+ pl_cont_r(ch->lp, start_x, start_y);
+
+ pl_arc_r(ch->lp,
+ x0, y0,
+ stop_x, stop_y,
+ start_x, start_y
+ );
+
+ pl_endpath_r(ch->lp);
+ }
+}
+
+
+
+/* Draw a single slice of the pie */
+static void
+draw_segment(struct chart *ch,
+ double x0, double y0,
+ double radius,
+ double start_angle, double segment_angle,
+ const char *colour)
+{
+ const double start_x = x0 - radius * sin(start_angle);
+ const double start_y = y0 + radius * cos(start_angle);
+
+ pl_savestate_r(ch->lp);
+
+ pl_savestate_r(ch->lp);
+ pl_colorname_r(ch->lp, colour);
+
+ pl_pentype_r(ch->lp,1);
+ pl_filltype_r(ch->lp,1);
+
+ fill_segment(ch, x0, y0, radius, start_angle, segment_angle);
+ pl_restorestate_r(ch->lp);
+
+ /* Draw line dividing segments */
+ pl_pentype_r(ch->lp, 1);
+ pl_fline_r(ch->lp, x0, y0, start_x, start_y);
+
+
+ pl_restorestate_r(ch->lp);
+}
+
--- /dev/null
+/* PSPP - draws pie charts of 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#ifndef PIECHART_H
+#define PIECHART_H
+
+struct slice {
+ const char *label;
+ double magnetude;
+};
+
+/* Draw a piechart */
+void piechart_plot(const char *title,
+ const struct slice *slices, int n_slices);
+
+#endif
+
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, 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-geometry.h"
+#include "plot-chart.h"
+#include "str.h"
+#include "alloc.h"
+#include "manager.h"
+#include "output.h"
+#include "plot-chart.h"
+
+const char *data_colour[] = {
+ "brown",
+ "red",
+ "orange",
+ "yellow",
+ "green",
+ "blue",
+ "violet",
+ "grey",
+ "pink"
+};
+
+
+
+/* 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;
+
+ assert(chart);
+
+ 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];
+
+ if ( ! chart )
+ return ;
+
+ 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);
+}
+
+
+/* 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);
+
+ assert ( ch );
+
+
+ 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);
+
+ if ( !ch )
+ return;
+
+ 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);
+ }
+}
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <float.h>
+#include <assert.h>
+#include <math.h>
+
+
+#include "chart-geometry.h"
+#include "chart.h"
+#include "str.h"
+#include "alloc.h"
+#include "manager.h"
+#include "output.h"
+
+
+#ifndef PLOT_CHART_H
+#define PLOT_CHART_H
+
+
+extern const char *data_colour[];
+
+enum tick_orientation {
+ TICK_ABSCISSA=0,
+ TICK_ORDINATE
+};
+
+
+/* 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, ...);
+
+
+/* Write the title on a chart*/
+void chart_write_title(struct chart *chart, const char *title, ...);
+
+
+/* Set the scale for the abscissa */
+void chart_write_xscale(struct chart *ch, double min, double max, int ticks);
+
+
+/* Set the scale for the ordinate */
+void chart_write_yscale(struct chart *ch, double smin, double smax, int ticks);
+
+
+#endif
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include "plot-hist.h"
+#include "plot-chart.h"
+#include <plot.h>
+#include <math.h>
+#include <gsl/gsl_histogram.h>
+#include <gsl/gsl_randist.h>
+#include <assert.h>
+#include "hash.h"
+#include "variable.h"
+#include "chart.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Write the legend of the chart */
+void
+histogram_write_legend(struct chart *ch, const struct normal_curve *norm)
+{
+ char buf[100];
+ if ( !ch )
+ return ;
+
+ 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)
+{
+ if ( !ch )
+ return ;
+
+
+ {
+ 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;
+
+ ch = chart_create();
+ chart_write_title(ch, _("HISTOGRAM"));
+
+ chart_write_ylabel(ch, _("Frequency"));
+ chart_write_xlabel(ch, factorname);
+
+ if ( ! hist ) /* If this happens, probably all values are SYSMIS */
+ {
+ chart_submit(ch);
+ return ;
+ }
+ else
+ {
+ bins = gsl_histogram_bins(hist);
+ }
+
+ 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_submit(ch);
+}
+
--- /dev/null
+/* 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef PLOT_HIST_H
+#define PLOT_HIST_H
+
+#include <config.h>
+#include <gsl/gsl_histogram.h>
+
+
+struct normal_curve
+{
+ double N ;
+ double mean ;
+ double stddev ;
+};
+struct chart;
+
+/* Write the legend of the chart */
+void histogram_write_legend(struct chart *ch, const struct normal_curve *norm);
+
+void histogram_plot(const gsl_histogram *hist,
+ const char *factorname,
+ const struct normal_curve *norm, short show_normal);
+
+
+#endif