1 /* -------------------------------------------------------------------
2 xldlas -- A Program for Statistics
3
4 Copyright (C) 1996, 1997 Thor Sigvaldason
5
6 This file contains all the filtering routines
7
8 -------------------------------------------------------------------*/
9
10 #include "xldlas.h"
11
12 extern void say_status(char the_status[XLDLASMAX_INPUT]);
13 extern void inhibit_input();
14 extern void reenable_input();
15 extern void simple_line_output(char which_routine[XLDLASMAX_INPUT], char the_output[XLDLASMAX_INPUT]);
16
17
do_detrend_filter(int f_begin,int f_end,int which_one)18 void do_detrend_filter(int f_begin, int f_end, int which_one)
19 {
20 int i, j, k, length, max;
21 float intercept, slope, running, temp1, temp2, coefs[3], mean;
22 char a_string[XLDLASMAX_INPUT];
23 double *bigmatrix;
24 double *matrix;
25 worksize = 0;
26 mean = 0.0;
27 if(f_end > data_matrix[which_one].obs) f_end = data_matrix[which_one].obs;
28 for(i = f_begin - 1; i < f_end; i++)
29 {
30 if(*(fvector[which_one] + i) != missing_value)
31 {
32 working[worksize] = *(fvector[which_one] + i);
33 mean = mean + working[worksize];
34 worksize++;
35 }
36 }
37 if(worksize < 2)
38 {
39 sprintf(a_string,"%s does not have enough observations", data_matrix[which_one].name);
40 fl_show_alert(a_string, "","",TRUE);
41 return;
42 }
43 mean = mean / worksize;
44 length = worksize;
45 bigmatrix = (double *) malloc ((length * 3) * sizeof (double));
46 if(!bigmatrix)
47 {
48 fl_show_alert("Not Enough Memory to Build Detrend Matrix","","",TRUE);
49 return;
50 }
51 for(i = 0; i < length; i++)
52 {
53 *(bigmatrix + i) = 1;
54 *(bigmatrix + i + length) = i+1;
55 *(bigmatrix + i + 2 * length) = working[i];
56 }
57 matrix = (double *) malloc (6 * sizeof (double));
58 if(!matrix)
59 {
60 fl_show_alert("Not Enough Memory to Build Detrend Sub-Matrix","","",TRUE);
61 free(bigmatrix);
62 return;
63 }
64 for(i = 0; i < 2; i++)
65 {
66 for(j = 0; j <= 2; j++)
67 {
68 running = 0.0;
69 for(k = 0; k < length; k++)
70 {
71 running = running + *(bigmatrix + k + (i * length)) * *(bigmatrix + k + (j * length));
72 }
73 *(matrix + i + (j * 2)) = running;
74 }
75 }
76 for(i = 0; i < 2; i++)
77 {
78 max = i;
79 for(j = i + 1; j < 2; j++)
80 {
81 temp1 = *(matrix + j + (i * 2));
82 temp2 = *(matrix + max + (i * 2));
83 if(fabs(temp1) > fabs(temp2)) max = j;
84 for(k = 0; k <= 2; k++)
85 {
86 running = *(matrix + i + (k * 2));
87 *(matrix + i + (k * 2)) = *(matrix + max + (k * 2));
88 *(matrix + max + (k * 2)) = running;
89 }
90 }
91 for(j = i + 1; j < 2; j++)
92 {
93 for(k = 2; k >= 0; k--)
94 {
95 temp1 = *(matrix + i + (i * 2));
96 if(temp1 == 0)
97 {
98 sprintf(a_string,"%s results in a singular matrix",data_matrix[which_one].name);
99 fl_show_alert(a_string,"Sorry, there's nothing I can do","",TRUE);
100 free(bigmatrix);
101 free(matrix);
102 return;
103 }
104 *(matrix + j + (k * 2)) = *(matrix + j + (k * 2)) - *(matrix + i + (k * 2)) * *(matrix + j + (i * 2)) / *(matrix + i + (i * 2));
105 }
106 }
107 }
108 for(i = 0; i < 3; i++)
109 {
110 coefs[i] = 0.0;
111 }
112 for(i = 1; i >= 0; i--)
113 {
114 running = 0.0;
115 for(j = i + 1; j <= 2; j++)
116 {
117 running = running + *(matrix + i + (j * 2)) * coefs[j];
118 temp1 = *(matrix + i + (i * 2));
119 if(temp1 == 0)
120 {
121 sprintf(a_string,"%s results in a singular matrix",data_matrix[which_one].name);
122 fl_show_alert(a_string,"Sorry, there's nothing I can do","",TRUE);
123 free(bigmatrix);
124 free(matrix);
125 return;
126 }
127 coefs[i]= ( *(matrix + i + (2 * 2)) - running ) / *(matrix + i + (i * 2));
128 }
129 }
130 intercept = coefs[0];
131 slope = coefs[1];
132 for(i = f_begin - 1; i < f_end; i++)
133 {
134 if(*(fvector[which_one] + i) != missing_value)
135 {
136 *(fvector[which_one] + i) = mean + *(fvector[which_one] + i) - (intercept + ((i - f_begin) * slope));
137 }
138 }
139 oktoquit = FALSE;
140 sprintf(a_string,"%s detrended (intercept = %f, slope %f)", data_matrix[which_one].name, intercept, slope);
141 simple_line_output("filter",a_string);
142 free(bigmatrix);
143 free(matrix);
144 }
145
do_outliers_filter(int f_begin,int f_end,int which_one)146 void do_outliers_filter(int f_begin, int f_end, int which_one)
147 {
148 int i, numb_removed, nrealobs;
149 float mean, variance, scratch;
150 char a_string[XLDLASMAX_INPUT];
151 worksize = 0;
152 mean = 0.0;
153 nrealobs = 0;
154 numb_removed = 0;
155 if(f_end > data_matrix[which_one].obs) f_end = data_matrix[which_one].obs;
156 for(i = f_begin - 1; i < f_end; i++)
157 {
158 working[worksize] = *(fvector[which_one] + i);
159 if(working[worksize] != missing_value)
160 {
161 mean = mean + working[worksize];
162 nrealobs++;
163 }
164 worksize++;
165 }
166 if(nrealobs < 2)
167 {
168 sprintf(a_string,"%s does not have enough observations", data_matrix[which_one].name);
169 fl_show_alert(a_string, "","",TRUE);
170 return;
171 }
172 mean = mean / nrealobs;
173 scratch = 0.0;
174 variance = 0.0;
175 for(i = 0; i < worksize; i++)
176 {
177 if(working[i] != missing_value)
178 {
179 scratch = scratch + (working[i] - mean);
180 variance = variance + pow((working[i] - mean),2);
181 }
182 }
183 variance = (variance - scratch * scratch / nrealobs) / nrealobs;
184 variance = pow(variance,0.5);
185 for(i = 0; i < worksize; i++)
186 {
187 if(working[i] != missing_value)
188 {
189 if(working[i] < mean - 3.0 * variance || working[i] > mean + 3.0 * variance)
190 {
191 numb_removed++;
192 working[i] = missing_value;
193 }
194 }
195 }
196 if(numb_removed > 0)
197 {
198 for(i = 0; i < worksize; i++)
199 {
200 *(fvector[which_one] + (f_begin - 1) + i) = working[i];
201 }
202 oktoquit = FALSE;
203 }
204 sprintf(a_string,"Outliers removed from %s (%d value(s) changed)", data_matrix[which_one].name, numb_removed);
205 simple_line_output("filter",a_string);
206 }
207
do_zo_filter(int f_begin,int f_end,int which_one)208 void do_zo_filter(int f_begin, int f_end, int which_one)
209 {
210 int i;
211 float smallest, largest;
212 char a_string[XLDLASMAX_INPUT];
213 smallest = missing_value;
214 largest = missing_value;
215 if(f_end > data_matrix[which_one].obs) f_end = data_matrix[which_one].obs;
216 for(i = f_begin - 1; i < f_end; i++)
217 {
218 if(*(fvector[which_one] + (f_begin -1) + i) != missing_value)
219 {
220 if(smallest == missing_value || smallest > *(fvector[which_one] + (f_begin - 1) + i))
221 {
222 smallest = *(fvector[which_one] + (f_begin - 1) + i);
223 }
224 if(largest == missing_value || largest < *(fvector[which_one] + (f_begin - 1) + i))
225 {
226 largest = *(fvector[which_one] + (f_begin - 1) + i);
227 }
228 }
229 }
230 if(smallest == missing_value)
231 {
232 fl_show_alert("No observations in selected range","","",TRUE);
233 return;
234 }
235 if(smallest == largest)
236 {
237 fl_show_alert("No variation in selected range","(I'm leaving the data unchanged)","",TRUE);
238 return;
239 }
240 for(i = f_begin -1; i < f_end; i++)
241 {
242 if(*(fvector[which_one] + (f_begin -1) + i) != missing_value)
243 {
244 *(fvector[which_one] + (f_begin - 1) + i) = ( *(fvector[which_one] + (f_begin - 1) + i) - smallest ) / ( largest - smallest);
245 }
246 }
247 sprintf(a_string,"Values of %s (obs %i to %i) transformed to lie between 0.0 and 1.0", data_matrix[which_one].name, f_begin, f_end);
248 simple_line_output("filter",a_string);
249 oktoquit=FALSE;
250 }
251
do_filter(FL_OBJECT * obj,long arg)252 void do_filter(FL_OBJECT *obj, long arg)
253 {
254 int numb_filters, to_filter[MAX_VARS], i;
255 numb_filters = 0;
256 for(i = 0; i < numb_variables; i++)
257 {
258 if(fl_isselected_browser_line(filter_browser, i+1))
259 {
260 to_filter[numb_filters] = i;
261 numb_filters++;
262 }
263 }
264 if(numb_filters == 0)
265 {
266 fl_show_alert("No Variable(s) Selected","","",TRUE);
267 return;
268 }
269 all_start = fl_get_counter_value(filter_from_counter);
270 all_stop = fl_get_counter_value(filter_to_counter);
271 if(all_stop < all_start)
272 {
273 fl_show_alert("From Value greater than To Value","","",TRUE);
274 return;
275 }
276 say_status("Filtering...");
277 if(fl_get_button(filter_outliers_button) == TRUE)
278 {
279 for(i = 0; i < numb_filters; i++)
280 {
281 do_outliers_filter(all_start, all_stop, to_filter[i]);
282 }
283 }
284 if(fl_get_button(filter_detrend_button) == TRUE)
285 {
286 for(i = 0; i < numb_filters; i++)
287 {
288 do_detrend_filter(all_start, all_stop, to_filter[i]);
289 }
290 }
291 if(fl_get_button(filter_zo_button) == TRUE)
292 {
293 for(i = 0; i < numb_filters; i++)
294 {
295 do_zo_filter(all_start, all_stop, to_filter[i]);
296 }
297 }
298 say_status("Waiting for filter specs...");
299 }
300
start_filters(int filt_numb)301 void start_filters(int filt_numb)
302 {
303 int i, largest;
304 inhibit_input();
305 largest = 0;
306 fl_clear_browser(filter_browser);
307 for(i = 0; i < numb_variables; i++)
308 {
309 if(largest < data_matrix[i].obs) largest = data_matrix[i].obs;
310 fl_addto_browser(filter_browser,data_matrix[i].name);
311 }
312 fl_set_counter_value(filter_from_counter, 1);
313 fl_set_counter_bounds(filter_from_counter, 1, largest);
314 fl_set_counter_value(filter_to_counter, largest);
315 fl_set_counter_bounds(filter_to_counter, 1, largest);
316 say_status("Waiting for filtering specs...");
317 if(window_geometry[XLDLAS_FILTER][0] != -1)
318 {
319 fl_set_form_geometry(filter_window,
320 window_geometry[XLDLAS_FILTER][0],
321 window_geometry[XLDLAS_FILTER][1],
322 window_geometry[XLDLAS_FILTER][2],
323 window_geometry[XLDLAS_FILTER][3]);
324 }
325 fl_show_form(filter_window,FL_PLACE_FREE,FL_FULLBORDER,"Do Some Filtering");
326 fl_set_button(filter_outliers_button, 0);
327 fl_set_button(filter_detrend_button, 0);
328 fl_set_button(filter_zo_button, 0);
329 if(filt_numb == 1) fl_set_button(filter_outliers_button, 1);
330 if(filt_numb == 2) fl_set_button(filter_detrend_button, 1);
331 if(filt_numb == 3) fl_set_button(filter_zo_button, 1);
332 }
333
done_filter(FL_OBJECT * obj,long arg)334 void done_filter(FL_OBJECT *obj, long arg)
335 {
336 window_geometry[XLDLAS_FILTER][0] = obj->form->x;
337 window_geometry[XLDLAS_FILTER][1] = obj->form->y;
338 window_geometry[XLDLAS_FILTER][2] = obj->form->w;
339 window_geometry[XLDLAS_FILTER][3] = obj->form->h;
340 fl_hide_form(filter_window);
341 reenable_input();
342 say_status("Ready");
343 }
344
filter_routines(FL_OBJECT * menu,long user_data)345 void filter_routines(FL_OBJECT *menu, long user_data)
346 {
347 int choice;
348 choice = fl_get_menu(menu);
349 start_filters(choice);
350 }
351
352