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