#include <libpspp/misc.h>
#include <libpspp/str.h>
#include <math/moments.h>
-#include <output/chart-provider.h>
#include <output/charts/box-whisker.h>
-#include <output/charts/cartesian.h>
+#include <output/charts/np-plot.h>
#include <output/manager.h>
#include <output/table.h>
};
-struct np_plot_chart
- {
- struct chart chart;
- char *label;
- struct casereader *data;
-
- /* Copied directly from struct np. */
- double y_min, y_max;
- double dns_min, dns_max;
-
- /* Calculated. */
- double slope, intercept;
- double y_first, y_last;
- double x_lower, x_upper;
- double slack;
- };
-
-static const struct chart_class np_plot_chart_class;
-static const struct chart_class dnp_plot_chart_class;
-
-/* Plot the normal and detrended normal plots for RESULT.
- Label the plots with LABEL */
-static void
-np_plot (struct np *np, const char *label)
-{
- struct np_plot_chart *np_plot, *dnp_plot;
-
- if ( np->n < 1.0 )
- {
- msg (MW, _("Not creating plot because data set is empty."));
- return ;
- }
-
- np_plot = xmalloc (sizeof *np_plot);
- chart_init (&np_plot->chart, &np_plot_chart_class);
- np_plot->label = xstrdup (label);
- np_plot->data = casewriter_make_reader (np->writer);
- np_plot->y_min = np->y_min;
- np_plot->y_max = np->y_max;
- np_plot->dns_min = np->dns_min;
- np_plot->dns_max = np->dns_max;
-
- /* Slope and intercept of the ideal normal probability line. */
- np_plot->slope = 1.0 / np->stddev;
- np_plot->intercept = -np->mean / np->stddev;
-
- np_plot->y_first = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1));
- np_plot->y_last = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1));
-
- /* Need to make sure that both the scatter plot and the ideal fit into the
- plot */
- np_plot->x_lower = MIN (
- np->y_min, (np_plot->y_first - np_plot->intercept) / np_plot->slope);
- np_plot->x_upper = MAX (
- np->y_max, (np_plot->y_last - np_plot->intercept) / np_plot->slope) ;
- np_plot->slack = (np_plot->x_upper - np_plot->x_lower) * 0.05 ;
-
- dnp_plot = xmemdup (np_plot, sizeof *np_plot);
- chart_init (&dnp_plot->chart, &dnp_plot_chart_class);
- dnp_plot->label = xstrdup (dnp_plot->label);
- dnp_plot->data = casereader_clone (dnp_plot->data);
-
- chart_submit (&np_plot->chart);
- chart_submit (&dnp_plot->chart);
-}
-
-static void
-np_plot_chart_draw (const struct chart *chart, plPlotter *lp)
-{
- const struct np_plot_chart *plot = (struct np_plot_chart *) chart;
- struct chart_geometry geom;
- struct casereader *data;
- struct ccase *c;
-
- chart_geometry_init (lp, &geom);
- chart_write_title (lp, &geom, _("Normal Q-Q Plot of %s"), plot->label);
- chart_write_xlabel (lp, &geom, _("Observed Value"));
- chart_write_ylabel (lp, &geom, _("Expected Normal"));
- chart_write_xscale (lp, &geom,
- plot->x_lower - plot->slack,
- plot->x_upper + plot->slack, 5);
- chart_write_yscale (lp, &geom, plot->y_first, plot->y_last, 5);
-
- data = casereader_clone (plot->data);
- for (; (c = casereader_read (data)) != NULL; case_unref (c))
- chart_datum (lp, &geom, 0,
- case_data_idx (c, NP_IDX_Y)->f,
- case_data_idx (c, NP_IDX_NS)->f);
- casereader_destroy (data);
-
- chart_line (lp, &geom, plot->slope, plot->intercept,
- plot->y_first, plot->y_last, CHART_DIM_Y);
-
- chart_geometry_free (lp);
-}
-
-static void
-dnp_plot_chart_draw (const struct chart *chart, plPlotter *lp)
-{
- const struct np_plot_chart *plot = (struct np_plot_chart *) chart;
- struct chart_geometry geom;
- struct casereader *data;
- struct ccase *c;
-
- chart_geometry_init (lp, &geom);
- chart_write_title (lp, &geom, _("Detrended Normal Q-Q Plot of %s"),
- plot->label);
- chart_write_xlabel (lp, &geom, _("Observed Value"));
- chart_write_ylabel (lp, &geom, _("Dev from Normal"));
- chart_write_xscale (lp, &geom, plot->y_min, plot->y_max, 5);
- chart_write_yscale (lp, &geom, plot->dns_min, plot->dns_max, 5);
-
- data = casereader_clone (plot->data);
- for (; (c = casereader_read (data)) != NULL; case_unref (c))
- chart_datum (lp, &geom, 0, case_data_idx (c, NP_IDX_Y)->f,
- case_data_idx (c, NP_IDX_DNS)->f);
- casereader_destroy (data);
-
- chart_line (lp, &geom, 0, 0, plot->y_min, plot->y_max, CHART_DIM_X);
-
- chart_geometry_free (lp);
-}
-
-static void
-np_plot_chart_destroy (struct chart *chart)
-{
- struct np_plot_chart *plot = (struct np_plot_chart *) chart;
-
- casereader_destroy (plot->data);
- free (plot->label);
- free (plot);
-}
-
-static const struct chart_class np_plot_chart_class =
- {
- np_plot_chart_draw,
- np_plot_chart_destroy
- };
-
-static const struct chart_class dnp_plot_chart_class =
- {
- dnp_plot_chart_draw,
- np_plot_chart_destroy
- };
static void
ll != ll_null (&fctr->result_list);
ll = ll_next (ll))
{
- struct string str;
+ struct string label;
const struct factor_result *result =
ll_data (ll, struct factor_result, ll);
+ struct chart *npp, *dnpp;
+ struct casereader *reader;
+ struct np *np;
- ds_init_empty (&str);
- ds_put_format (&str, "%s ", var_get_name (dependent_var[v]));
+ ds_init_empty (&label);
+ ds_put_format (&label, "%s ", var_get_name (dependent_var[v]));
+ factor_to_string (fctr, result, &label);
- factor_to_string (fctr, result, &str);
+ np = (struct np *) result->metrics[v].np;
+ reader = casewriter_make_reader (np->writer);
+ npp = np_plot_create (np, reader, ds_cstr (&label));
+ dnpp = dnp_plot_create (np, reader, ds_cstr (&label));
- np_plot ((struct np*) result->metrics[v].np, ds_cstr(&str));
+ ds_destroy (&label);
- statistic_destroy ((struct statistic *)result->metrics[v].np);
+ if (npp == NULL || dnpp == NULL)
+ {
+ msg (MW, _("Not creating NP plot because data set is empty."));
+ chart_unref (npp);
+ chart_unref (dnpp);
+ }
+ else
+ {
+ chart_submit (npp);
+ chart_submit (dnpp);
+ }
- ds_destroy (&str);
+ statistic_destroy (&np->parent.parent);
}
}
}
src/output/charts/box-whisker.h \
src/output/charts/cartesian.c \
src/output/charts/cartesian.h \
+ src/output/charts/np-plot.c \
+ src/output/charts/np-plot.h \
src/output/charts/piechart.c \
src/output/charts/piechart.h \
src/output/charts/plot-chart.h \
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <output/charts/np-plot.h>
+
+#include <gsl/gsl_cdf.h>
+
+#include <data/casereader.h>
+#include <data/casewriter.h>
+#include <libpspp/message.h>
+#include <math/np.h>
+#include <output/chart-provider.h>
+#include <output/charts/cartesian.h>
+#include <output/charts/plot-chart.h>
+
+#include "gl/minmax.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* An NP or DNP plot. */
+struct np_plot_chart
+ {
+ struct chart chart;
+ char *label;
+ struct casereader *data;
+
+ /* Copied directly from struct np. */
+ double y_min, y_max;
+ double dns_min, dns_max;
+
+ /* Calculated. */
+ double slope, intercept;
+ double y_first, y_last;
+ double x_lower, x_upper;
+ double slack;
+ };
+
+static const struct chart_class np_plot_chart_class;
+static const struct chart_class dnp_plot_chart_class;
+
+static struct chart *
+make_np_plot (const struct chart_class *class,
+ const struct np *np, const struct casereader *reader,
+ const char *label)
+{
+ struct np_plot_chart *npp;
+
+ if (np->n < 1.0)
+ return NULL;
+
+ npp = xmalloc (sizeof *npp);
+ chart_init (&npp->chart, class);
+ npp->label = xstrdup (label);
+ npp->data = casereader_clone (reader);
+ npp->y_min = np->y_min;
+ npp->y_max = np->y_max;
+ npp->dns_min = np->dns_min;
+ npp->dns_max = np->dns_max;
+
+ /* Slope and intercept of the ideal normal probability line. */
+ npp->slope = 1.0 / np->stddev;
+ npp->intercept = -np->mean / np->stddev;
+
+ npp->y_first = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1));
+ npp->y_last = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1));
+
+ /* Need to make sure that both the scatter plot and the ideal fit into the
+ plot. */
+ npp->x_lower = MIN (np->y_min, (npp->y_first - npp->intercept) / npp->slope);
+ npp->x_upper = MAX (np->y_max, (npp->y_last - npp->intercept) / npp->slope);
+ npp->slack = (npp->x_upper - npp->x_lower) * 0.05;
+
+ return &npp->chart;
+}
+
+/* Creates and returns a normal probability plot corresponding to
+ the calculations in NP and the data in READER, and label the
+ plot with LABEL. The data in READER must have Y-values in
+ value index NP_IDX_Y and NS-values in value index NP_IDX_NS.
+
+ Returns a null pointer if the data set is empty.
+
+ The caller retains ownership of NP and READER. */
+struct chart *
+np_plot_create (const struct np *np, const struct casereader *reader,
+ const char *label)
+{
+ return make_np_plot (&np_plot_chart_class, np, reader, label);
+}
+
+/* Creates and returns a detrended normal probability plot
+ corresponding to the calculations in NP and the data in
+ READER, and label the plot with LABEL. The data in READER
+ must have Y-values in value index NP_IDX_Y and DNS-values in
+ value index NP_IDX_DNS.
+
+ Returns a null pointer if the data set is empty.
+
+ The caller retains ownership of NP and READER. */
+struct chart *
+dnp_plot_create (const struct np *np, const struct casereader *reader,
+ const char *label)
+{
+ return make_np_plot (&dnp_plot_chart_class, np, reader, label);
+}
+
+static void
+np_plot_chart_draw (const struct chart *chart, plPlotter *lp)
+{
+ const struct np_plot_chart *npp = (struct np_plot_chart *) chart;
+ struct chart_geometry geom;
+ struct casereader *data;
+ struct ccase *c;
+
+ chart_geometry_init (lp, &geom);
+ chart_write_title (lp, &geom, _("Normal Q-Q Plot of %s"), npp->label);
+ chart_write_xlabel (lp, &geom, _("Observed Value"));
+ chart_write_ylabel (lp, &geom, _("Expected Normal"));
+ chart_write_xscale (lp, &geom,
+ npp->x_lower - npp->slack,
+ npp->x_upper + npp->slack, 5);
+ chart_write_yscale (lp, &geom, npp->y_first, npp->y_last, 5);
+
+ data = casereader_clone (npp->data);
+ for (; (c = casereader_read (data)) != NULL; case_unref (c))
+ chart_datum (lp, &geom, 0,
+ case_data_idx (c, NP_IDX_Y)->f,
+ case_data_idx (c, NP_IDX_NS)->f);
+ casereader_destroy (data);
+
+ chart_line (lp, &geom, npp->slope, npp->intercept,
+ npp->y_first, npp->y_last, CHART_DIM_Y);
+
+ chart_geometry_free (lp);
+}
+
+static void
+dnp_plot_chart_draw (const struct chart *chart, plPlotter *lp)
+{
+ const struct np_plot_chart *dnpp = (struct np_plot_chart *) chart;
+ struct chart_geometry geom;
+ struct casereader *data;
+ struct ccase *c;
+
+ chart_geometry_init (lp, &geom);
+ chart_write_title (lp, &geom, _("Detrended Normal Q-Q Plot of %s"),
+ dnpp->label);
+ chart_write_xlabel (lp, &geom, _("Observed Value"));
+ chart_write_ylabel (lp, &geom, _("Dev from Normal"));
+ chart_write_xscale (lp, &geom, dnpp->y_min, dnpp->y_max, 5);
+ chart_write_yscale (lp, &geom, dnpp->dns_min, dnpp->dns_max, 5);
+
+ data = casereader_clone (dnpp->data);
+ for (; (c = casereader_read (data)) != NULL; case_unref (c))
+ chart_datum (lp, &geom, 0, case_data_idx (c, NP_IDX_Y)->f,
+ case_data_idx (c, NP_IDX_DNS)->f);
+ casereader_destroy (data);
+
+ chart_line (lp, &geom, 0, 0, dnpp->y_min, dnpp->y_max, CHART_DIM_X);
+
+ chart_geometry_free (lp);
+}
+
+static void
+np_plot_chart_destroy (struct chart *chart)
+{
+ struct np_plot_chart *npp = (struct np_plot_chart *) chart;
+
+ casereader_destroy (npp->data);
+ free (npp->label);
+ free (npp);
+}
+
+static const struct chart_class np_plot_chart_class =
+ {
+ np_plot_chart_draw,
+ np_plot_chart_destroy
+ };
+
+static const struct chart_class dnp_plot_chart_class =
+ {
+ dnp_plot_chart_draw,
+ np_plot_chart_destroy
+ };
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
+
+#ifndef OUTPUT_CHARTS_NP_PLOT_H
+#define OUTPUT_CHARTS_NP_PLOT_H 1
+
+struct casereader;
+struct np;
+
+struct chart *np_plot_create (const struct np *, const struct casereader *,
+ const char *label);
+struct chart *dnp_plot_create (const struct np *, const struct casereader *,
+ const char *label);
+
+#endif /* output/charts/np-plot.h */