VIRCAM Pipeline  1.3.4
vircam_filt.c
1 /* $Id: vircam_filt.c,v 1.4 2012-07-20 09:49:14 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2008 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: 2012-07-20 09:49:14 $
24  * $Revision: 1.4 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 /* Includes */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <cpl.h>
35 #include <math.h>
36 #include <string.h>
37 
38 #include "vircam_utils.h"
39 #include "vircam_filt.h"
40 
41 static void docols(float *data, unsigned char *bpm, int nx, int ny,
42  int filter, int stat);
43 static void dorows(float *data, unsigned char *bpm, int nx, int ny,
44  int filter, int stat);
45 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
46  int whichstat, float **ybuf, unsigned char **ybbuf,
47  int *nbuf);
48 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
49  int whichstat, int newl, float *outval,
50  unsigned char *outbp);
51 static void quickie(float *array, unsigned char *iarray, int *iarray2,
52  int lll, int narray);
53 static void sortm(float *a1, unsigned char *a2, int *a3, int n);
54 static void plugholes(float *data, unsigned char *bpm, int nx);
55 
56 /* Global variables */
57 
58 static float sum;
59 static float sumw;
60 static int naver;
61 static float nextw;
62 static float lastw;
63 static float nextval;
64 static float lastval;
65 static short int nextc;
66 static short int lastc;
67 
82 /*---------------------------------------------------------------------------*/
120 /*---------------------------------------------------------------------------*/
121 
122 extern void vircam_bfilt(float *data, unsigned char *bpm, int nx, int ny,
123  int filt, int stat, int axis) {
124 
125  /* Order the reset correction so that the first smoothing is done
126  across the axis of the anomaly */
127 
128  if (axis == 1) {
129  dorows(data,bpm,nx,ny,filt,stat);
130  docols(data,bpm,nx,ny,filt,stat);
131  } else {
132  docols(data,bpm,nx,ny,filt,stat);
133  dorows(data,bpm,nx,ny,filt,stat);
134  }
135 
136 }
137 
138 /*---------------------------------------------------------------------------*/
168 /*---------------------------------------------------------------------------*/
169 
170 static void docols(float *data, unsigned char *bpm, int nx, int ny,
171  int filter, int stat) {
172  int j,k,indx,nbuf;
173  unsigned char *goodval,*bbuf;
174  float *dbuf;
175 
176  /* Get out of here if you've asked for something stupid */
177 
178  if (filter <= 0)
179  return;
180 
181  /* Get some workspace */
182 
183  nbuf = max(nx,ny);
184  dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
185  bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
186  goodval = cpl_malloc(ny*sizeof(*goodval));
187 
188  /* Now loop for each column and load a column into the buffer */
189 
190  for (k = 0; k < nx; k++) {
191  memset((char *)goodval,0,ny);
192  for (j = 0; j < ny; j++) {
193  indx = j*nx + k;
194  dbuf[j] = data[indx];
195  bbuf[j] = bpm[indx];
196  }
197 
198  /* Do the smoothing and plug any holes where there are bad pixels */
199 
200  vircam_dostat(dbuf,bbuf,goodval,ny,filter,stat);
201  plugholes(dbuf,goodval,ny);
202 
203  /* Transfer the data back */
204 
205  for (j = 0; j < ny; j++) {
206  indx = j*nx + k;
207  data[indx] = dbuf[j];
208  }
209  }
210 
211  /* Ditch workspace */
212 
213  freespace(dbuf);
214  freespace(bbuf);
215  freespace(goodval);
216 }
217 
218 /*---------------------------------------------------------------------------*/
248 /*---------------------------------------------------------------------------*/
249 
250 static void dorows(float *data, unsigned char *bpm, int nx, int ny,
251  int filter, int stat) {
252  int j,k,indx,nbuf;
253  unsigned char *goodval,*bbuf;
254  float *dbuf;
255 
256  /* Get out of here if you've asked for something stupid */
257 
258  if (filter <= 0)
259  return;
260 
261  /* Get some workspace */
262 
263  nbuf = max(nx,ny);
264  dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
265  bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
266  goodval = cpl_malloc(nx*sizeof(*goodval));
267 
268  /* Now loop for each row and load a row into the buffer */
269 
270  for (k = 0; k < ny; k++) {
271  memset((char *)goodval,0,nx);
272  for (j = 0; j < nx; j++) {
273  indx = k*nx + j;
274  dbuf[j] = data[indx];
275  bbuf[j] = bpm[indx];
276  }
277 
278  /* Do the smoothing and plug any holes where there are bad pixels */
279 
280  vircam_dostat(dbuf,bbuf,goodval,nx,filter,stat);
281  plugholes(dbuf,goodval,nx);
282 
283  /* Transfer the data back */
284 
285  for (j = 0; j < nx; j++) {
286  indx = k*nx + j;
287  data[indx] = dbuf[j];
288  }
289  }
290 
291  /* Ditch workspace */
292 
293  freespace(dbuf);
294  freespace(bbuf);
295  freespace(goodval);
296 }
297 
298 /*---------------------------------------------------------------------------*/
328 /*---------------------------------------------------------------------------*/
329 
330 extern void vircam_dostat(float *data, unsigned char *bpm,
331  unsigned char *goodval, int npts, int nfilt,
332  int whichstat) {
333  int nbuf,jl,jh,j,*ipoint,ifree,i;
334  unsigned char *ybbuf,*barray,bval;
335  float *ybuf,*darray,val;
336 
337  /* check to make sure the filter size is odd */
338 
339  if ((nfilt/2)*2 == nfilt)
340  nfilt++;
341 
342  /* Do the wrap around and load the data into an oversized array */
343 
344  wraparound(data,bpm,npts,nfilt,whichstat,&ybuf,&ybbuf,&nbuf);
345 
346  /* Get some data buffers and initialise them */
347 
348  darray = cpl_malloc(nfilt*sizeof(*darray));
349  barray = cpl_malloc(nfilt*sizeof(*barray));
350  ipoint = cpl_malloc(nfilt*sizeof(*ipoint));
351  memmove((char *)darray,(char *)ybuf,nfilt*sizeof(*ybuf));
352  memmove((char *)barray,(char *)ybbuf,nfilt*sizeof(*ybbuf));
353  for (j = 0; j < nfilt; j++)
354  ipoint[j] = j;
355 
356  /* Do the stat for the first point */
357 
358  ifree = 0;
359  medavg(darray,barray,ipoint,nfilt,whichstat,-1,&val,&bval);
360  if (! bval)
361  data[0] = val;
362  goodval[0] = bval;
363 
364  /* Now do the stats for all subsequent points. The oldest point in the
365  buffer is replaced by the next raw point */
366 
367  jl = nfilt;
368  jh = nfilt + npts - 2;
369  for (j = jl; j <= jh; j++) {
370  for (i = 0; i < nfilt; i++) {
371  if (ipoint[i] == 0) {
372  ifree = i;
373  ipoint[i] = nfilt - 1;
374  lastval = darray[ifree];
375  lastw = 0.0;
376  lastc = 0;
377  if (barray[ifree] == 0) {
378  lastw = 1.0;
379  lastc = 1;
380  }
381  darray[ifree] = ybuf[j];
382  barray[ifree] = ybbuf[j];
383  nextval = darray[ifree];
384  nextw = 0.0;
385  nextc = 0;
386  if (barray[ifree] == 0) {
387  nextw = 1.0;
388  nextc = 1;
389  }
390  } else
391  ipoint[i]--;
392  }
393  medavg(darray,barray,ipoint,nfilt,whichstat,ifree,&val,&bval);
394  if (! bval)
395  data[j-jl+1] = val;
396  goodval[j-jl+1] = bval;
397  }
398 
399  /* Ditch workspace */
400 
401  freespace(darray);
402  freespace(barray);
403  freespace(ipoint);
404  freespace(ybuf);
405  freespace(ybbuf);
406 }
407 
408 /*---------------------------------------------------------------------------*/
443 /*---------------------------------------------------------------------------*/
444 
445 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
446  int whichstat, float **ybuf, unsigned char **ybbuf, int *nbuf) {
447 
448  float *darray,xmns,xmnf;
449  int i1,ilow,i,*ipoint;
450  unsigned char *barray,bxmns,bxmnf;
451 
452  /* Do some padding at the edges */
453 
454  i1 = nfilt/2;
455  ilow = max(3,nfilt/4);
456  ilow = (ilow/2)*2 + 1;
457 
458  /* Get some workspace */
459 
460  darray = cpl_malloc(nfilt*sizeof(*darray));
461  barray = cpl_malloc(nfilt*sizeof(*barray));
462  ipoint = cpl_calloc(nfilt,sizeof(*ipoint));
463  *nbuf = npts + 2*i1;
464  *ybuf = cpl_malloc(*nbuf*sizeof(float));
465  *ybbuf = cpl_malloc(*nbuf*sizeof(unsigned char));
466 
467  /* Do the wrap around.*/
468 
469  memmove((char *)darray,(char *)data,ilow*sizeof(*data));
470  memmove((char *)barray,(char *)bpm,ilow*sizeof(*bpm));
471  medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmns,&bxmns);
472  memmove((char *)darray,(char *)(data+npts-ilow),ilow*sizeof(*data));
473  memmove((char *)barray,(char *)(bpm+npts-ilow),ilow*sizeof(*bpm));
474  medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmnf,&bxmnf);
475  for (i = 0; i < i1; i++) {
476  if (! bxmns) {
477  (*ybuf)[i] = 2.0*xmns - data[i1+ilow-i-1];
478  (*ybbuf)[i] = bpm[i1+ilow-i-1];
479  } else {
480  (*ybuf)[i] = data[i1+ilow-i-1];
481  (*ybbuf)[i] = 1;
482  }
483  if (! bxmnf) {
484  (*ybuf)[npts+i1+i] = 2.0*xmnf - data[npts-i-ilow-1];
485  (*ybbuf)[npts+i1+i] = bpm[npts-i-ilow-1];
486  } else {
487  (*ybuf)[npts+i1+i] = data[npts-i-ilow-1];
488  (*ybbuf)[npts+i1+i] = 1;
489  }
490  }
491 
492  /* Now place the full line into the buffer */
493 
494  memmove((char *)(*ybuf+i1),data,npts*sizeof(*data));
495  memmove((char *)(*ybbuf+i1),bpm,npts*sizeof(*bpm));
496 
497  /* Free workspace */
498 
499  freespace(darray);
500  freespace(barray);
501  freespace(ipoint);
502 }
503 
504 /*---------------------------------------------------------------------------*/
541 /*---------------------------------------------------------------------------*/
542 
543 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
544  int whichstat, int newl, float *outval,
545  unsigned char *outbp) {
546 
547  float *buf = NULL;
548  int m,i;
549 
550  /* Prepare for median. If there is no new element then do a proper
551  sort. Otherwise to a much quicker sort because the input array should
552  be almost sorted as it is. */
553 
554  m = 0;
555  if (whichstat == MEDIANCALC) {
556  if (newl == -1)
557  sortm(array,bpm,ipoint,npix);
558  else
559  quickie(array,bpm,ipoint,newl,npix);
560 
561  /* Get some workspace */
562 
563  buf = cpl_malloc(npix*sizeof(*buf));
564 
565  /* Now put everything that's good in the buffer */
566 
567  m = 0;
568  for (i = 0; i < npix; i++) {
569  if (bpm[i] == 0) {
570  buf[m] = array[i];
571  m++;
572  }
573  }
574 
575  /* Prepare for a mean. If there are no new values in the input arrays
576  then do the summations. If there is, then include it in the summations
577  from the previous calls and removed the oldest value from the
578  summations */
579 
580  } else if (whichstat == MEANCALC) {
581  if (newl == -1) {
582  sum = 0.0;
583  sumw = 0.0;
584  naver = 0;
585  for (i = 0; i < npix; i++) {
586  if (bpm[i] == 0) {
587  sum += array[i];
588  sumw += 1.0;
589  naver += 1;
590  }
591  }
592  m = naver;
593  } else {
594  sum += (nextw*nextval - lastw*lastval);
595  sumw += (nextw - lastw);
596  naver += (nextc - lastc);
597  m = naver;
598  }
599  }
600 
601  /* If they were all bad, then send a null result back */
602 
603  if (m == 0) {
604  *outval = 0.0;
605  *outbp = 1;
606  if (whichstat == MEDIANCALC)
607  freespace(buf);
608 
609  /* Otherwise calculate the relevant stat */
610 
611  } else {
612  if (whichstat == MEDIANCALC) {
613  if (!(m & 1))
614  *outval = 0.5*(buf[(m/2)-1] + buf[m/2]);
615  else
616  *outval = buf[m/2];
617  freespace(buf);
618  } else if (whichstat == MEANCALC)
619  *outval = sum/sumw;
620  *outbp = 0;
621  }
622 }
623 
624 /*---------------------------------------------------------------------------*/
648 /*---------------------------------------------------------------------------*/
649 
650 static void quickie(float *array, unsigned char *iarray, int *iarray2,
651  int testloc, int narray) {
652 
653  float test;
654  int i,j,npt,it2;
655  unsigned char it;
656 
657  test = array[testloc];
658  it = iarray[testloc];
659  it2 = iarray2[testloc];
660  j = -1;
661  for (i = 0; i < narray; i++) {
662  if (i != testloc && test <= array[i]) {
663  j = i;
664  break;
665  }
666  }
667  if (j == -1)
668  j = narray;
669  if (j - 1 == testloc)
670  return;
671 
672  if (j - testloc < 0) {
673  npt = testloc - j;
674  for (i = 0; i < npt; i++) {
675  array[testloc-i] = array[testloc-i-1];
676  iarray[testloc-i] = iarray[testloc-i-1];
677  iarray2[testloc-i] = iarray2[testloc-i-1];
678  }
679  array[j] = test;
680  iarray[j] = it;
681  iarray2[j] = it2;
682  } else {
683  j--;
684  npt = j - testloc;
685  if (npt != 0) {
686  for (i = 0; i < npt; i++) {
687  array[testloc+i] = array[testloc+i+1];
688  iarray[testloc+i] = iarray[testloc+i+1];
689  iarray2[testloc+i] = iarray2[testloc+i+1];
690  }
691  }
692  array[j] = test;
693  iarray[j] = it;
694  iarray2[j] = it2;
695  }
696 }
697 
698 /*---------------------------------------------------------------------------*/
720 /*---------------------------------------------------------------------------*/
721 
722 static void sortm(float *a1, unsigned char *a2, int *a3, int n) {
723  int iii,ii,i,ifin,j,b3;
724  unsigned char b2;
725  float b1;
726 
727  iii = 4;
728  while (iii < n)
729  iii *= 2;
730  iii = min(n,(3*iii)/4 - 1);
731 
732  while (iii > 1) {
733  iii /= 2;
734  ifin = n - iii;
735  for (ii = 0; ii < ifin; ii++) {
736  i = ii;
737  j = i + iii;
738  if (a1[i] > a1[j]) {
739  b1 = a1[j];
740  b2 = a2[j];
741  b3 = a3[j];
742  while (1) {
743  a1[j] = a1[i];
744  a2[j] = a2[i];
745  a3[j] = a3[i];
746  j = i;
747  i = i - iii;
748  if (i < 0 || a1[i] <= b1)
749  break;
750  }
751  a1[j] = b1;
752  a2[j] = b2;
753  a3[j] = b3;
754  }
755  }
756  }
757 }
758 
759 /*---------------------------------------------------------------------------*/
779 /*---------------------------------------------------------------------------*/
780 
781 static void plugholes(float *data, unsigned char *bpm, int nx) {
782  int i,ifirst,ilast,i1,i2,j;
783  float nc,d1,d2,t1,t2,slope;
784 
785  /* First of all, find the first good value in the array */
786 
787  i = 0;
788  while (i < nx && bpm[i] != 0)
789  i++;
790  ifirst = i;
791 
792  /* If all the values in the array are bad, then do nothing */
793 
794  if (ifirst == nx)
795  return;
796 
797  /* Find the last good value in the array */
798 
799  i = nx - 1;
800  while (i >= 0 && bpm[i] != 0)
801  i--;
802  ilast = i;
803 
804  /* Right, now start from the first good value and fill in any holes in the
805  middle part of the array */
806 
807  i = ifirst;
808  while (i <= ilast) {
809  if (bpm[i] == 0) {
810  i++;
811  continue;
812  }
813  i1 = i - 1;
814  while (bpm[i] != 0)
815  i++;
816  i2 = i;
817  nc = (float)(i2 - i1 + 1);
818  d1 = data[i1];
819  d2 = data[i2];
820  for (j = i1+1; j <= i2-1; j++) {
821  t1 = 1.0 - (float)(j - i1)/nc;
822  t2 = 1.0 - t1;
823  data[j] = t1*d1 + t2*d2;
824  }
825  }
826 
827  /* Now the left bit... */
828 
829  if (ifirst > 0) {
830  slope = data[ifirst+1] - data[ifirst];
831  for (j = 0; j < ifirst; j++)
832  data[j] = slope*(j - ifirst) + data[ifirst];
833  }
834 
835  /* Now the right bit... */
836 
837  if (ilast < nx - 1) {
838  slope = data[ilast] - data[ilast-1];
839  for (j = ilast; j < nx; j++)
840  data[j] = slope*(j - ilast) + data[ilast];
841  }
842 }
843 
847 /*
848 
849 $Log: not supported by cvs2svn $
850 Revision 1.3 2010/09/09 12:11:09 jim
851 Fixed problems with docs that make doxygen barf
852 
853 Revision 1.2 2009/11/17 10:21:32 jim
854 dostat is now called vircam_dostat and is exported
855 
856 Revision 1.1 2008/10/13 08:13:21 jim
857 New entry
858 
859 
860 */
void vircam_dostat(float *data, unsigned char *bpm, unsigned char *goodval, int npts, int nfilt, int whichstat)
Definition: vircam_filt.c:330
void vircam_bfilt(float *data, unsigned char *bpm, int nx, int ny, int filt, int stat, int axis)
Do linear filtering on an input map.
Definition: vircam_filt.c:122