VIRCAM Pipeline 2.3.12
casu_filt.c
1/* $Id: casu_filt.c,v 1.2 2015/08/07 13:06:54 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/07 13:06:54 $
24 * $Revision: 1.2 $
25 * $Name: $
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 "catalogue/casu_utils.h"
39#include "casu_filt.h"
40
41/* Structure for holding useful information for the stats routine */
42
43typedef struct {
44 float sum;
45 float sumw;
46 int naver;
47 float nextw;
48 float lastw;
49 float nextval;
50 float lastval;
51 short int nextc;
52 short int lastc;
53} nextlast;
54
55static void docols(float *data, unsigned char *bpm, int nx, int ny,
56 int filter, int stat);
57static void dorows(float *data, unsigned char *bpm, int nx, int ny,
58 int filter, int stat);
59static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
60 int whichstat, float **ybuf, unsigned char **ybbuf,
61 int *nbuf);
62static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
63 int whichstat, int newl, nextlast *nl, float *outval,
64 unsigned char *outbp);
65static void quickie(float *array, unsigned char *iarray, int *iarray2,
66 int lll, int narray);
67static void sortm(float *a1, unsigned char *a2, int *a3, int n);
68static void plugholes(float *data, unsigned char *bpm, int nx);
69
70
73/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114extern void casu_bfilt(float *data, unsigned char *bpm, int nx, int ny,
115 int filt, int stat, int axis) {
116
117 /* Order the reset correction so that the first smoothing is done
118 across the axis of the anomaly */
119
120 if (axis == 1) {
121 dorows(data,bpm,nx,ny,filt,stat);
122 docols(data,bpm,nx,ny,filt,stat);
123 } else {
124 docols(data,bpm,nx,ny,filt,stat);
125 dorows(data,bpm,nx,ny,filt,stat);
126 }
127
128}
129
130/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
162static void docols(float *data, unsigned char *bpm, int nx, int ny,
163 int filter, int stat) {
164 int j,k,indx,nbuf;
165 unsigned char *goodval,*bbuf;
166 float *dbuf;
167
168 /* Get out of here if you've asked for something stupid */
169
170 if (filter <= 0)
171 return;
172
173 /* Get some workspace */
174
175 nbuf = max(nx,ny);
176 dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
177 bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
178 goodval = cpl_malloc(ny*sizeof(*goodval));
179
180 /* Now loop for each column and load a column into the buffer */
181
182 for (k = 0; k < nx; k++) {
183 memset((char *)goodval,0,ny);
184 for (j = 0; j < ny; j++) {
185 indx = j*nx + k;
186 dbuf[j] = data[indx];
187 bbuf[j] = bpm[indx];
188 }
189
190 /* Do the smoothing and plug any holes where there are bad pixels */
191
192 casu_dostat(dbuf,bbuf,goodval,ny,filter,stat);
193 plugholes(dbuf,goodval,ny);
194
195 /* Transfer the data back */
196
197 for (j = 0; j < ny; j++) {
198 indx = j*nx + k;
199 data[indx] = dbuf[j];
200 }
201 }
202
203 /* Ditch workspace */
204
205 freespace(dbuf);
206 freespace(bbuf);
207 freespace(goodval);
208}
209
210/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242static void dorows(float *data, unsigned char *bpm, int nx, int ny,
243 int filter, int stat) {
244 int j,k,indx,nbuf;
245 unsigned char *goodval,*bbuf;
246 float *dbuf;
247
248 /* Get out of here if you've asked for something stupid */
249
250 if (filter <= 0)
251 return;
252
253 /* Get some workspace */
254
255 nbuf = max(nx,ny);
256 dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
257 bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
258 goodval = cpl_malloc(nx*sizeof(*goodval));
259
260 /* Now loop for each row and load a row into the buffer */
261
262 for (k = 0; k < ny; k++) {
263 memset((char *)goodval,0,nx);
264 for (j = 0; j < nx; j++) {
265 indx = k*nx + j;
266 dbuf[j] = data[indx];
267 bbuf[j] = bpm[indx];
268 }
269
270 /* Do the smoothing and plug any holes where there are bad pixels */
271
272 casu_dostat(dbuf,bbuf,goodval,nx,filter,stat);
273 plugholes(dbuf,goodval,nx);
274
275 /* Transfer the data back */
276
277 for (j = 0; j < nx; j++) {
278 indx = k*nx + j;
279 data[indx] = dbuf[j];
280 }
281 }
282
283 /* Ditch workspace */
284
285 freespace(dbuf);
286 freespace(bbuf);
287 freespace(goodval);
288}
289
290/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322extern void casu_dostat(float *data, unsigned char *bpm,
323 unsigned char *goodval, int npts, int nfilt,
324 int whichstat) {
325 int nbuf,jl,jh,j,*ipoint,ifree,i;
326 unsigned char *ybbuf,*barray,bval;
327 float *ybuf,*darray,val;
328 nextlast nl;
329
330 /* check to make sure the filter size is odd */
331
332 if ((nfilt/2)*2 == nfilt)
333 nfilt++;
334
335 /* Do the wrap around and load the data into an oversized array */
336
337 wraparound(data,bpm,npts,nfilt,whichstat,&ybuf,&ybbuf,&nbuf);
338
339 /* Get some data buffers and initialise them */
340
341 darray = cpl_malloc(nfilt*sizeof(*darray));
342 barray = cpl_malloc(nfilt*sizeof(*barray));
343 ipoint = cpl_malloc(nfilt*sizeof(*ipoint));
344 memmove((char *)darray,(char *)ybuf,nfilt*sizeof(*ybuf));
345 memmove((char *)barray,(char *)ybbuf,nfilt*sizeof(*ybbuf));
346 for (j = 0; j < nfilt; j++)
347 ipoint[j] = j;
348
349 /* Do the stat for the first point */
350
351 ifree = 0;
352 medavg(darray,barray,ipoint,nfilt,whichstat,-1,&nl,&val,&bval);
353 if (! bval)
354 data[0] = val;
355 goodval[0] = bval;
356
357 /* Now do the stats for all subsequent points. The oldest point in the
358 buffer is replaced by the next raw point */
359
360 jl = nfilt;
361 jh = nfilt + npts - 2;
362 for (j = jl; j <= jh; j++) {
363 for (i = 0; i < nfilt; i++) {
364 if (ipoint[i] == 0) {
365 ifree = i;
366 ipoint[i] = nfilt - 1;
367 nl.lastval = darray[ifree];
368 nl.lastw = 0.0;
369 nl.lastc = 0;
370 if (barray[ifree] == 0) {
371 nl.lastw = 1.0;
372 nl.lastc = 1;
373 }
374 darray[ifree] = ybuf[j];
375 barray[ifree] = ybbuf[j];
376 nl.nextval = darray[ifree];
377 nl.nextw = 0.0;
378 nl.nextc = 0;
379 if (barray[ifree] == 0) {
380 nl.nextw = 1.0;
381 nl.nextc = 1;
382 }
383 } else
384 ipoint[i]--;
385 }
386 medavg(darray,barray,ipoint,nfilt,whichstat,ifree,&nl,&val,&bval);
387 if (! bval)
388 data[j-jl+1] = val;
389 goodval[j-jl+1] = bval;
390 }
391
392 /* Ditch workspace */
393
394 freespace(darray);
395 freespace(barray);
396 freespace(ipoint);
397 freespace(ybuf);
398 freespace(ybbuf);
399}
400
401/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
437
438static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt,
439 int whichstat, float **ybuf, unsigned char **ybbuf, int *nbuf) {
440
441 float *darray,xmns,xmnf;
442 int i1,ilow,i,*ipoint;
443 unsigned char *barray,bxmns,bxmnf;
444 nextlast nl;
445
446 /* Do some padding at the edges */
447
448 i1 = nfilt/2;
449 ilow = max(3,nfilt/4);
450 ilow = (ilow/2)*2 + 1;
451
452 /* Get some workspace */
453
454 darray = cpl_malloc(nfilt*sizeof(*darray));
455 barray = cpl_malloc(nfilt*sizeof(*barray));
456 ipoint = cpl_calloc(nfilt,sizeof(*ipoint));
457 *nbuf = npts + 2*i1;
458 *ybuf = cpl_malloc(*nbuf*sizeof(float));
459 *ybbuf = cpl_malloc(*nbuf*sizeof(unsigned char));
460
461 /* Do the wrap around.*/
462
463 memmove((char *)darray,(char *)data,ilow*sizeof(*data));
464 memmove((char *)barray,(char *)bpm,ilow*sizeof(*bpm));
465 medavg(darray,barray,ipoint,ilow,whichstat,-1,&nl,&xmns,&bxmns);
466 memmove((char *)darray,(char *)(data+npts-ilow),ilow*sizeof(*data));
467 memmove((char *)barray,(char *)(bpm+npts-ilow),ilow*sizeof(*bpm));
468 medavg(darray,barray,ipoint,ilow,whichstat,-1,&nl,&xmnf,&bxmnf);
469 for (i = 0; i < i1; i++) {
470 if (! bxmns) {
471 (*ybuf)[i] = 2.0*xmns - data[i1+ilow-i-1];
472 (*ybbuf)[i] = bpm[i1+ilow-i-1];
473 } else {
474 (*ybuf)[i] = data[i1+ilow-i-1];
475 (*ybbuf)[i] = 1;
476 }
477 if (! bxmnf) {
478 (*ybuf)[npts+i1+i] = 2.0*xmnf - data[npts-i-ilow-1];
479 (*ybbuf)[npts+i1+i] = bpm[npts-i-ilow-1];
480 } else {
481 (*ybuf)[npts+i1+i] = data[npts-i-ilow-1];
482 (*ybbuf)[npts+i1+i] = 1;
483 }
484 }
485
486 /* Now place the full line into the buffer */
487
488 memmove((char *)(*ybuf+i1),data,npts*sizeof(*data));
489 memmove((char *)(*ybbuf+i1),bpm,npts*sizeof(*bpm));
490
491 /* Free workspace */
492
493 freespace(darray);
494 freespace(barray);
495 freespace(ipoint);
496}
497
498/*---------------------------------------------------------------------------*/
535/*---------------------------------------------------------------------------*/
536
537static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix,
538 int whichstat, int newl, nextlast *nl, float *outval,
539 unsigned char *outbp) {
540
541 float *buf=NULL;
542 int m,i;
543
544 /* Prepare for median. If there is no new element then do a proper
545 sort. Otherwise to a much quicker sort because the input array should
546 be almost sorted as it is. */
547
548 m = 0;
549 if (whichstat == MEDIANCALC) {
550 if (newl == -1)
551 sortm(array,bpm,ipoint,npix);
552 else
553 quickie(array,bpm,ipoint,newl,npix);
554
555 /* Get some workspace */
556
557 buf = cpl_malloc(npix*sizeof(*buf));
558
559 /* Now put everything that's good in the buffer */
560
561 m = 0;
562 for (i = 0; i < npix; i++) {
563 if (bpm[i] == 0) {
564 buf[m] = array[i];
565 m++;
566 }
567 }
568
569 /* Prepare for a mean. If there are no new values in the input arrays
570 then do the summations. If there is, then include it in the summations
571 from the previous calls and removed the oldest value from the
572 summations */
573
574 } else if (whichstat == MEANCALC) {
575 if (newl == -1) {
576 nl->sum = 0.0;
577 nl->sumw = 0.0;
578 nl->naver = 0;
579 for (i = 0; i < npix; i++) {
580 if (bpm[i] == 0) {
581 nl->sum += array[i];
582 nl->sumw += 1.0;
583 nl->naver += 1;
584 }
585 }
586 m = nl->naver;
587 } else {
588 nl->sum += (nl->nextw*nl->nextval - nl->lastw*nl->lastval);
589 nl->sumw += (nl->nextw - nl->lastw);
590 nl->naver += (nl->nextc - nl->lastc);
591 m = nl->naver;
592 }
593 }
594
595 /* If they were all bad, then send a null result back */
596
597 if (m == 0) {
598 *outval = 0.0;
599 *outbp = 1;
600 if (whichstat == MEDIANCALC)
601 freespace(buf);
602
603 /* Otherwise calculate the relevant stat */
604
605 } else {
606 if (whichstat == MEDIANCALC) {
607 if (!(m & 1))
608 *outval = 0.5*(buf[(m/2)-1] + buf[m/2]);
609 else
610 *outval = buf[m/2];
611 freespace(buf);
612 } else if (whichstat == MEANCALC)
613 *outval = (nl->sum)/(nl->sumw);
614 *outbp = 0;
615 }
616}
617
618/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
644static void quickie(float *array, unsigned char *iarray, int *iarray2,
645 int testloc, int narray) {
646
647 float test;
648 int i,j,npt,it2;
649 unsigned char it;
650
651 test = array[testloc];
652 it = iarray[testloc];
653 it2 = iarray2[testloc];
654 j = -1;
655 for (i = 0; i < narray; i++) {
656 if (i != testloc && test <= array[i]) {
657 j = i;
658 break;
659 }
660 }
661 if (j == -1)
662 j = narray;
663 if (j - 1 == testloc)
664 return;
665
666 if (j - testloc < 0) {
667 npt = testloc - j;
668 for (i = 0; i < npt; i++) {
669 array[testloc-i] = array[testloc-i-1];
670 iarray[testloc-i] = iarray[testloc-i-1];
671 iarray2[testloc-i] = iarray2[testloc-i-1];
672 }
673 array[j] = test;
674 iarray[j] = it;
675 iarray2[j] = it2;
676 } else {
677 j--;
678 npt = j - testloc;
679 if (npt != 0) {
680 for (i = 0; i < npt; i++) {
681 array[testloc+i] = array[testloc+i+1];
682 iarray[testloc+i] = iarray[testloc+i+1];
683 iarray2[testloc+i] = iarray2[testloc+i+1];
684 }
685 }
686 array[j] = test;
687 iarray[j] = it;
688 iarray2[j] = it2;
689 }
690}
691
692/*---------------------------------------------------------------------------*/
714/*---------------------------------------------------------------------------*/
715
716static void sortm(float *a1, unsigned char *a2, int *a3, int n) {
717 int iii,ii,i,ifin,j,b3;
718 unsigned char b2;
719 float b1;
720
721 iii = 4;
722 while (iii < n)
723 iii *= 2;
724 iii = min(n,(3*iii)/4 - 1);
725
726 while (iii > 1) {
727 iii /= 2;
728 ifin = n - iii;
729 for (ii = 0; ii < ifin; ii++) {
730 i = ii;
731 j = i + iii;
732 if (a1[i] > a1[j]) {
733 b1 = a1[j];
734 b2 = a2[j];
735 b3 = a3[j];
736 while (1) {
737 a1[j] = a1[i];
738 a2[j] = a2[i];
739 a3[j] = a3[i];
740 j = i;
741 i = i - iii;
742 if (i < 0 || a1[i] <= b1)
743 break;
744 }
745 a1[j] = b1;
746 a2[j] = b2;
747 a3[j] = b3;
748 }
749 }
750 }
751}
752
753/*---------------------------------------------------------------------------*/
773/*---------------------------------------------------------------------------*/
774
775static void plugholes(float *data, unsigned char *bpm, int nx) {
776 int i,ifirst,ilast,i1,i2,j;
777 float nc,d1,d2,t1,t2,slope;
778
779 /* First of all, find the first good value in the array */
780
781 i = 0;
782 while (i < nx && bpm[i] != 0)
783 i++;
784 ifirst = i;
785
786 /* If all the values in the array are bad, then do nothing */
787
788 if (ifirst == nx)
789 return;
790
791 /* Find the last good value in the array */
792
793 i = nx - 1;
794 while (i >= 0 && bpm[i] != 0)
795 i--;
796 ilast = i;
797
798 /* Right, now start from the first good value and fill in any holes in the
799 middle part of the array */
800
801 i = ifirst;
802 while (i <= ilast) {
803 if (bpm[i] == 0) {
804 i++;
805 continue;
806 }
807 i1 = i - 1;
808 while (bpm[i] != 0)
809 i++;
810 i2 = i;
811 nc = (float)(i2 - i1 + 1);
812 d1 = data[i1];
813 d2 = data[i2];
814 for (j = i1+1; j <= i2-1; j++) {
815 t1 = 1.0 - (float)(j - i1)/nc;
816 t2 = 1.0 - t1;
817 data[j] = t1*d1 + t2*d2;
818 }
819 }
820
821 /* Now the left bit... */
822
823 if (ifirst > 0) {
824 slope = data[ifirst+1] - data[ifirst];
825 for (j = 0; j < ifirst; j++)
826 data[j] = slope*(j - ifirst) + data[ifirst];
827 }
828
829 /* Now the right bit... */
830
831 if (ilast < nx - 1) {
832 slope = data[ilast] - data[ilast-1];
833 for (j = ilast; j < nx; j++)
834 data[j] = slope*(j - ilast) + data[ilast];
835 }
836}
837
841/*
842
843$Log: casu_filt.c,v $
844Revision 1.2 2015/08/07 13:06:54 jim
845Fixed copyright to ESO
846
847Revision 1.1.1.1 2015/06/12 10:44:32 jim
848Initial import
849
850Revision 1.5 2015/06/09 18:31:56 jim
851Made casu_dostat external
852
853Revision 1.4 2015/01/29 11:46:18 jim
854modified comments
855
856Revision 1.3 2014/03/26 15:35:26 jim
857Modified to remove globals
858
859Revision 1.2 2013/11/21 09:38:13 jim
860detabbed
861
862Revision 1.1.1.1 2013-08-27 12:07:48 jim
863Imported
864
865
866*/