vircam_filt.c

00001 /* $Id: vircam_filt.c,v 1.4 2012/07/20 09:49:14 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2008 Cambridge Astronomy Survey Unit
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: jim $
00023  * $Date: 2012/07/20 09:49:14 $
00024  * $Revision: 1.4 $
00025  * $Name: vcam-1_3_2 $
00026  */
00027 
00028 /* Includes */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 #include <cpl.h>
00035 #include <math.h>
00036 #include <string.h>
00037 
00038 #include "vircam_utils.h"
00039 #include "vircam_filt.h"
00040 
00041 static void docols(float *data, unsigned char *bpm, int nx, int ny, 
00042                    int filter, int stat);
00043 static void dorows(float *data, unsigned char *bpm, int nx, int ny, 
00044                    int filter, int stat);
00045 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt, 
00046                        int whichstat, float **ybuf, unsigned char **ybbuf, 
00047                        int *nbuf);
00048 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix, 
00049                    int whichstat, int newl, float *outval, 
00050                    unsigned char *outbp);
00051 static void quickie(float *array, unsigned char *iarray, int *iarray2, 
00052                     int lll, int narray);
00053 static void sortm(float *a1, unsigned char *a2, int *a3, int n);
00054 static void plugholes(float *data, unsigned char *bpm, int nx);
00055 
00056 /* Global variables */
00057 
00058 static float sum;
00059 static float sumw;
00060 static int   naver;
00061 static float nextw;
00062 static float lastw;
00063 static float nextval;
00064 static float lastval;
00065 static short int nextc;
00066 static short int lastc;
00067 
00082 /*---------------------------------------------------------------------------*/
00120 /*---------------------------------------------------------------------------*/
00121 
00122 extern void vircam_bfilt(float *data, unsigned char *bpm, int nx, int ny, 
00123                          int filt, int stat, int axis) {
00124 
00125     /* Order the reset correction so that the first smoothing is done
00126        across the axis of the anomaly */
00127 
00128     if (axis == 1) {
00129         dorows(data,bpm,nx,ny,filt,stat);
00130         docols(data,bpm,nx,ny,filt,stat);
00131     } else {
00132         docols(data,bpm,nx,ny,filt,stat);
00133         dorows(data,bpm,nx,ny,filt,stat);
00134     }
00135 
00136 }
00137 
00138 /*---------------------------------------------------------------------------*/
00168 /*---------------------------------------------------------------------------*/
00169 
00170 static void docols(float *data, unsigned char *bpm, int nx, int ny, 
00171                    int filter, int stat) {
00172     int j,k,indx,nbuf;
00173     unsigned char *goodval,*bbuf;
00174     float *dbuf;
00175 
00176     /* Get out of here if you've asked for something stupid */
00177 
00178     if (filter <= 0)
00179         return;
00180 
00181     /* Get some workspace */
00182 
00183     nbuf = max(nx,ny);
00184     dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
00185     bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
00186     goodval = cpl_malloc(ny*sizeof(*goodval));
00187 
00188     /* Now loop for each column and load a column into the buffer */
00189 
00190     for (k = 0; k < nx; k++) {
00191         memset((char *)goodval,0,ny);
00192         for (j = 0; j < ny; j++) {
00193             indx = j*nx + k;
00194             dbuf[j] = data[indx];
00195             bbuf[j] = bpm[indx];
00196         }
00197 
00198         /* Do the smoothing and plug any holes where there are bad pixels */
00199 
00200         vircam_dostat(dbuf,bbuf,goodval,ny,filter,stat);
00201         plugholes(dbuf,goodval,ny);
00202 
00203         /* Transfer the data back */
00204 
00205         for (j = 0; j < ny; j++) {
00206             indx = j*nx + k;
00207             data[indx] = dbuf[j];
00208         }
00209     } 
00210 
00211     /* Ditch workspace */
00212 
00213     freespace(dbuf);
00214     freespace(bbuf);
00215     freespace(goodval);
00216 }
00217 
00218 /*---------------------------------------------------------------------------*/
00248 /*---------------------------------------------------------------------------*/
00249 
00250 static void dorows(float *data, unsigned char *bpm, int nx, int ny, 
00251                    int filter, int stat) {
00252     int j,k,indx,nbuf;
00253     unsigned char *goodval,*bbuf;
00254     float *dbuf;
00255 
00256     /* Get out of here if you've asked for something stupid */
00257 
00258     if (filter <= 0)
00259         return;
00260 
00261     /* Get some workspace */
00262 
00263     nbuf = max(nx,ny);
00264     dbuf = cpl_malloc(nbuf*sizeof(*dbuf));
00265     bbuf = cpl_malloc(nbuf*sizeof(*bbuf));
00266     goodval = cpl_malloc(nx*sizeof(*goodval));
00267 
00268     /* Now loop for each row and load a row into the buffer */
00269 
00270     for (k = 0; k < ny; k++) {
00271         memset((char *)goodval,0,nx);
00272         for (j = 0; j < nx; j++) {
00273             indx = k*nx + j;
00274             dbuf[j] = data[indx];
00275             bbuf[j] = bpm[indx];
00276         }
00277 
00278         /* Do the smoothing and plug any holes where there are bad pixels */
00279 
00280         vircam_dostat(dbuf,bbuf,goodval,nx,filter,stat);
00281         plugholes(dbuf,goodval,nx);
00282 
00283         /* Transfer the data back */
00284 
00285         for (j = 0; j < nx; j++) {
00286             indx = k*nx + j;
00287             data[indx] = dbuf[j];
00288         }
00289     }
00290 
00291     /* Ditch workspace */
00292 
00293     freespace(dbuf);
00294     freespace(bbuf);
00295     freespace(goodval);
00296 }
00297 
00298 /*---------------------------------------------------------------------------*/
00328 /*---------------------------------------------------------------------------*/
00329 
00330 extern void vircam_dostat(float *data, unsigned char *bpm, 
00331                           unsigned char *goodval, int npts, int nfilt,
00332                           int whichstat) {
00333     int nbuf,jl,jh,j,*ipoint,ifree,i;
00334     unsigned char *ybbuf,*barray,bval;
00335     float *ybuf,*darray,val;
00336 
00337     /* check to make sure the filter size is odd */
00338 
00339     if ((nfilt/2)*2 == nfilt)
00340         nfilt++;
00341 
00342     /* Do the wrap around and load the data into an oversized array */
00343 
00344     wraparound(data,bpm,npts,nfilt,whichstat,&ybuf,&ybbuf,&nbuf);
00345 
00346     /* Get some data buffers and initialise them */
00347 
00348     darray = cpl_malloc(nfilt*sizeof(*darray));
00349     barray = cpl_malloc(nfilt*sizeof(*barray));
00350     ipoint = cpl_malloc(nfilt*sizeof(*ipoint));
00351     memmove((char *)darray,(char *)ybuf,nfilt*sizeof(*ybuf));
00352     memmove((char *)barray,(char *)ybbuf,nfilt*sizeof(*ybbuf));
00353     for (j = 0; j < nfilt; j++)
00354         ipoint[j] = j;
00355 
00356     /* Do the stat for the first point */
00357 
00358     ifree = 0;
00359     medavg(darray,barray,ipoint,nfilt,whichstat,-1,&val,&bval);
00360     if (! bval) 
00361         data[0] = val;
00362     goodval[0] = bval;
00363 
00364     /* Now do the stats for all subsequent points. The oldest point in the
00365        buffer is replaced by the next raw point */
00366 
00367     jl = nfilt;
00368     jh = nfilt + npts - 2;
00369     for (j = jl; j <= jh; j++) {
00370         for (i = 0; i < nfilt; i++) {
00371             if (ipoint[i] == 0) {
00372                 ifree = i;
00373                 ipoint[i] = nfilt - 1;
00374                 lastval = darray[ifree];
00375                 lastw = 0.0;
00376                 lastc = 0;
00377                 if (barray[ifree] == 0) {
00378                     lastw = 1.0;
00379                     lastc = 1;
00380                 }                
00381                 darray[ifree] = ybuf[j];
00382                 barray[ifree] = ybbuf[j];
00383                 nextval = darray[ifree];
00384                 nextw = 0.0;
00385                 nextc = 0;
00386                 if (barray[ifree] == 0) {
00387                     nextw = 1.0;
00388                     nextc = 1;
00389                 }                
00390             } else
00391                 ipoint[i]--;
00392         }
00393         medavg(darray,barray,ipoint,nfilt,whichstat,ifree,&val,&bval);
00394         if (! bval) 
00395             data[j-jl+1] = val;
00396         goodval[j-jl+1] = bval;
00397     }
00398 
00399     /* Ditch workspace */
00400 
00401     freespace(darray);
00402     freespace(barray);
00403     freespace(ipoint);
00404     freespace(ybuf);
00405     freespace(ybbuf);
00406 }
00407 
00408 /*---------------------------------------------------------------------------*/
00443 /*---------------------------------------------------------------------------*/
00444 
00445 static void wraparound(float *data, unsigned char *bpm, int npts, int nfilt, 
00446     int whichstat, float **ybuf, unsigned char **ybbuf, int *nbuf) {
00447 
00448     float *darray,xmns,xmnf;
00449     int i1,ilow,i,*ipoint;
00450     unsigned char *barray,bxmns,bxmnf;
00451 
00452     /* Do some padding at the edges */
00453 
00454     i1 = nfilt/2;
00455     ilow = max(3,nfilt/4);
00456     ilow = (ilow/2)*2 + 1;
00457 
00458     /* Get some workspace */
00459 
00460     darray = cpl_malloc(nfilt*sizeof(*darray));
00461     barray = cpl_malloc(nfilt*sizeof(*barray));
00462     ipoint = cpl_calloc(nfilt,sizeof(*ipoint));
00463     *nbuf = npts + 2*i1;
00464     *ybuf = cpl_malloc(*nbuf*sizeof(float));
00465     *ybbuf = cpl_malloc(*nbuf*sizeof(unsigned char));
00466 
00467     /* Do the wrap around.*/
00468 
00469     memmove((char *)darray,(char *)data,ilow*sizeof(*data));
00470     memmove((char *)barray,(char *)bpm,ilow*sizeof(*bpm));
00471     medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmns,&bxmns);
00472     memmove((char *)darray,(char *)(data+npts-ilow),ilow*sizeof(*data));
00473     memmove((char *)barray,(char *)(bpm+npts-ilow),ilow*sizeof(*bpm));
00474     medavg(darray,barray,ipoint,ilow,whichstat,-1,&xmnf,&bxmnf);
00475     for (i = 0; i < i1; i++) {
00476         if (! bxmns) {
00477             (*ybuf)[i] = 2.0*xmns - data[i1+ilow-i-1];
00478             (*ybbuf)[i] = bpm[i1+ilow-i-1];
00479         } else {
00480             (*ybuf)[i] = data[i1+ilow-i-1];
00481             (*ybbuf)[i] = 1;
00482         }
00483         if (! bxmnf) {
00484             (*ybuf)[npts+i1+i] = 2.0*xmnf - data[npts-i-ilow-1];
00485             (*ybbuf)[npts+i1+i] = bpm[npts-i-ilow-1];
00486         } else {
00487             (*ybuf)[npts+i1+i] = data[npts-i-ilow-1];
00488             (*ybbuf)[npts+i1+i] = 1;
00489         }
00490     }
00491 
00492     /* Now place the full line into the buffer */
00493 
00494     memmove((char *)(*ybuf+i1),data,npts*sizeof(*data));
00495     memmove((char *)(*ybbuf+i1),bpm,npts*sizeof(*bpm));
00496 
00497     /* Free workspace */
00498 
00499     freespace(darray);
00500     freespace(barray);
00501     freespace(ipoint);
00502 }
00503 
00504 /*---------------------------------------------------------------------------*/
00541 /*---------------------------------------------------------------------------*/
00542 
00543 static void medavg(float *array, unsigned char *bpm, int *ipoint, int npix, 
00544                    int whichstat, int newl, float *outval, 
00545                    unsigned char *outbp) {
00546 
00547     float *buf = NULL;
00548     int m,i;
00549 
00550     /* Prepare for median. If there is no new element then do a proper 
00551        sort. Otherwise to a much quicker sort because the input array should
00552        be almost sorted as it is. */
00553     
00554     m = 0;
00555     if (whichstat == MEDIANCALC) {
00556         if (newl == -1) 
00557             sortm(array,bpm,ipoint,npix);
00558         else  
00559             quickie(array,bpm,ipoint,newl,npix);
00560 
00561         /* Get some workspace */
00562 
00563         buf = cpl_malloc(npix*sizeof(*buf));
00564 
00565         /* Now put everything that's good in the buffer */
00566 
00567         m = 0;
00568         for (i = 0; i < npix; i++) {
00569             if (bpm[i] == 0) {
00570                 buf[m] = array[i];
00571                 m++;
00572             }
00573         }
00574 
00575     /* Prepare for a mean. If there are no new values in the input arrays
00576        then do the summations. If there is, then include it in the summations
00577        from the previous calls and removed the oldest value from the
00578        summations */
00579 
00580     } else if (whichstat == MEANCALC) {
00581         if (newl == -1) {
00582             sum = 0.0;
00583             sumw = 0.0;
00584             naver = 0;
00585             for (i = 0; i < npix; i++) {
00586                 if (bpm[i] == 0) {
00587                     sum += array[i];
00588                     sumw += 1.0;
00589                     naver += 1;
00590                 }
00591             }
00592             m = naver;
00593         } else {
00594             sum += (nextw*nextval - lastw*lastval);
00595             sumw += (nextw - lastw);
00596             naver += (nextc - lastc);
00597             m = naver;
00598         }
00599     }
00600         
00601     /* If they were all bad, then send a null result back */
00602 
00603     if (m == 0) {
00604         *outval = 0.0;
00605         *outbp = 1;
00606         if (whichstat == MEDIANCALC)
00607             freespace(buf);
00608 
00609     /* Otherwise calculate the relevant stat */
00610 
00611     } else {
00612         if (whichstat == MEDIANCALC) {
00613             if (!(m & 1)) 
00614                 *outval = 0.5*(buf[(m/2)-1] + buf[m/2]);
00615             else
00616                 *outval = buf[m/2];
00617             freespace(buf);
00618         } else if (whichstat == MEANCALC)
00619             *outval = sum/sumw;
00620         *outbp = 0;
00621     }
00622 }
00623 
00624 /*---------------------------------------------------------------------------*/
00648 /*---------------------------------------------------------------------------*/
00649 
00650 static void quickie(float *array, unsigned char *iarray, int *iarray2, 
00651     int testloc, int narray) {
00652 
00653     float test;
00654     int i,j,npt,it2;
00655     unsigned char it;
00656 
00657     test = array[testloc];
00658     it = iarray[testloc];
00659     it2 = iarray2[testloc];
00660     j = -1;
00661     for (i = 0; i < narray; i++) {
00662         if (i != testloc && test <= array[i]) {
00663             j = i;
00664             break;
00665         }
00666     }
00667     if (j == -1) 
00668         j = narray;
00669     if (j - 1 == testloc)
00670         return;
00671 
00672     if (j - testloc < 0) {
00673         npt = testloc - j;
00674         for (i = 0; i < npt; i++) {
00675             array[testloc-i] = array[testloc-i-1];
00676             iarray[testloc-i] = iarray[testloc-i-1];
00677             iarray2[testloc-i] = iarray2[testloc-i-1];
00678         }
00679         array[j] = test;
00680         iarray[j] = it;
00681         iarray2[j] = it2;
00682     } else {
00683         j--;
00684         npt = j - testloc;
00685         if (npt != 0) {
00686             for (i = 0; i < npt; i++) {
00687                 array[testloc+i] = array[testloc+i+1];
00688                 iarray[testloc+i] = iarray[testloc+i+1];
00689                 iarray2[testloc+i] = iarray2[testloc+i+1];
00690             }
00691         }
00692         array[j] = test;
00693         iarray[j] = it;
00694         iarray2[j] = it2;
00695     }
00696 }
00697             
00698 /*---------------------------------------------------------------------------*/
00720 /*---------------------------------------------------------------------------*/
00721 
00722 static void sortm(float *a1, unsigned char *a2, int *a3, int n) {
00723     int iii,ii,i,ifin,j,b3;
00724     unsigned char b2;
00725     float b1;
00726 
00727     iii = 4;
00728     while (iii < n)
00729         iii *= 2;
00730     iii = min(n,(3*iii)/4 - 1);
00731 
00732     while (iii > 1) {
00733         iii /= 2;
00734         ifin = n - iii;
00735         for (ii = 0; ii < ifin; ii++) {
00736             i = ii;
00737             j = i + iii;
00738             if (a1[i] > a1[j]) {
00739                 b1 = a1[j];
00740                 b2 = a2[j];
00741                 b3 = a3[j];
00742                 while (1) {
00743                     a1[j] = a1[i];
00744                     a2[j] = a2[i];
00745                     a3[j] = a3[i];
00746                     j = i;
00747                     i = i - iii;
00748                     if (i < 0 || a1[i] <= b1) 
00749                         break;
00750                 }
00751                 a1[j] = b1;
00752                 a2[j] = b2;
00753                 a3[j] = b3;
00754             }
00755         }
00756     }
00757 }
00758 
00759 /*---------------------------------------------------------------------------*/
00779 /*---------------------------------------------------------------------------*/
00780 
00781 static void plugholes(float *data, unsigned char *bpm, int nx) {
00782     int i,ifirst,ilast,i1,i2,j;
00783     float nc,d1,d2,t1,t2,slope;
00784 
00785     /* First of all, find the first good value in the array */
00786 
00787     i = 0;
00788     while (i < nx && bpm[i] != 0)
00789         i++;
00790     ifirst = i;
00791 
00792     /* If all the values in the array are bad, then do nothing */
00793 
00794     if (ifirst == nx)
00795         return;
00796 
00797     /* Find the last good value in the array */
00798 
00799     i = nx - 1;
00800     while (i >= 0 && bpm[i] != 0) 
00801         i--;
00802     ilast = i;
00803 
00804     /* Right, now start from the first good value and fill in any holes in the
00805        middle part of the array */
00806 
00807     i = ifirst;
00808     while (i <= ilast) {
00809         if (bpm[i] == 0) {
00810             i++;
00811             continue;
00812         }
00813         i1 = i - 1;
00814         while (bpm[i] != 0) 
00815             i++;
00816         i2 = i;
00817         nc = (float)(i2 - i1 + 1);
00818         d1 = data[i1];
00819         d2 = data[i2];
00820         for (j = i1+1; j <= i2-1; j++) {
00821             t1 = 1.0 - (float)(j - i1)/nc;
00822             t2 = 1.0 - t1;
00823             data[j] = t1*d1 + t2*d2;
00824         }
00825     }
00826 
00827     /* Now the left bit... */
00828 
00829     if (ifirst > 0) {
00830         slope = data[ifirst+1] - data[ifirst];
00831         for (j = 0; j < ifirst; j++)
00832             data[j] = slope*(j - ifirst) + data[ifirst];
00833     }
00834 
00835     /* Now the right bit... */
00836 
00837     if (ilast < nx - 1) {
00838         slope = data[ilast] - data[ilast-1];
00839         for (j = ilast; j < nx; j++) 
00840             data[j] = slope*(j - ilast) + data[ilast];
00841     }
00842 }
00843 
00847 /* 
00848 
00849 $Log: vircam_filt.c,v $
00850 Revision 1.4  2012/07/20 09:49:14  jim
00851 fixed small bug in sort routine
00852 
00853 Revision 1.3  2010/09/09 12:11:09  jim
00854 Fixed problems with docs that make doxygen barf
00855 
00856 Revision 1.2  2009/11/17 10:21:32  jim
00857 dostat is now called vircam_dostat and is exported
00858 
00859 Revision 1.1  2008/10/13 08:13:21  jim
00860 New entry
00861 
00862 
00863 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1