VIRCAM Pipeline  1.3.4
imcore_filter.c
1 /* $Id: imcore_filter.c,v 1.6 2010-09-09 12:09:57 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 Cambridge Astronomy Survey Unit
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: 2010-09-09 12:09:57 $
24  * $Revision: 1.6 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #include <stdlib.h>
29 
30 #include "util.h"
31 #include "imcore.h"
32 
33 /* Function prototypes */
34 
35 static void sortm (float ia[], int ib[], int n);
36 static void quicksort (float x[], int point[], int l, int nfilt);
37 
40 /*---------------------------------------------------------------------------*/
68 /*---------------------------------------------------------------------------*/
69 
70 extern void bfilt (float **xbuf, int nx, int ny) {
71  float *ybuf, *save;
72  int mfilt = 5, j, k;
73 
74 /* Allocate temporary storage */
75  ybuf = (float *) malloc(MAX(nx,ny) * sizeof(float));
76  save = (float *) malloc((nx+1) * ny * sizeof(float));
77 /* if(!ybuf || !save) bombout(1, "malloc"); */
78 
79 /* median filter across */
80  for(k = 0; k < ny; k++) {
81  for(j = 0; j < nx; j++) {
82  save[(nx+1)*k+j] = xbuf[k][j];
83  ybuf[j] = xbuf[k][j];
84  }
85  filt1d(ybuf, nx, mfilt);
86  for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
87  }
88 
89 /* and now down */
90  for(k = 0; k < nx; k++) {
91  for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
92  filt1d(ybuf, ny, mfilt);
93  for(j = 0; j < ny; j++)
94 /* make sure median filtered values are not large than original */
95  if(save[(nx+1)*j+k] > -1000.0)
96  xbuf[j][k] = MIN(save[(nx+1)*j+k], ybuf[j]);
97  }
98 
99 /* now repeat with linear filters across */
100  for(k = 0; k < ny; k++) {
101  for(j = 0; j < nx; j++) ybuf[j] = xbuf[k][j];
102  hanning(ybuf, nx);
103  for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
104  }
105 
106 /* and now down */
107  for(k = 0; k < nx; k++) {
108  for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
109  hanning(ybuf, ny);
110  for(j = 0; j < ny; j++) xbuf[j][k] = ybuf[j];
111  }
112 
113 /* Free temporary storage */
114  free((void *) ybuf);
115  free((void *) save);
116 }/* --------------------------------------- ------------------------------ */
117 
120 /* does median filtering allowing for unmeasured entries */
121 
122 void filt1d (float ybuf[], int mpt, int mfilt) {
123  float *wbuf;
124  int i, irc;
125 /* Allocate temporary storage */
126  wbuf = (float *) malloc(mpt * sizeof(float));
127 /* if(!wbuf) bombout(1, "malloc"); */
128 
129  irc = 0;
130  for(i = 0; i < mpt; i++){
131  if(ybuf[i] > -1000.0){
132  wbuf[irc] = ybuf[i];
133  irc++;
134  }
135  }
136  if(irc == 0) {
137  free((void *) wbuf);
138  return;
139  }
140  median(wbuf, irc, mfilt);
141  irc = 0;
142  for(i = 0; i < mpt; i++){
143  if(ybuf[i] > -1000.0){
144  ybuf[i] = wbuf[irc];
145  irc++;
146  }
147  }
148  padext(ybuf, mpt);
149 /* Free temporary storage */
150  free((void *) wbuf);
151 }
152 
153 
154 /* pads out array with missing points and linearly extrapolates the ends */
155 
156 void padext (float x[], int n) {
157  int i, j, ilow, ihih=0, ic;
158  float xlow, xhih, slope, t1 ,t2;
159 /* elements <= -1000.0 are treated as missing */
160  i = 0;
161  while(x[i] <= -1000.0) i++;
162  ilow = i;
163  for(i = ilow+1; i < n; i++){
164  if(x[i] <= -1000.0) {
165  ic = 1;
166  if (i < n - 1) {
167  while(x[i+ic] <= -1000.0) {
168  ic++;
169  if (i+ic >= n-1)
170  break;
171  }
172  }
173  if(i+ic < n-1){
174  xlow = x[i-1];
175  xhih = x[i+ic];
176  for(j = 0; j < ic; j++){
177  t2 = ((float) j+1)/((float) ic+1);
178  t1 = 1.0 - t2;
179  x[i+j] = t1*xlow+t2*xhih;
180  }
181  }
182  } else {
183  ihih = i;
184  }
185  }
186 /* linear extrapolation of ends */
187  if(ilow > 0){
188  slope = x[ilow+1]-x[ilow];
189  for(i = 0; i < ilow; i++) x[i] = x[ilow]-slope*(ilow-i);
190  }
191  if(ihih < n-1) {
192  slope = x[ihih]-x[ihih-1];
193  for(i = ihih+1; i < n; i++) x[i] = x[ihih]+slope*(i-ihih);
194  }
195 }
196 
197 /* performs linear filtering on array xbuf */
198 
199 void hanning (float xbuf[], int npt) {
200  float *ybuf;
201  float sum = 0.0, xmns, xmnf;
202  int nfilt = 3, i, il, ilow, nelem;
203 
204  if(npt <= nfilt)
205  return;
206 
207  /* set first and last edges equal */
208  il = nfilt/2;
209  ilow = MAX(3,nfilt/4);
210  ilow = (ilow/2)*2 + 1;
211 
212  for(i = 0; i < ilow; i++)
213  sum += xbuf[i];
214 
215  xmns = sum/((float) ilow);
216 
217  sum=0.0;
218  for(i = 0; i < ilow; i++)
219  sum += xbuf[npt-1-i];
220 
221  xmnf = sum/((float) ilow);
222 
223  /* allocate ybuf array */
224  nelem = npt + nfilt; /* Max. number of elements req'd */
225 
226  ybuf = (float *) malloc(nelem * sizeof(float));
227 /* if(!ybuf) */
228 /* bombout(1, "malloc"); */
229 
230  /* reflect edges before filtering */
231  for(i = 0; i < il; i++) {
232  ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
233  ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
234  }
235 
236  for(i = 0; i < npt; i++)
237  ybuf[i+il] = xbuf[i];
238 
239  /* do linear filtering on rest */
240  for(i = 0; i < npt; i++)
241  xbuf[i] = 0.25 * (ybuf[i] + 2.0 * ybuf[i+1] + ybuf[i+2]); /* 1-2-1 Hanning weighting */
242 
243  free((void *) ybuf);
244 }
245 
246 /* performs median filtering on array xbuf */
247 
248 void median (float xbuf[], int npt, int nfilt) {
249  float *ybuf, *array;
250  float xmns, xmnf;
251  int *point;
252  int nfo2p1, i, il, ilow, j, jl, jh, nelem, l=0;
253 
254  if((nfilt/2)*2 == nfilt) nfilt++;
255  if(npt <= nfilt) return;
256  nfo2p1 = nfilt/2;
257 
258  /* allocate ybuf, array, point */
259  nelem = npt + nfilt; /* Max. number of elements req'd */
260  ybuf = (float *) malloc(nelem * sizeof(float));
261 /* if(!ybuf) */
262 /* bombout(1, "malloc"); */
263  array = (float *) malloc(nfilt * sizeof(float));
264  point = (int *) malloc(nfilt * sizeof(int));
265 /* if(!array || !point) */
266 /* bombout(1, "malloc"); */
267 
268  /* set first and last edges equal */
269  il = nfilt/2;
270  ilow = MAX(3, nfilt/4);
271  ilow = (ilow/2)*2 + 1;
272 
273  for(i = 0; i < ilow; i++) array[i] = xbuf[i];
274  sortm(array, point, ilow);
275  xmns = array[ilow/2];
276 
277  for(i = 0; i < ilow; i++) array[i] = xbuf[npt-1-i];
278  sortm(array, point, ilow);
279  xmnf = array[ilow/2];
280 
281  /* reflect edges before filtering */
282  for(i = 0; i < il; i++) {
283  ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
284  ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
285  }
286  for(i = 0; i < npt; i++) ybuf[i+il] = xbuf[i];
287 
288  /* do median filtering on rest */
289  for(i = 0; i < nfilt; i++) {
290  array[i] = ybuf[i];
291  point[i] = i+1;
292  }
293 
294  sortm(array, point, nfilt);
295 
296  xbuf[0] = array[nfo2p1];
297  jl = nfilt;
298  jh = nfilt+npt-1;
299  for(j = jl; j < jh; j++) {
300 
301  for(i = 0; i < nfilt; i++) {
302  if(point[i] != 1) {
303  point[i]--;
304  continue;
305  }
306  point[i] = nfilt;
307  array[i] = ybuf[j];
308  l = i;
309  }
310  quicksort(array, point, l, nfilt);
311  xbuf[j-jl+1] = array[nfo2p1];
312  }
313 
314  /* Free temporary arrays */
315  free((void *) point);
316  free((void *) array);
317  free((void *) ybuf);
318 }
319 
320 static void sortm (float ia[], int ib[], int n) {
321  int i,j, ii, jj, ifin, iu;
322  float it;
323 
324  jj = 2;
325  while(jj < n) jj = 2 * jj;
326  jj = MIN(n,(3 * jj)/4 - 1);
327  while(jj > 1) {
328  jj = jj/2;
329  ifin = n - jj;
330  for(ii = 0; ii < ifin; ii++) {
331  i = ii;
332  j = i + jj;
333  if(ia[i] <= ia[j]) continue;
334  it = ia[j];
335  iu = ib[j];
336  do {
337  ia[j] = ia[i];
338  ib[j] = ib[i];
339  j = i;
340  i = i - jj;
341  if (i < 0) break;
342  } while(ia[i] > it);
343  ia[j] = it;
344  ib[j] = iu;
345  }
346  }
347 }
348 
349 static void quicksort (float x[], int point[], int l, int nfilt) {
350  float test, temp;
351  int i, it, j, npt, ii;
352 
353  test = x[l];
354  j = nfilt;
355  for(i = 0; i < nfilt; i++) {
356  if(i != l && test <= x[i]) {
357  j = i;
358  break;
359  }
360  }
361  if(j - 1 == l) return;
362 
363  if(j < l) {
364  temp = x[l];
365  it = point[l];
366  npt = l - j;
367  for(i = 0; i < npt; i++) {
368  ii = l - i - 1;
369  x[ii+1] = x[ii];
370  point[ii+1] = point[ii];
371  }
372  x[j] = temp;
373  point[j] = it;
374  }
375  else if(j > l) {
376  temp = x[l];
377  it = point[l];
378  j--;
379  npt = j - l;
380  if(npt != 0) {
381  for(i = 0; i < npt; i++) {
382  ii = l + i + 1;
383  x[ii-1] = x[ii];
384  point[ii-1] = point[ii];
385  }
386  }
387  x[j] = temp;
388  point[j] = it;
389  }
390 }
391 
392 
393 /*
394 
395 $Log: not supported by cvs2svn $
396 Revision 1.5 2008/07/10 13:05:35 jim
397 Modified code in padext to avoid valgrind warnings
398 
399 Revision 1.4 2008/01/22 19:42:17 jim
400 Fixed memory allocation error
401 
402 Revision 1.3 2006/08/01 11:27:54 jim
403 Modifications to imcore background estimation and to add ability to
404 specify the smoothing kernel width
405 
406 Revision 1.2 2006/07/11 14:51:02 jim
407 Fixed small bug in the range of the main loop
408 
409 Revision 1.1 2005/09/13 13:25:29 jim
410 Initial entry after modifications to make cpl compliant
411 
412 
413 */
void bfilt(float **xbuf, int nx, int ny)
Do bilinear median and linear filtering on background values.
Definition: imcore_filter.c:70