dfc74603003f342dacc7141ee347d472aa8a127b
[pspp-builds.git] / src / output / charts / np-plot.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <output/charts/np-plot.h>
20
21 #include <gsl/gsl_cdf.h>
22
23 #include <data/casereader.h>
24 #include <libpspp/cast.h>
25 #include <math/np.h>
26 #include <output/chart-item-provider.h>
27
28 #include "gl/minmax.h"
29
30 static struct chart_item *
31 make_np_plot (const struct np *np, const struct casereader *reader,
32               const char *label, bool detrended)
33 {
34   struct np_plot_chart *npp;
35
36   if (np->n < 1.0)
37     return NULL;
38
39   npp = xzalloc (sizeof *npp);
40   chart_item_init (&npp->chart_item, &np_plot_chart_class, label);
41   npp->data = casereader_clone (reader);
42   npp->y_min = np->y_min;
43   npp->y_max = np->y_max;
44   npp->dns_min = np->dns_min;
45   npp->dns_max = np->dns_max;
46   npp->detrended = detrended;
47
48   /* Slope and intercept of the ideal normal probability line. */
49   npp->slope = 1.0 / np->stddev;
50   npp->intercept = -np->mean / np->stddev;
51
52   npp->y_first = gsl_cdf_ugaussian_Pinv (1 / (np->n + 1));
53   npp->y_last = gsl_cdf_ugaussian_Pinv (np->n / (np->n + 1));
54
55   /* Need to make sure that both the scatter plot and the ideal fit into the
56      plot. */
57   npp->x_lower = MIN (np->y_min, (npp->y_first - npp->intercept) / npp->slope);
58   npp->x_upper = MAX (np->y_max, (npp->y_last  - npp->intercept) / npp->slope);
59   npp->slack = (npp->x_upper - npp->x_lower) * 0.05;
60
61   return &npp->chart_item;
62 }
63
64 /* Creates and returns a normal probability plot corresponding to
65    the calculations in NP and the data in READER, and label the
66    plot with LABEL.  The data in READER must have Y-values in
67    value index NP_IDX_Y and NS-values in value index NP_IDX_NS.
68
69    Returns a null pointer if the data set is empty.
70
71    The caller retains ownership of NP and READER. */
72 struct chart_item *
73 np_plot_create (const struct np *np, const struct casereader *reader,
74                 const char *label)
75 {
76   return make_np_plot (np, reader, label, false);
77 }
78
79 /* Creates and returns a detrended normal probability plot
80    corresponding to the calculations in NP and the data in
81    READER, and label the plot with LABEL.  The data in READER
82    must have Y-values in value index NP_IDX_Y and DNS-values in
83    value index NP_IDX_DNS.
84
85    Returns a null pointer if the data set is empty.
86
87    The caller retains ownership of NP and READER. */
88 struct chart_item *
89 dnp_plot_create (const struct np *np, const struct casereader *reader,
90                  const char *label)
91 {
92   return make_np_plot (np, reader, label, true);
93 }
94
95 static void
96 np_plot_chart_destroy (struct chart_item *chart_item)
97 {
98   struct np_plot_chart *npp = to_np_plot_chart (chart_item);
99   casereader_destroy (npp->data);
100   free (npp);
101 }
102
103 const struct chart_item_class np_plot_chart_class =
104   {
105     np_plot_chart_destroy
106   };