Added stub for ROC computation
[pspp-builds.git] / src / language / stats / roc.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 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 "roc.h"
20 #include <data/procedure.h>
21 #include <language/lexer/variable-parser.h>
22 #include <language/lexer/value-parser.h>
23 #include <language/lexer/lexer.h>
24
25 #include <data/casegrouper.h>
26 #include <data/casereader.h>
27
28 #include "gettext.h"
29 #define _(msgid) gettext (msgid)
30 #define N_(msgid) msgid
31
32 struct cmd_roc
33 {
34   size_t n_vars;
35   const struct variable **vars;
36
37   struct variable *state_var ;
38   union value state_value;
39
40   /* Plot the roc curve */
41   bool curve;
42   /* Plot the reference line */
43   bool reference;
44
45   double ci;
46
47   bool print_coords;
48   bool print_se;
49   bool bi_neg_exp; /* True iff the bi-negative exponential critieria
50                       should be used */
51   enum mv_class exclude;
52
53   bool invert ; /* True iff a smaller test result variable indicates
54                    a positive result */
55
56 };
57
58 static int run_roc (struct dataset *ds, struct cmd_roc *roc);
59
60 int
61 cmd_roc (struct lexer *lexer, struct dataset *ds)
62 {
63   struct cmd_roc roc ;
64   const struct dictionary *dict = dataset_dict (ds);
65
66   roc.vars = NULL;
67   roc.n_vars = 0;
68   roc.print_se = false;
69   roc.print_coords = false;
70   roc.exclude = MV_ANY;
71   roc.curve = true;
72   roc.reference = false;
73   roc.ci = 95;
74   roc.bi_neg_exp = false;
75   roc.invert = false;
76
77   if (!parse_variables_const (lexer, dict, &roc.vars, &roc.n_vars,
78                               PV_APPEND | PV_NO_DUPLICATE | PV_NUMERIC))
79     return 2;
80
81   if ( ! lex_force_match (lexer, T_BY))
82     {
83       return 2;
84     }
85
86   roc.state_var = parse_variable (lexer, dict);
87
88   if ( !lex_force_match (lexer, '('))
89     {
90       return 2;
91     }
92
93   parse_value (lexer, &roc.state_value, var_get_width (roc.state_var));
94
95
96   if ( !lex_force_match (lexer, ')'))
97     {
98       return 2;
99     }
100
101
102   while (lex_token (lexer) != '.')
103     {
104       lex_match (lexer, '/');
105       if (lex_match_id (lexer, "MISSING"))
106         {
107           lex_match (lexer, '=');
108           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
109             {
110               if (lex_match_id (lexer, "INCLUDE"))
111                 {
112                   roc.exclude = MV_SYSTEM;
113                 }
114               else if (lex_match_id (lexer, "EXCLUDE"))
115                 {
116                   roc.exclude = MV_ANY;
117                 }
118               else
119                 {
120                   lex_error (lexer, NULL);
121                   return 2;
122                 }
123             }
124         }
125       else if (lex_match_id (lexer, "PLOT"))
126         {
127           lex_match (lexer, '=');
128           if (lex_match_id (lexer, "CURVE"))
129             {
130               roc.curve = true;
131               if (lex_match (lexer, '('))
132                 {
133                   roc.reference = true;
134                   lex_force_match_id (lexer, "REFERENCE");
135                   lex_force_match (lexer, ')');
136                 }
137             }
138           else if (lex_match_id (lexer, "NONE"))
139             {
140               roc.curve = false;
141             }
142           else
143             {
144               lex_error (lexer, NULL);
145               return 2;
146             }
147         }
148       else if (lex_match_id (lexer, "PRINT"))
149         {
150           lex_match (lexer, '=');
151           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
152             {
153               if (lex_match_id (lexer, "SE"))
154                 {
155                   roc.print_se = true;
156                 }
157               else if (lex_match_id (lexer, "COORDINATES"))
158                 {
159                   roc.print_coords = true;
160                 }
161               else
162                 {
163                   lex_error (lexer, NULL);
164                   return 2;
165                 }
166             }
167         }
168       else if (lex_match_id (lexer, "CRITERIA"))
169         {
170           lex_match (lexer, '=');
171           while (lex_token (lexer) != '.' && lex_token (lexer) != '/')
172             {
173               if (lex_match_id (lexer, "CUTOFF"))
174                 {
175                   lex_force_match (lexer, '(');
176                   if (lex_match_id (lexer, "INCLUDE"))
177                     {
178                       roc.exclude = MV_SYSTEM;
179                     }
180                   else if (lex_match_id (lexer, "EXCLUDE"))
181                     {
182                       roc.exclude = MV_USER | MV_SYSTEM;
183                     }
184                   else
185                     {
186                       lex_error (lexer, NULL);
187                       return 2;
188                     }
189                   lex_force_match (lexer, ')');
190                 }
191               else if (lex_match_id (lexer, "TESTPOS"))
192                 {
193                   lex_force_match (lexer, '(');
194                   if (lex_match_id (lexer, "LARGE"))
195                     {
196                       roc.invert = false;
197                     }
198                   else if (lex_match_id (lexer, "SMALL"))
199                     {
200                       roc.invert = true;
201                     }
202                   else
203                     {
204                       lex_error (lexer, NULL);
205                       return 2;
206                     }
207                   lex_force_match (lexer, ')');
208                 }
209               else if (lex_match_id (lexer, "CI"))
210                 {
211                   lex_force_match (lexer, '(');
212                   lex_force_num (lexer);
213                   roc.ci = lex_number (lexer);
214                   lex_get (lexer);
215                   lex_force_match (lexer, ')');
216                 }
217               else if (lex_match_id (lexer, "DISTRIBUTION"))
218                 {
219                   lex_force_match (lexer, '(');
220                   if (lex_match_id (lexer, "FREE"))
221                     {
222                       roc.bi_neg_exp = false;
223                     }
224                   else if (lex_match_id (lexer, "NEGEXPO"))
225                     {
226                       roc.bi_neg_exp = true;
227                     }
228                   else
229                     {
230                       lex_error (lexer, NULL);
231                       return 2;
232                     }
233                   lex_force_match (lexer, ')');
234                 }
235               else
236                 {
237                   lex_error (lexer, NULL);
238                   return 2;
239                 }
240             }
241         }
242       else
243         {
244           lex_error (lexer, NULL);
245           break;
246         }
247     }
248
249   run_roc (ds, &roc);
250
251   return 1;
252 }
253
254
255
256
257 static void
258 do_roc (struct cmd_roc *roc, struct casereader *group, struct dictionary *dict);
259
260
261 static int
262 run_roc (struct dataset *ds, struct cmd_roc *roc)
263 {
264   struct dictionary *dict = dataset_dict (ds);
265   bool ok;
266   struct casereader *group;
267
268   struct casegrouper *grouper = casegrouper_create_splits (proc_open (ds), dict);
269   while (casegrouper_get_next_group (grouper, &group))
270     {
271       do_roc (roc, group, dataset_dict (ds));
272       casereader_destroy (group);
273     }
274   ok = casegrouper_destroy (grouper);
275   ok = proc_commit (ds) && ok;
276
277   return ok;
278 }
279
280
281 static void
282 do_roc (struct cmd_roc *roc, struct casereader *group, struct dictionary *dict)
283 {
284 }
285