imcore_filter.c

00001 /* $Id: imcore_filter.c,v 1.6 2010/09/09 12:09:57 jim Exp $
00002  *
00003  * This file is part of the VIRCAM Pipeline
00004  * Copyright (C) 2005 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: 2010/09/09 12:09:57 $
00024  * $Revision: 1.6 $
00025  * $Name: vcam-1_3_2 $
00026  */
00027 
00028 #include <stdlib.h>
00029 
00030 #include "util.h"
00031 #include "imcore.h"
00032 
00033 /* Function prototypes */
00034 
00035 static void sortm (float ia[], int ib[], int n);
00036 static void quicksort (float x[], int point[], int l, int nfilt);
00037 
00040 /*---------------------------------------------------------------------------*/
00068 /*---------------------------------------------------------------------------*/
00069  
00070 extern void bfilt (float **xbuf, int nx, int ny) {
00071    float *ybuf, *save;
00072    int mfilt = 5, j, k;
00073  
00074 /* Allocate temporary storage */
00075    ybuf = (float *) malloc(MAX(nx,ny) * sizeof(float));
00076    save = (float *) malloc((nx+1) * ny * sizeof(float));
00077 /*    if(!ybuf || !save) bombout(1, "malloc"); */
00078  
00079 /* median filter across */
00080    for(k = 0; k < ny; k++) {
00081      for(j = 0; j < nx; j++) {
00082        save[(nx+1)*k+j] = xbuf[k][j];
00083        ybuf[j] = xbuf[k][j];
00084      }
00085      filt1d(ybuf, nx, mfilt);
00086      for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
00087    }
00088  
00089 /* and now down */
00090    for(k = 0; k < nx; k++) {
00091      for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
00092      filt1d(ybuf, ny, mfilt);
00093      for(j = 0; j < ny; j++)
00094 /* make sure median filtered values are not large than original */
00095        if(save[(nx+1)*j+k] > -1000.0)
00096        xbuf[j][k] = MIN(save[(nx+1)*j+k], ybuf[j]);
00097    }
00098 
00099 /* now repeat with linear filters across */
00100    for(k = 0; k < ny; k++) {
00101      for(j = 0; j < nx; j++) ybuf[j] = xbuf[k][j];
00102      hanning(ybuf, nx);
00103      for(j = 0; j < nx; j++) xbuf[k][j] = ybuf[j];
00104    }
00105 
00106 /* and now down */
00107    for(k = 0; k < nx; k++) {
00108      for(j = 0; j < ny; j++) ybuf[j] = xbuf[j][k];
00109      hanning(ybuf, ny);
00110      for(j = 0; j < ny; j++) xbuf[j][k] = ybuf[j];
00111    }
00112 
00113 /* Free temporary storage */
00114    free((void *) ybuf);
00115    free((void *) save);
00116 }/* --------------------------------------- ------------------------------ */
00117 
00120 /* does median filtering allowing for unmeasured entries */
00121  
00122 void filt1d (float ybuf[], int mpt, int mfilt) {
00123    float *wbuf;
00124    int i, irc;
00125 /* Allocate temporary storage */
00126    wbuf = (float *) malloc(mpt * sizeof(float));
00127 /*    if(!wbuf) bombout(1, "malloc"); */
00128  
00129    irc = 0;
00130    for(i = 0; i < mpt; i++){
00131      if(ybuf[i] > -1000.0){
00132        wbuf[irc] = ybuf[i];
00133        irc++;
00134      }
00135    }
00136    if(irc == 0) {
00137      free((void *) wbuf);
00138      return;
00139    }
00140    median(wbuf, irc, mfilt);
00141    irc = 0;
00142    for(i = 0; i < mpt; i++){
00143      if(ybuf[i] > -1000.0){
00144        ybuf[i] = wbuf[irc];
00145        irc++;
00146      }
00147    }
00148    padext(ybuf, mpt);
00149 /* Free temporary storage */
00150    free((void *) wbuf);
00151 }
00152 
00153 
00154 /* pads out array with missing points and linearly extrapolates the ends */
00155  
00156 void padext (float x[], int n) {
00157    int i, j, ilow, ihih=0, ic;
00158    float xlow, xhih, slope, t1 ,t2;
00159 /* elements <= -1000.0 are treated as missing */
00160    i = 0;
00161    while(x[i] <= -1000.0) i++;
00162    ilow = i;
00163    for(i = ilow+1; i < n; i++){
00164      if(x[i] <= -1000.0) {
00165        ic = 1;
00166        if (i < n - 1) {
00167            while(x[i+ic] <= -1000.0) {
00168                ic++;
00169                if (i+ic >= n-1)
00170                    break;
00171            }
00172        }
00173        if(i+ic < n-1){
00174          xlow = x[i-1];
00175          xhih = x[i+ic];
00176          for(j = 0; j < ic; j++){
00177            t2 = ((float) j+1)/((float) ic+1);
00178            t1 = 1.0 - t2;
00179            x[i+j] = t1*xlow+t2*xhih;
00180          }
00181        }
00182      } else {
00183        ihih = i;
00184      }
00185    }
00186 /* linear extrapolation of ends */
00187    if(ilow > 0){
00188      slope = x[ilow+1]-x[ilow];
00189      for(i = 0; i < ilow; i++) x[i] = x[ilow]-slope*(ilow-i);
00190    }
00191    if(ihih < n-1) {
00192      slope = x[ihih]-x[ihih-1];
00193      for(i = ihih+1; i < n; i++) x[i] = x[ihih]+slope*(i-ihih);
00194    }
00195 }
00196 
00197 /* performs linear filtering on array xbuf */
00198 
00199 void hanning (float xbuf[], int npt) {
00200   float *ybuf;
00201   float sum = 0.0, xmns, xmnf;
00202   int nfilt = 3, i, il, ilow, nelem;
00203 
00204   if(npt <= nfilt)
00205     return;
00206 
00207   /* set first and last edges equal */
00208   il   = nfilt/2;
00209   ilow = MAX(3,nfilt/4);
00210   ilow = (ilow/2)*2 + 1;
00211 
00212   for(i = 0; i < ilow; i++)
00213     sum += xbuf[i];
00214 
00215   xmns = sum/((float) ilow);
00216 
00217   sum=0.0;
00218   for(i = 0; i < ilow; i++)
00219     sum += xbuf[npt-1-i];
00220 
00221   xmnf = sum/((float) ilow);
00222 
00223   /* allocate ybuf array */
00224   nelem = npt + nfilt;  /* Max. number of elements req'd */
00225 
00226   ybuf = (float *) malloc(nelem * sizeof(float));
00227 /*   if(!ybuf) */
00228 /*     bombout(1, "malloc"); */
00229 
00230   /* reflect edges before filtering */
00231   for(i = 0; i < il; i++) {
00232     ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
00233     ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
00234   }
00235 
00236   for(i = 0; i < npt; i++)
00237     ybuf[i+il] = xbuf[i];
00238 
00239   /* do linear filtering on rest */
00240   for(i = 0; i < npt; i++)
00241     xbuf[i] = 0.25 * (ybuf[i] + 2.0 * ybuf[i+1] + ybuf[i+2]);  /* 1-2-1 Hanning weighting */
00242 
00243   free((void *) ybuf);
00244 }
00245 
00246 /* performs median filtering on array xbuf */
00247 
00248 void median (float xbuf[], int npt, int nfilt) {
00249   float *ybuf, *array;
00250   float xmns, xmnf;
00251   int *point;
00252   int nfo2p1, i, il, ilow, j, jl, jh, nelem, l=0;
00253 
00254   if((nfilt/2)*2 == nfilt) nfilt++;
00255   if(npt <= nfilt) return;
00256   nfo2p1 = nfilt/2;
00257 
00258   /* allocate ybuf, array, point */
00259   nelem = npt + nfilt;  /* Max. number of elements req'd */
00260   ybuf = (float *) malloc(nelem * sizeof(float));
00261 /*   if(!ybuf) */
00262 /*     bombout(1, "malloc"); */
00263   array = (float *) malloc(nfilt * sizeof(float));
00264   point = (int *) malloc(nfilt * sizeof(int));
00265 /*   if(!array || !point) */
00266 /*     bombout(1, "malloc"); */
00267 
00268   /* set first and last edges equal */
00269   il   = nfilt/2;
00270   ilow = MAX(3, nfilt/4);
00271   ilow = (ilow/2)*2 + 1;
00272 
00273   for(i = 0; i < ilow; i++) array[i] = xbuf[i];
00274   sortm(array, point, ilow);
00275   xmns = array[ilow/2];
00276 
00277   for(i = 0; i < ilow; i++) array[i] = xbuf[npt-1-i];
00278   sortm(array, point, ilow);
00279   xmnf = array[ilow/2];
00280 
00281   /* reflect edges before filtering */
00282   for(i = 0; i < il; i++) {
00283     ybuf[i] = 2.0 * xmns - xbuf[il+ilow-1-i];
00284     ybuf[npt+i+il] = 2.0 * xmnf - xbuf[npt-i-ilow-1];
00285   }
00286   for(i = 0; i < npt; i++) ybuf[i+il] = xbuf[i];
00287 
00288   /* do median filtering on rest */
00289   for(i = 0; i < nfilt; i++) {
00290     array[i] = ybuf[i];
00291     point[i] = i+1;
00292   }
00293 
00294   sortm(array, point, nfilt);
00295 
00296   xbuf[0] = array[nfo2p1];
00297   jl = nfilt;
00298   jh = nfilt+npt-1;
00299   for(j = jl; j < jh; j++) {
00300 
00301     for(i = 0; i < nfilt; i++) {
00302       if(point[i] != 1) {
00303         point[i]--;
00304         continue;
00305       }
00306       point[i] = nfilt;
00307       array[i] = ybuf[j];
00308       l = i;
00309     }
00310     quicksort(array, point, l, nfilt);
00311     xbuf[j-jl+1] = array[nfo2p1];
00312   }
00313 
00314   /* Free temporary arrays */
00315   free((void *) point);
00316   free((void *) array);
00317   free((void *) ybuf);
00318 }
00319 
00320 static void sortm (float ia[], int ib[], int n) {
00321   int i,j, ii, jj, ifin, iu;
00322   float it;
00323 
00324   jj = 2;
00325   while(jj < n) jj = 2 * jj;
00326   jj = MIN(n,(3 * jj)/4 - 1);
00327   while(jj > 1) {
00328     jj = jj/2;
00329     ifin = n - jj;
00330     for(ii = 0; ii < ifin; ii++) {
00331       i = ii;
00332       j = i + jj;
00333       if(ia[i] <= ia[j]) continue;
00334       it = ia[j];
00335       iu = ib[j];
00336       do {
00337         ia[j] = ia[i];
00338         ib[j] = ib[i];
00339         j = i;
00340         i = i - jj;
00341         if (i < 0) break;
00342       } while(ia[i] > it);
00343       ia[j] = it;
00344       ib[j] = iu;
00345     }
00346   }
00347 }
00348 
00349 static void quicksort (float x[], int point[], int l, int nfilt) {
00350   float test, temp;
00351   int i, it, j, npt, ii;
00352 
00353   test = x[l];
00354   j = nfilt;
00355   for(i = 0; i < nfilt; i++) {
00356     if(i != l && test <= x[i]) {
00357       j = i;
00358       break;
00359     }
00360   }
00361   if(j - 1 == l) return;
00362   
00363   if(j < l) {
00364     temp = x[l];
00365     it = point[l];
00366     npt = l - j;
00367     for(i = 0; i < npt; i++) {
00368       ii = l - i - 1;
00369       x[ii+1] = x[ii];
00370       point[ii+1] = point[ii];
00371     }
00372     x[j] = temp;
00373     point[j] = it;
00374   }
00375   else if(j > l) {
00376     temp = x[l];
00377     it = point[l];
00378     j--;
00379     npt = j - l;
00380     if(npt != 0) {
00381       for(i = 0; i < npt; i++) {
00382         ii = l + i + 1;
00383         x[ii-1] = x[ii];
00384         point[ii-1] = point[ii];
00385       }
00386     }
00387     x[j] = temp;
00388     point[j] = it;
00389   }
00390 }
00391 
00392 
00393 /*
00394 
00395 $Log: imcore_filter.c,v $
00396 Revision 1.6  2010/09/09 12:09:57  jim
00397 Added docs
00398 
00399 Revision 1.5  2008/07/10 13:05:35  jim
00400 Modified code in padext to avoid valgrind warnings
00401 
00402 Revision 1.4  2008/01/22 19:42:17  jim
00403 Fixed memory allocation error
00404 
00405 Revision 1.3  2006/08/01 11:27:54  jim
00406 Modifications to imcore background estimation and to add ability to
00407 specify the smoothing kernel width
00408 
00409 Revision 1.2  2006/07/11 14:51:02  jim
00410 Fixed small bug in the range of the main loop
00411 
00412 Revision 1.1  2005/09/13 13:25:29  jim
00413 Initial entry after modifications to make cpl compliant
00414 
00415 
00416 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1