VIRCAM Pipeline 2.3.12
imcore_filter.c
1/* $Id: imcore_filter.c,v 1.3 2015/08/12 11:16:55 jim Exp $
2 *
3 * This file is part of the CASU Pipeline utilities
4 * Copyright (C) 2015 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jim $
23 * $Date: 2015/08/12 11:16:55 $
24 * $Revision: 1.3 $
25 * $Name: $
26 */
27
28#include <stdlib.h>
29
30#include "util.h"
31#include "imcore.h"
32
33/* Function prototypes */
34
35static void sortm (float ia[], int ib[], int n);
36static void quicksort (float x[], int point[], int l, int nfilt);
37static void filt1d(float [], int, int);
38static void padext(float [], int);
39static void hanning(float [], int);
40
43/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73extern void imcore_bfilt (float **xbuf, int nx, int ny) {
74 float *ybuf, *save;
75 int mfilt = 5, j, k;
76
77/* Allocate temporary storage */
78 ybuf = (float *) cpl_malloc(MAX(nx,ny) * sizeof(float));
79 save = (float *) cpl_malloc((nx+1) * ny * sizeof(float));
80/* if(!ybuf || !save) bombout(1, "malloc"); */
81
82/* median filter across */
83 for(k = 0; k < ny; k++) {
84 for(j = 0; j < nx; j++) {
85 save[(nx+1)*k+j] = xbuf[k][j];
86 ybuf[j] = xbuf[k][j];
87 }
88 filt1d(ybuf, nx, mfilt);
89 for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
90 }
91
92/* and now down */
93 for(k = 0; k < nx; k++) {
94 for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
95 filt1d(ybuf, ny, mfilt);
96 for(j = 0; j < ny; j++)
97/* make sure median filtered values are not large than original */
98 if(save[(nx+1)*j+k] > -1000.0)
99 xbuf[j][k] = MIN(save[(nx+1)*j+k], ybuf[j]);
100 }
101
102/* now repeat with linear filters across */
103 for(k = 0; k < ny; k++) {
104 for(j = 0; j < nx; j++) ybuf[j] = xbuf[k][j];
105 hanning(ybuf, nx);
106 for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
107 }
108
109/* and now down */
110 for(k = 0; k < nx; k++) {
111 for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
112 hanning(ybuf, ny);
113 for(j = 0; j < ny; j++) xbuf[j][k] = ybuf[j];
114 }
115
116/* Free temporary storage */
117 cpl_free((void *) ybuf);
118 cpl_free((void *) save);
119}/* --------------------------------------- ------------------------------ */
120
123/* does median filtering allowing for unmeasured entries */
124
125static void filt1d (float ybuf[], int mpt, int mfilt) {
126 float *wbuf;
127 int i, irc;
128/* Allocate temporary storage */
129 wbuf = (float *) cpl_malloc(mpt * sizeof(float));
130/* if(!wbuf) bombout(1, "malloc"); */
131
132 irc = 0;
133 for(i = 0; i < mpt; i++){
134 if(ybuf[i] > -1000.0){
135 wbuf[irc] = ybuf[i];
136 irc++;
137 }
138 }
139 if(irc == 0) {
140 cpl_free((void *) wbuf);
141 return;
142 }
143 imcore_median(wbuf, irc, mfilt);
144 irc = 0;
145 for(i = 0; i < mpt; i++){
146 if(ybuf[i] > -1000.0){
147 ybuf[i] = wbuf[irc];
148 irc++;
149 }
150 }
151 padext(ybuf, mpt);
152/* Free temporary storage */
153 cpl_free((void *) wbuf);
154}
155
156
157/* pads out array with missing points and linearly extrapolates the ends */
158
159static void padext (float x[], int n) {
160 int i, j, ilow, ihih=0, ic;
161 float xlow, xhih, slope, t1 ,t2;
162/* elements <= -1000.0 are treated as missing */
163 i = 0;
164 while(i < n && x[i] <= -1000.0) i++;
165 ilow = i;
166 for(i = ilow+1; i < n; i++){
167 if(x[i] <= -1000.0) {
168 ic = 1;
169 if (i < n - 1) {
170 while(x[i+ic] <= -1000.0) {
171 ic++;
172 if (i+ic >= n-1)
173 break;
174 }
175 }
176 if(i+ic < n-1){
177 xlow = x[i-1];
178 xhih = x[i+ic];
179 for(j = 0; j < ic; j++){
180 t2 = ((float) j+1)/((float) ic+1);
181 t1 = 1.0 - t2;
182 x[i+j] = t1*xlow+t2*xhih;
183 }
184 }
185 } else {
186 ihih = i;
187 }
188 }
189/* linear extrapolation of ends */
190 if(ilow > 0){
191 if (ilow < n - 1)
192 slope = x[ilow+1]-x[ilow];
193 else
194 slope = 0.0;
195 for(i = 0; i < ilow; i++) x[i] = x[ilow]-slope*(ilow-i);
196 }
197 if(ihih < n-1) {
198 if (ihih > 0)
199 slope = x[ihih]-x[ihih-1];
200 else
201 slope = 0.0;
202 for(i = ihih+1; i < n; i++) x[i] = x[ihih]+slope*(i-ihih);
203 }
204}
205
206/* performs linear filtering on array xbuf */
207
208static void hanning (float xbuf[], int npt) {
209 float *ybuf;
210 float sum = 0.0, xmns, xmnf;
211 int nfilt = 3, i, il, ilow, nelem;
212
213 if(npt <= nfilt)
214 return;
215
216 /* set first and last edges equal */
217 il = nfilt/2;
218 ilow = MAX(3,nfilt/4);
219 ilow = (ilow/2)*2 + 1;
220
221 for(i = 0; i < ilow; i++)
222 sum += xbuf[i];
223
224 xmns = sum/((float) ilow);
225
226 sum=0.0;
227 for(i = 0; i < ilow; i++)
228 sum += xbuf[npt-1-i];
229
230 xmnf = sum/((float) ilow);
231
232 /* allocate ybuf array */
233 nelem = npt + nfilt; /* Max. number of elements req'd */
234
235 ybuf = (float *) cpl_malloc(nelem * sizeof(float));
236/* if(!ybuf) */
237/* bombout(1, "malloc"); */
238
239 /* reflect edges before filtering */
240 for(i = 0; i < il; i++) {
241 ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
242 ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
243 }
244
245 for(i = 0; i < npt; i++)
246 ybuf[i+il] = xbuf[i];
247
248 /* do linear filtering on rest */
249 for(i = 0; i < npt; i++)
250 xbuf[i] = 0.25 * (ybuf[i] + 2.0 * ybuf[i+1] + ybuf[i+2]); /* 1-2-1 Hanning weighting */
251
252 cpl_free((void *) ybuf);
253}
254
255/* performs median filtering on array xbuf */
256
257extern void imcore_median (float xbuf[], int npt, int nfilt) {
258 float *ybuf, *array;
259 float xmns, xmnf;
260 int *point;
261 int nfo2p1, i, il, ilow, j, jl, jh, nelem, l=0;
262
263 if((nfilt/2)*2 == nfilt) nfilt++;
264 if(npt <= nfilt) return;
265 nfo2p1 = nfilt/2;
266
267 /* allocate ybuf, array, point */
268 nelem = npt + nfilt; /* Max. number of elements req'd */
269 ybuf = (float *) cpl_malloc(nelem * sizeof(float));
270/* if(!ybuf) */
271/* bombout(1, "malloc"); */
272 array = (float *) cpl_malloc(nfilt * sizeof(float));
273 point = (int *) cpl_malloc(nfilt * sizeof(int));
274/* if(!array || !point) */
275/* bombout(1, "malloc"); */
276
277 /* set first and last edges equal */
278 il = nfilt/2;
279 ilow = MAX(3, nfilt/4);
280 ilow = (ilow/2)*2 + 1;
281
282 for(i = 0; i < ilow; i++) array[i] = xbuf[i];
283 sortm(array, point, ilow);
284 xmns = array[ilow/2];
285
286 for(i = 0; i < ilow; i++) array[i] = xbuf[npt-1-i];
287 sortm(array, point, ilow);
288 xmnf = array[ilow/2];
289
290 /* reflect edges before filtering */
291 for(i = 0; i < il; i++) {
292 ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
293 ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
294 }
295 for(i = 0; i < npt; i++) ybuf[i+il] = xbuf[i];
296
297 /* do median filtering on rest */
298 for(i = 0; i < nfilt; i++) {
299 array[i] = ybuf[i];
300 point[i] = i+1;
301 }
302
303 sortm(array, point, nfilt);
304
305 xbuf[0] = array[nfo2p1];
306 jl = nfilt;
307 jh = nfilt+npt-1;
308 for(j = jl; j < jh; j++) {
309
310 for(i = 0; i < nfilt; i++) {
311 if(point[i] != 1) {
312 point[i]--;
313 continue;
314 }
315 point[i] = nfilt;
316 array[i] = ybuf[j];
317 l = i;
318 }
319 quicksort(array, point, l, nfilt);
320 xbuf[j-jl+1] = array[nfo2p1];
321 }
322
323 /* Free temporary arrays */
324 cpl_free((void *) point);
325 cpl_free((void *) array);
326 cpl_free((void *) ybuf);
327}
328
329static void sortm (float ia[], int ib[], int n) {
330 int i,j, ii, jj, ifin, iu;
331 float it;
332
333 jj = 2;
334 while(jj < n) jj = 2 * jj;
335 jj = MIN(n,(3 * jj)/4 - 1);
336 while(jj > 1) {
337 jj = jj/2;
338 ifin = n - jj;
339 for(ii = 0; ii < ifin; ii++) {
340 i = ii;
341 j = i + jj;
342 if(ia[i] <= ia[j]) continue;
343 it = ia[j];
344 iu = ib[j];
345 do {
346 ia[j] = ia[i];
347 ib[j] = ib[i];
348 j = i;
349 i = i - jj;
350 if (i < 0) break;
351 } while(ia[i] > it);
352 ia[j] = it;
353 ib[j] = iu;
354 }
355 }
356}
357
358static void quicksort (float x[], int point[], int l, int nfilt) {
359 float test, temp;
360 int i, it, j, npt, ii;
361
362 test = x[l];
363 j = nfilt;
364 for(i = 0; i < nfilt; i++) {
365 if(i != l && test <= x[i]) {
366 j = i;
367 break;
368 }
369 }
370 if(j - 1 == l) return;
371
372 if(j < l) {
373 temp = x[l];
374 it = point[l];
375 npt = l - j;
376 for(i = 0; i < npt; i++) {
377 ii = l - i - 1;
378 x[ii+1] = x[ii];
379 point[ii+1] = point[ii];
380 }
381 x[j] = temp;
382 point[j] = it;
383 }
384 else if(j > l) {
385 temp = x[l];
386 it = point[l];
387 j--;
388 npt = j - l;
389 if(npt != 0) {
390 for(i = 0; i < npt; i++) {
391 ii = l + i + 1;
392 x[ii-1] = x[ii];
393 point[ii-1] = point[ii];
394 }
395 }
396 x[j] = temp;
397 point[j] = it;
398 }
399}
400
401
402/*
403
404$Log: imcore_filter.c,v $
405Revision 1.3 2015/08/12 11:16:55 jim
406Modified procedure names to protect namespace
407
408Revision 1.2 2015/08/07 13:06:54 jim
409Fixed copyright to ESO
410
411Revision 1.1.1.1 2015/06/12 10:44:32 jim
412Initial import
413
414Revision 1.3 2014/04/09 09:09:51 jim
415Detabbed
416
417Revision 1.2 2013/08/28 05:43:22 jim
418Fixed padext for the situation where all the row is bad
419
420Revision 1.1.1.1 2013-08-27 12:07:48 jim
421Imported
422
423
424*/
void imcore_bfilt(float **xbuf, int nx, int ny)
Do bilinear median and linear filtering on background values.
Definition: imcore_filter.c:73