vircam_inpaint.c

00001 /* $Id: vircam_inpaint.c,v 1.5 2012/01/15 17:40:09 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/01/15 17:40:09 $
00024  * $Revision: 1.5 $
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 <string.h>
00036 
00037 #include "vircam_mods.h"
00038 #include "vircam_utils.h"
00039 #include "vircam_filt.h"
00040 #include "vircam_fits.h"
00041 #include "vircam_mask.h"
00042 #include "vircam_stats.h"
00043 
00044 /* Set up some global histogramming parameters */
00045 
00046 static int maxhist = 66536;
00047 static int minhistval = -1000;
00048 static int maxhistval = 65535;
00049 
00050 
00051 static void modelback(float *map, cpl_binary *bpm, int nx, int ny, int nbsize, 
00052                       float **skymap);
00053 static void medsig(int *hist, int ist, int itarg, float *med, float *sig);
00054 
00057 /*---------------------------------------------------------------------------*/
00092 /*---------------------------------------------------------------------------*/
00093 
00094 extern int vircam_inpaint(vir_fits *in, int nbsize, int *status) {
00095     int i,nx,ny;
00096     float *data,*skymap;
00097     cpl_binary *bpm;
00098     cpl_image *im;
00099     
00100     /* Inherited status */
00101 
00102     if (*status != VIR_OK)
00103         return(*status);
00104 
00105     /* Set the data arrays */
00106 
00107     im = vircam_fits_get_image(in);
00108     data = cpl_image_get_data_float(im);
00109     bpm = cpl_mask_get_data(cpl_image_get_bpm(im));
00110     nx = (int)cpl_image_get_size_x(im);
00111     ny = (int)cpl_image_get_size_y(im);
00112 
00113     /* Model out the background */
00114 
00115     modelback(data,bpm,nx,ny,nbsize,&skymap);
00116 
00117     /* Now inpaint the bad bits */
00118 
00119     for (i = 0; i < nx*ny; i++) 
00120         if (bpm[i]) 
00121             data[i] = skymap[i];
00122     freespace(skymap);
00123 
00124     /* Get out of here */
00125 
00126     GOOD_STATUS
00127 }
00128 
00129 /*---------------------------------------------------------------------------*/
00157 /*---------------------------------------------------------------------------*/
00158 
00159 static void modelback(float *map, cpl_binary *bpm, int nx, int ny, 
00160                       int nbsize, float **skymap) {
00161     float fracx,fracy,skymed,sigma,skymedc,sigmac,avsky,fnbsize,dely,delx;
00162     float t1,t2,*bvals;
00163     int ifracx,ifracy,nbsizx,nbsizy,nbx,nby,npixstripe,l,i,ll;
00164     int isquare,ilev,j,iclip,mcpix,iloop,irej,nbsizo2,kk,k,iby,ibyp1,ibx,ibxp1;
00165     int *shist,**hist,*nnp,jj1,jj2,jj3,jj4;
00166     unsigned char *badmask;
00167 
00168     /* Check to see if nbsize is close to exact divisor */
00169 
00170     fracx = ((float)nx)/((float)nbsize);
00171     fracy = ((float)ny)/((float)nbsize);
00172     ifracx = (int)(fracx + 0.1);
00173     ifracy = (int)(fracy + 0.1);
00174     nbsizx = nx/ifracx;
00175     nbsizy = ny/ifracy;
00176     nbsize = max(vircam_nint(0.9*nbsize),min(nbsize,min(nbsizx,nbsizy)));
00177     nbsize = min(nx,min(ny,nbsize)); /* trap for small maps */
00178 
00179     /* Divide the map into partitions */
00180 
00181     nbx = nx/nbsize;
00182     nby = ny/nbsize;
00183     npixstripe = nbsize*nx;
00184 
00185     /* Get histogram workspace if you can */
00186 
00187     hist = cpl_malloc(nbx*sizeof(int *));
00188     for (l = 0; l < nbx; l++)
00189         hist[l] = cpl_malloc(maxhist*sizeof(int));
00190 
00191     /* Same for background values array and for a bad mask */
00192 
00193     bvals = cpl_malloc(nbx*nby*sizeof(float *));
00194     badmask = cpl_calloc(nbx*nby,sizeof(unsigned char *));
00195 
00196     /* Finally a counter array */
00197 
00198     nnp = cpl_malloc(nbx*sizeof(int));
00199 
00200     /* Loop for each row of background squares. Start by initialising
00201        the accumulators and histograms */
00202 
00203     for (l = 0; l < nby; l++) {
00204         memset((char *)nnp,0,nbx*sizeof(*nnp));
00205         for (i = 0; i < nbx; i++)
00206             memset((char *)hist[i],0,maxhist*sizeof(int));
00207 
00208         /* Skim through the data in this stripe. Find out which square each
00209            belongs to and add it it to the relevant histogram */
00210 
00211         ll = l*npixstripe;
00212         for (i = 0; i < npixstripe; i++) {
00213             if (bpm[ll+i] == 0)   {
00214                 isquare = (int)((float)(i % nx)/(float)nbsize);
00215                 isquare = min(nbx-1,max(0,isquare));
00216                 ilev = min(maxhistval,max(minhistval,vircam_nint(map[i+ll])));
00217                 hist[isquare][ilev-minhistval] += 1;
00218                 nnp[isquare] += 1;
00219             }
00220         }
00221 
00222 
00223         /* Only do background estimation if enough pixels */
00224 
00225         for (j = 0; j < nbx; j++) {
00226             jj1 = l*nbx + j;
00227             if (nnp[j] > 0.25*nbsize*nbsize) {
00228                 shist = hist[j];
00229                 medsig(shist,minhistval-1,nnp[j],&skymed,&sigma);
00230 
00231                 /* Do an iterative 3-sigma upper clip to give a more robust
00232                    estimator */
00233 
00234                 iclip = maxhistval;
00235                 mcpix = nnp[j];
00236                 skymedc = skymed;
00237                 sigmac = sigma;
00238                 for (iloop = 0; iloop < 3; iloop++) {
00239                     irej = 0;
00240                     for (i = vircam_nint(skymedc+3.0*sigmac); i <= iclip; i++)
00241                         irej += shist[i-minhistval];
00242                     if (irej == 0)
00243                         break;
00244                     iclip = vircam_nint(skymedc+3.0*sigmac) - 1;
00245                     mcpix = mcpix - irej;
00246                     medsig(shist,minhistval-1,mcpix,&skymedc,
00247                            &sigmac);
00248                 }
00249                 bvals[jj1] = skymedc;
00250                 badmask[jj1] = 0;
00251             } else {
00252                 bvals[jj1] = -1000.0;
00253                 badmask[jj1] = 1;
00254             }
00255         }
00256 
00257     }
00258 
00259     /* Filter raw background values */
00260 
00261     vircam_bfilt(bvals,badmask,nbx,nby,3,MEDIANCALC,1);
00262 
00263     /* Compute average sky level */
00264 
00265     avsky = vircam_med(bvals,badmask,(long)(nbx*nby));
00266     freespace(badmask);
00267 
00268     /* OK now create a sky map */
00269     
00270     *skymap = cpl_malloc(nx*ny*sizeof(float));
00271     nbsizo2 = nbsize/2;
00272     fnbsize = 1.0/((float)nbsize);
00273     for (k = 0; k < ny; k++) {
00274         kk = k*nx;
00275 
00276         /* Nearest background pixel vertically */
00277 
00278         iby = (k + 1 + nbsizo2)/nbsize;
00279         ibyp1 = iby + 1;
00280         iby = min(nby,max(1,iby));
00281         ibyp1 = min(nby,ibyp1);
00282         dely = (k + 1 - nbsize*iby + nbsizo2)*fnbsize;
00283 
00284         for (j = 0; j < nx; j++) {
00285 
00286             /* nearest background pixel across */
00287 
00288             ibx = (j + 1 + nbsizo2)/nbsize;
00289             ibxp1 = ibx + 1;
00290             ibx = min(nbx,max(1,ibx));
00291             ibxp1 = min(nbx,ibxp1);
00292             delx = (j + 1 - nbsize*ibx + nbsizo2)*fnbsize;
00293             jj1 = (iby-1)*nbx + ibx - 1;
00294             jj2 = (ibyp1-1)*nbx + ibx - 1;
00295             jj3 = (iby-1)*nbx + ibxp1 - 1;
00296             jj4 = (ibyp1-1)*nbx + ibxp1 - 1;
00297 
00298             /* bilinear interpolation to find background */
00299 
00300             t1 = (1.0 - dely)*bvals[jj1] + dely*bvals[jj2];
00301             t2 = (1.0 - dely)*bvals[jj3] + dely*bvals[jj4];
00302             (*skymap)[kk+j] = (1.0 - delx)*t1 + delx*t2;
00303         }
00304     }
00305 
00306     /* Free some workspace */
00307 
00308     for (l = 0; l < nbx; l++)
00309         freespace(hist[l]);
00310     freespace(hist);
00311     freespace(bvals);
00312     freespace(nnp);
00313 }
00314 
00315 /*---------------------------------------------------------------------------*/
00344 /*---------------------------------------------------------------------------*/
00345 
00346 static void medsig(int *hist, int ist, int itarg, float *med, float *sig) {
00347     int isum, medata,indx;
00348     float ffrac,sigmed;
00349 
00350     /* The median. We start in the lowest allowable bin defined by 'ist'. 
00351        We then continue summing up until we have reached just over 
00352        half the allowed contributions defined by 'itarg'. */
00353 
00354     isum = 0;
00355     medata = ist;
00356     indx = medata - minhistval;
00357     while (isum <= (itarg+1)/2 && indx < maxhist - 1) {
00358         medata++;
00359         indx = medata - minhistval;
00360         isum += hist[indx];
00361     }
00362     ffrac = (float)(isum - (itarg+1)/2)/(float)hist[medata-minhistval];
00363     *med = (float)medata - ffrac + 0.5;
00364 
00365     /* The sigma. We start in the lowest allowable bin defined by 'ist'. 
00366        We then continue summing up until we have reached just over 
00367        3/4 of the allowed contributions defined by 'itarg'.  The sigma
00368        is defined as 1.48* the distance from this third quartile to the
00369        median point. A minimal value is also included. */
00370 
00371     isum = 0;
00372     medata = ist;
00373     indx = medata - minhistval;
00374     while (isum <= (itarg+3)/4 && indx < maxhist - 1) {
00375         medata++;
00376         indx = medata - minhistval;
00377         isum += hist[indx];
00378     }
00379     ffrac = (float)(isum - (itarg+3)/4)/(float)hist[medata-minhistval];
00380     sigmed = (float)medata - ffrac + 0.5;
00381     *sig = 1.48*(*med - sigmed);
00382     *sig = max(2.5,*sig);
00383 }
00384 
00385 
00388 /*
00389 
00390 $Log: vircam_inpaint.c,v $
00391 Revision 1.5  2012/01/15 17:40:09  jim
00392 Minor modifications to take into accout the changes in cpl API for v6
00393 
00394 Revision 1.4  2010/09/09 12:11:09  jim
00395 Fixed problems with docs that make doxygen barf
00396 
00397 Revision 1.3  2010/06/07 12:42:40  jim
00398 Modifications to get rid of compiler gripes
00399 
00400 Revision 1.2  2009/02/20 10:53:52  jim
00401 Fixed small memory leak
00402 
00403 Revision 1.1  2008/10/13 08:13:21  jim
00404 New entry
00405 
00406 
00407 */

Generated on 5 Mar 2013 for VIRCAM Pipeline by  doxygen 1.6.1