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 
35 static void sortm (float ia[], int ib[], int n);
36 static void quicksort (float x[], int point[], int l, int nfilt);
37 static void filt1d(float [], int, int);
38 static void padext(float [], int);
39 static void hanning(float [], int);
40 
43 /*---------------------------------------------------------------------------*/
71 /*---------------------------------------------------------------------------*/
72 
73 extern 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 
125 static 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 
159 static 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 
208 static 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 
257 extern 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 
329 static 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 
358 static 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 $
405 Revision 1.3 2015/08/12 11:16:55 jim
406 Modified procedure names to protect namespace
407 
408 Revision 1.2 2015/08/07 13:06:54 jim
409 Fixed copyright to ESO
410 
411 Revision 1.1.1.1 2015/06/12 10:44:32 jim
412 Initial import
413 
414 Revision 1.3 2014/04/09 09:09:51 jim
415 Detabbed
416 
417 Revision 1.2 2013/08/28 05:43:22 jim
418 Fixed padext for the situation where all the row is bad
419 
420 Revision 1.1.1.1 2013-08-27 12:07:48 jim
421 Imported
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