1 /*
2 * analysis-normality.c:
3 *
4 *
5 * Author:
6 * Andreas J. Guelzow <aguelzow@pyrshep.ca>
7 *
8 * (C) Copyright 2009 by Andreas J. Guelzow <aguelzow@pyrshep.ca>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses/>.
23 */
24
25 #include <gnumeric-config.h>
26 #include <glib/gi18n-lib.h>
27 #include <gnumeric.h>
28 #include <tools/analysis-normality.h>
29 #include <tools/analysis-tools.h>
30 #include <value.h>
31 #include <ranges.h>
32 #include <expr.h>
33 #include <func.h>
34 #include <numbers.h>
35 #include <sheet-object-graph.h>
36 #include <graph.h>
37 #include <goffice/goffice.h>
38 #include <sheet.h>
39
40
41 static gboolean
analysis_tool_normality_engine_run(data_analysis_output_t * dao,analysis_tools_data_normality_t * info)42 analysis_tool_normality_engine_run (data_analysis_output_t *dao,
43 analysis_tools_data_normality_t *info)
44 {
45 guint col;
46 GSList *data = info->base.input;
47 GnmFunc *fd;
48 GnmFunc *fd_if;
49
50 char const *fdname;
51 char const *testname;
52 char const *n_comment;
53
54 GogGraph *graph = NULL;
55 GogPlot *plot = NULL;
56 SheetObject *so;
57
58 switch (info->type) {
59 case normality_test_type_andersondarling:
60 fdname = "ADTEST";
61 testname = N_("Anderson-Darling Test");
62 n_comment = N_("For the Anderson-Darling Test\n"
63 "the sample size must be at\n"
64 "least 8.");
65 break;
66 case normality_test_type_cramervonmises:
67 fdname = "CVMTEST";
68 testname = N_("Cram\xc3\xa9r-von Mises Test");
69 n_comment = N_("For the Cram\xc3\xa9r-von Mises Test\n"
70 "the sample size must be at\n"
71 "least 8.");
72 break;
73 case normality_test_type_lilliefors:
74 fdname = "LKSTEST";
75 testname = N_("Lilliefors (Kolmogorov-Smirnov) Test");
76 n_comment = N_("For the Lilliefors (Kolmogorov-Smirnov) Test\n"
77 "the sample size must be at least 5.");
78 break;
79 case normality_test_type_shapirofrancia:
80 fdname = "SFTEST";
81 testname = N_("Shapiro-Francia Test");
82 n_comment = N_("For the Shapiro-Francia Test\n"
83 "the sample size must be at\n"
84 "least 5 and at most 5000.");
85 break;
86 default:
87 g_assert_not_reached();
88 }
89
90 fd = gnm_func_lookup_or_add_placeholder (fdname);
91 gnm_func_inc_usage (fd);
92 fd_if = gnm_func_lookup_or_add_placeholder ("IF");
93 gnm_func_inc_usage (fd_if);
94
95 dao_set_italic (dao, 0, 0, 0, 5);
96 dao_set_cell (dao, 0, 0, _(testname));
97
98
99 if (info->graph) {
100 GogChart *chart;
101
102 graph = g_object_new (GOG_TYPE_GRAPH, NULL);
103 chart = GOG_CHART (gog_object_add_by_name (
104 GOG_OBJECT (graph), "Chart", NULL));
105
106 plot = gog_plot_new_by_name ("GogProbabilityPlot");
107 go_object_set_property (G_OBJECT (plot), "distribution",
108 "Distribution", "GODistNormal",
109 NULL, NULL);
110
111 gog_object_add_by_name (GOG_OBJECT (chart),
112 "Plot", GOG_OBJECT (plot));
113 }
114
115
116 /* xgettext:
117 * Note to translators: in the following string and others like it,
118 * the "/" is a separator character that can be changed to anything
119 * if the translation needs the slash; just use, say, "|" instead.
120 *
121 * The items are bundled like this to increase translation context.
122 */
123 set_cell_text_col (dao, 0, 1, _("/Alpha"
124 "/p-Value"
125 "/Statistic"
126 "/N"
127 "/Conclusion"));
128
129 dao_set_cell_comment (dao, 0, 4, _(n_comment));
130
131 for (col = 1; data != NULL; data = data->next, col++) {
132 GnmValue *val_org = value_dup (data->data);
133
134 /* Note that analysis_tools_write_label may modify val_org */
135 dao_set_italic (dao, col, 0, col, 0);
136 analysis_tools_write_label (val_org, dao, &info->base,
137 col, 0, col);
138 if (info->graph) {
139 GogSeries *series;
140
141 series = gog_plot_new_series (plot);
142 gog_series_set_dim (series, 0,
143 gnm_go_data_vector_new_expr
144 (val_org->v_range.cell.a.sheet,
145 gnm_expr_top_new (gnm_expr_new_constant (value_dup (val_org)))),
146 NULL);
147 }
148
149 if (col == 1)
150 dao_set_cell_float (dao, col, 1, info->alpha);
151 else
152 dao_set_cell_expr (dao, col, 1,
153 make_cellref (1 - col, 0));
154
155 dao_set_array_expr (dao, col, 2, 1, 3,
156 gnm_expr_new_funcall1 (fd, gnm_expr_new_constant (val_org)));
157 dao_set_cell_expr (dao, col, 5,
158 gnm_expr_new_funcall3
159 (fd_if, gnm_expr_new_binary
160 (make_cellref (0, -4),
161 GNM_EXPR_OP_GTE,
162 make_cellref (0, -3)),
163 gnm_expr_new_constant (value_new_string (_("Not normal"))),
164 gnm_expr_new_constant (value_new_string (_("Possibly normal")))));
165 }
166
167 if (info->graph) {
168 so = sheet_object_graph_new (graph);
169 g_object_unref (graph);
170
171 dao_set_sheet_object (dao, 0, 1, so);
172 }
173
174
175 gnm_func_dec_usage (fd);
176 gnm_func_dec_usage (fd_if);
177
178 dao_redraw_respan (dao);
179 return 0;
180 }
181
182 gboolean
analysis_tool_normality_engine(G_GNUC_UNUSED GOCmdContext * gcc,data_analysis_output_t * dao,gpointer specs,analysis_tool_engine_t selector,gpointer result)183 analysis_tool_normality_engine (G_GNUC_UNUSED GOCmdContext *gcc, data_analysis_output_t *dao, gpointer specs,
184 analysis_tool_engine_t selector, gpointer result)
185 {
186 analysis_tools_data_normality_t *info = specs;
187
188 switch (selector) {
189 case TOOL_ENGINE_UPDATE_DESCRIPTOR:
190 return (dao_command_descriptor (dao, _("Normality Test (%s)"), result)
191 == NULL);
192 case TOOL_ENGINE_UPDATE_DAO:
193 prepare_input_range (&info->base.input, info->base.group_by);
194 dao_adjust (dao, 1 + g_slist_length (info->base.input), 6);
195 return FALSE;
196 case TOOL_ENGINE_CLEAN_UP:
197 return analysis_tool_generic_clean (specs);
198 case TOOL_ENGINE_LAST_VALIDITY_CHECK:
199 return FALSE;
200 case TOOL_ENGINE_PREPARE_OUTPUT_RANGE:
201 dao_prepare_output (NULL, dao, _("Normality Test"));
202 return FALSE;
203 case TOOL_ENGINE_FORMAT_OUTPUT_RANGE:
204 return dao_format_output (dao, _("Normality Test"));
205 case TOOL_ENGINE_PERFORM_CALC:
206 default:
207 return analysis_tool_normality_engine_run (dao, specs);
208 }
209 return TRUE; /* We shouldn't get here */
210 }
211
212