VIRCAM Pipeline  1.3.4
vircam_inpaint.c
1 /* $Id: vircam_inpaint.c,v 1.5 2012-01-15 17:40:09 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-01-15 17:40:09 $
24  * $Revision: 1.5 $
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 <string.h>
36 
37 #include "vircam_mods.h"
38 #include "vircam_utils.h"
39 #include "vircam_filt.h"
40 #include "vircam_fits.h"
41 #include "vircam_mask.h"
42 #include "vircam_stats.h"
43 
44 /* Set up some global histogramming parameters */
45 
46 static int maxhist = 66536;
47 static int minhistval = -1000;
48 static int maxhistval = 65535;
49 
50 
51 static void modelback(float *map, cpl_binary *bpm, int nx, int ny, int nbsize,
52  float **skymap);
53 static void medsig(int *hist, int ist, int itarg, float *med, float *sig);
54 
57 /*---------------------------------------------------------------------------*/
92 /*---------------------------------------------------------------------------*/
93 
94 extern int vircam_inpaint(vir_fits *in, int nbsize, int *status) {
95  int i,nx,ny;
96  float *data,*skymap;
97  cpl_binary *bpm;
98  cpl_image *im;
99 
100  /* Inherited status */
101 
102  if (*status != VIR_OK)
103  return(*status);
104 
105  /* Set the data arrays */
106 
107  im = vircam_fits_get_image(in);
108  data = cpl_image_get_data_float(im);
109  bpm = cpl_mask_get_data(cpl_image_get_bpm(im));
110  nx = (int)cpl_image_get_size_x(im);
111  ny = (int)cpl_image_get_size_y(im);
112 
113  /* Model out the background */
114 
115  modelback(data,bpm,nx,ny,nbsize,&skymap);
116 
117  /* Now inpaint the bad bits */
118 
119  for (i = 0; i < nx*ny; i++)
120  if (bpm[i])
121  data[i] = skymap[i];
122  freespace(skymap);
123 
124  /* Get out of here */
125 
126  GOOD_STATUS
127 }
128 
129 /*---------------------------------------------------------------------------*/
157 /*---------------------------------------------------------------------------*/
158 
159 static void modelback(float *map, cpl_binary *bpm, int nx, int ny,
160  int nbsize, float **skymap) {
161  float fracx,fracy,skymed,sigma,skymedc,sigmac,avsky,fnbsize,dely,delx;
162  float t1,t2,*bvals;
163  int ifracx,ifracy,nbsizx,nbsizy,nbx,nby,npixstripe,l,i,ll;
164  int isquare,ilev,j,iclip,mcpix,iloop,irej,nbsizo2,kk,k,iby,ibyp1,ibx,ibxp1;
165  int *shist,**hist,*nnp,jj1,jj2,jj3,jj4;
166  unsigned char *badmask;
167 
168  /* Check to see if nbsize is close to exact divisor */
169 
170  fracx = ((float)nx)/((float)nbsize);
171  fracy = ((float)ny)/((float)nbsize);
172  ifracx = (int)(fracx + 0.1);
173  ifracy = (int)(fracy + 0.1);
174  nbsizx = nx/ifracx;
175  nbsizy = ny/ifracy;
176  nbsize = max(vircam_nint(0.9*nbsize),min(nbsize,min(nbsizx,nbsizy)));
177  nbsize = min(nx,min(ny,nbsize)); /* trap for small maps */
178 
179  /* Divide the map into partitions */
180 
181  nbx = nx/nbsize;
182  nby = ny/nbsize;
183  npixstripe = nbsize*nx;
184 
185  /* Get histogram workspace if you can */
186 
187  hist = cpl_malloc(nbx*sizeof(int *));
188  for (l = 0; l < nbx; l++)
189  hist[l] = cpl_malloc(maxhist*sizeof(int));
190 
191  /* Same for background values array and for a bad mask */
192 
193  bvals = cpl_malloc(nbx*nby*sizeof(float *));
194  badmask = cpl_calloc(nbx*nby,sizeof(unsigned char *));
195 
196  /* Finally a counter array */
197 
198  nnp = cpl_malloc(nbx*sizeof(int));
199 
200  /* Loop for each row of background squares. Start by initialising
201  the accumulators and histograms */
202 
203  for (l = 0; l < nby; l++) {
204  memset((char *)nnp,0,nbx*sizeof(*nnp));
205  for (i = 0; i < nbx; i++)
206  memset((char *)hist[i],0,maxhist*sizeof(int));
207 
208  /* Skim through the data in this stripe. Find out which square each
209  belongs to and add it it to the relevant histogram */
210 
211  ll = l*npixstripe;
212  for (i = 0; i < npixstripe; i++) {
213  if (bpm[ll+i] == 0) {
214  isquare = (int)((float)(i % nx)/(float)nbsize);
215  isquare = min(nbx-1,max(0,isquare));
216  ilev = min(maxhistval,max(minhistval,vircam_nint(map[i+ll])));
217  hist[isquare][ilev-minhistval] += 1;
218  nnp[isquare] += 1;
219  }
220  }
221 
222 
223  /* Only do background estimation if enough pixels */
224 
225  for (j = 0; j < nbx; j++) {
226  jj1 = l*nbx + j;
227  if (nnp[j] > 0.25*nbsize*nbsize) {
228  shist = hist[j];
229  medsig(shist,minhistval-1,nnp[j],&skymed,&sigma);
230 
231  /* Do an iterative 3-sigma upper clip to give a more robust
232  estimator */
233 
234  iclip = maxhistval;
235  mcpix = nnp[j];
236  skymedc = skymed;
237  sigmac = sigma;
238  for (iloop = 0; iloop < 3; iloop++) {
239  irej = 0;
240  for (i = vircam_nint(skymedc+3.0*sigmac); i <= iclip; i++)
241  irej += shist[i-minhistval];
242  if (irej == 0)
243  break;
244  iclip = vircam_nint(skymedc+3.0*sigmac) - 1;
245  mcpix = mcpix - irej;
246  medsig(shist,minhistval-1,mcpix,&skymedc,
247  &sigmac);
248  }
249  bvals[jj1] = skymedc;
250  badmask[jj1] = 0;
251  } else {
252  bvals[jj1] = -1000.0;
253  badmask[jj1] = 1;
254  }
255  }
256 
257  }
258 
259  /* Filter raw background values */
260 
261  vircam_bfilt(bvals,badmask,nbx,nby,3,MEDIANCALC,1);
262 
263  /* Compute average sky level */
264 
265  avsky = vircam_med(bvals,badmask,(long)(nbx*nby));
266  freespace(badmask);
267 
268  /* OK now create a sky map */
269 
270  *skymap = cpl_malloc(nx*ny*sizeof(float));
271  nbsizo2 = nbsize/2;
272  fnbsize = 1.0/((float)nbsize);
273  for (k = 0; k < ny; k++) {
274  kk = k*nx;
275 
276  /* Nearest background pixel vertically */
277 
278  iby = (k + 1 + nbsizo2)/nbsize;
279  ibyp1 = iby + 1;
280  iby = min(nby,max(1,iby));
281  ibyp1 = min(nby,ibyp1);
282  dely = (k + 1 - nbsize*iby + nbsizo2)*fnbsize;
283 
284  for (j = 0; j < nx; j++) {
285 
286  /* nearest background pixel across */
287 
288  ibx = (j + 1 + nbsizo2)/nbsize;
289  ibxp1 = ibx + 1;
290  ibx = min(nbx,max(1,ibx));
291  ibxp1 = min(nbx,ibxp1);
292  delx = (j + 1 - nbsize*ibx + nbsizo2)*fnbsize;
293  jj1 = (iby-1)*nbx + ibx - 1;
294  jj2 = (ibyp1-1)*nbx + ibx - 1;
295  jj3 = (iby-1)*nbx + ibxp1 - 1;
296  jj4 = (ibyp1-1)*nbx + ibxp1 - 1;
297 
298  /* bilinear interpolation to find background */
299 
300  t1 = (1.0 - dely)*bvals[jj1] + dely*bvals[jj2];
301  t2 = (1.0 - dely)*bvals[jj3] + dely*bvals[jj4];
302  (*skymap)[kk+j] = (1.0 - delx)*t1 + delx*t2;
303  }
304  }
305 
306  /* Free some workspace */
307 
308  for (l = 0; l < nbx; l++)
309  freespace(hist[l]);
310  freespace(hist);
311  freespace(bvals);
312  freespace(nnp);
313 }
314 
315 /*---------------------------------------------------------------------------*/
344 /*---------------------------------------------------------------------------*/
345 
346 static void medsig(int *hist, int ist, int itarg, float *med, float *sig) {
347  int isum, medata,indx;
348  float ffrac,sigmed;
349 
350  /* The median. We start in the lowest allowable bin defined by 'ist'.
351  We then continue summing up until we have reached just over
352  half the allowed contributions defined by 'itarg'. */
353 
354  isum = 0;
355  medata = ist;
356  indx = medata - minhistval;
357  while (isum <= (itarg+1)/2 && indx < maxhist - 1) {
358  medata++;
359  indx = medata - minhistval;
360  isum += hist[indx];
361  }
362  ffrac = (float)(isum - (itarg+1)/2)/(float)hist[medata-minhistval];
363  *med = (float)medata - ffrac + 0.5;
364 
365  /* The sigma. We start in the lowest allowable bin defined by 'ist'.
366  We then continue summing up until we have reached just over
367  3/4 of the allowed contributions defined by 'itarg'. The sigma
368  is defined as 1.48* the distance from this third quartile to the
369  median point. A minimal value is also included. */
370 
371  isum = 0;
372  medata = ist;
373  indx = medata - minhistval;
374  while (isum <= (itarg+3)/4 && indx < maxhist - 1) {
375  medata++;
376  indx = medata - minhistval;
377  isum += hist[indx];
378  }
379  ffrac = (float)(isum - (itarg+3)/4)/(float)hist[medata-minhistval];
380  sigmed = (float)medata - ffrac + 0.5;
381  *sig = 1.48*(*med - sigmed);
382  *sig = max(2.5,*sig);
383 }
384 
385 
388 /*
389 
390 $Log: not supported by cvs2svn $
391 Revision 1.4 2010/09/09 12:11:09 jim
392 Fixed problems with docs that make doxygen barf
393 
394 Revision 1.3 2010/06/07 12:42:40 jim
395 Modifications to get rid of compiler gripes
396 
397 Revision 1.2 2009/02/20 10:53:52 jim
398 Fixed small memory leak
399 
400 Revision 1.1 2008/10/13 08:13:21 jim
401 New entry
402 
403 
404 */
int vircam_inpaint(vir_fits *in, int nbsize, int *status)
Inpaint pixels or patches in a map.
cpl_image * vircam_fits_get_image(vir_fits *p)
Definition: vircam_fits.c:349
float vircam_med(float *data, unsigned char *bpm, long npts)
Definition: vircam_stats.c:89
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