VIRCAM Pipeline  1.3.3
imcore_opm.c
1 /* $Id: imcore_opm.c,v 1.6 2013-10-15 16:21:32 jim Exp $
2  *
3  * This file is part of the VIRCAM Pipeline
4  * Copyright (C) 2005 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: 2013-10-15 16:21:32 $
24  * $Revision: 1.6 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <math.h>
31 #include <string.h>
32 
33 #include "ap.h"
34 #include "util.h"
35 #include "imcore.h"
36 #include "floatmath.h"
37 
38 #include "../vircam_pfits.h"
39 #include "../vircam_fits.h"
40 
41 #define FATAL_ERR(_a) {freetable(tab); cpl_msg_error(fctid,_a); tidy(); return(VIR_FATAL);}
42 
43 #define NW 5
44 
45 static float *indata = NULL;
46 static int *confdata = NULL;
47 static float *confsqrt = NULL;
48 static float *smoothed = NULL;
49 static float *smoothedc = NULL;
50 static unsigned char *mflag = NULL;
51 static ap_t ap;
52 static int freeconf = 0;
53 static float *incopy = NULL;
54 static int *ccopy = NULL;
55 
56 static float weights[NW*NW];
57 static float weightc[NW*NW];
58 static long nx;
59 static long ny;
60 
61 static void crweights(float);
62 static void convolve(int);
63 static void tidy(void);
64 
67 /*---------------------------------------------------------------------------*/
110 /*---------------------------------------------------------------------------*/
111 
112 extern int imcore_opm(vir_fits *infile, vir_fits *conf, int ipix,
113  float threshold, int nbsize, float filtfwhm,
114  int niter) {
115 
116  int i,retval,j,nw2,iter,nclip,nxc,nyc;
117  float fconst,nullval,skymed,skysig,thresh,xintmin,offset;
118  float isat,isatbc,*current,junk,*currentc;
119  long npix;
120  cpl_image *map,*cmap;
121  cpl_propertylist *plist;
122  cpl_binary *opm;
123  const char *fctid = "imcore_opm";
124 
125  /* Useful constants */
126 
127  fconst = CPL_MATH_LOG2E;
128  nullval = 0.0;
129  cattype = 4;
130 
131  /* Open input image */
132 
133  map = vircam_fits_get_image(infile);
134  if ((indata = cpl_image_get_data_float(map)) == NULL)
135  FATAL_ERR("Error getting image data");
136  nx = (long)cpl_image_get_size_x(map);
137  ny = (long)cpl_image_get_size_y(map);
138  npix = nx*ny;
139  if (vircam_pfits_get_gain(vircam_fits_get_ehu(infile),&gain) != VIR_OK)
140  gain = 5.0;
141 
142  /* Open the associated confidence map, if it exists */
143 
144  if (conf != NULL) {
145  cmap = vircam_fits_get_image(conf);
146  if ((confdata = cpl_image_get_data(cmap)) == NULL)
147  FATAL_ERR("Error getting confidence map data");
148  nxc = (long)cpl_image_get_size_x(cmap);
149  nyc = (long)cpl_image_get_size_y(cmap);
150  if ((nx != nxc) || (ny != nyc))
151  FATAL_ERR("Input image and confidence dimensions don't match");
152  freeconf = 0;
153  } else {
154  confdata = cpl_malloc(npix*sizeof(*confdata));
155  for (i = 0; i < npix; i++)
156  confdata[i] = 100;
157  freeconf = 1;
158  cmap = NULL;
159  }
160  confsqrt = cpl_malloc(npix*sizeof(*confsqrt));
161  for (i = 0; i < npix; i++)
162  confsqrt[i] = sqrt(0.01*(float)confdata[i]);
163 
164  /* Make a copy of each */
165 
166  incopy = cpl_malloc(npix*sizeof(*incopy));
167  ccopy = cpl_malloc(npix*sizeof(*ccopy));
168  memmove(incopy,indata,npix*sizeof(*incopy));
169  memmove(ccopy,confdata,npix*sizeof(*ccopy));
170 
171  /* Get mflag array for flagging saturated pixels */
172 
173  mflag = cpl_calloc(npix,sizeof(*mflag));
174 
175  /* Open the ap structure and define some stuff in it */
176 
177  ap.lsiz = nx;
178  ap.csiz = ny;
179  ap.inframe = map;
180  ap.conframe = cmap;
181  ap.xtnum = vircam_fits_get_nexten(infile);
182  apinit(&ap);
183  ap.indata = indata;
184  ap.confdata = confdata;
185  ap.multiply = 1;
186  ap.ipnop = ipix;
187  ap.mflag = mflag;
188  ap.fconst = fconst;
189  ap.filtfwhm = filtfwhm;
190 
191  /* Open the output catalogue FITS table */
192 
193  tabinit(&ap);
194 
195  /* Set up the data flags */
196 
197  for (i = 0; i < npix ; i++)
198  if (confdata[i] == 0)
199  mflag[i] = MF_ZEROCONF;
200  else if (indata[i] < STUPID_VALUE)
201  mflag[i] = MF_STUPID_VALUE;
202  else
203  mflag[i] = MF_CLEANPIX;
204 
205  /* Compute a saturation level before background correction. */
206 
207  retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isatbc);
208  if (retval != VIR_OK)
209  FATAL_ERR("Error calculating saturation level");
210 
211  /* Flag saturated pixels */
212 
213  for (i = 0; i < npix ; i++)
214  if (mflag[i] == MF_CLEANPIX && indata[i] > isatbc)
215  mflag[i] = MF_SATURATED;
216 
217  /* Get a bit of workspace for buffers */
218 
219  smoothed = cpl_malloc(nx*sizeof(*smoothed));
220  smoothedc = cpl_malloc(nx*sizeof(*smoothedc));
221 
222  /* Set the weights */
223 
224  crweights(filtfwhm);
225  nw2 = NW/2;
226 
227  /* Iteration loop */
228 
229  for (iter = 0; iter < niter; iter++) {
230 
231  /* Compute the background variation and remove it from the data*/
232 
233  retval = imcore_background(&ap,nbsize,nullval);
234  if (retval != VIR_OK)
235  FATAL_ERR("Error calculating background");
236 
237  /* Compute a saturation level */
238 
239  retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isat);
240  if (retval != VIR_OK)
241  FATAL_ERR("Error calculating saturation");
242 
243  /* Compute background statistics */
244 
245  retval = imcore_backstats(&ap,nullval,0,&skymed,&skysig,&junk);
246  if (retval != VIR_OK)
247  FATAL_ERR("Error calculating background stats");
248 
249  /* Get the propertly list for the input file and add some info*/
250 
251  plist = vircam_fits_get_ehu(infile);
252  cpl_propertylist_update_float(plist,"ESO DRS SKYLEVEL",skymed);
253  cpl_propertylist_set_comment(plist,"ESO DRS SKYLEVEL",
254  "[adu] Median sky brightness");
255  cpl_propertylist_update_float(plist,"ESO DRS SKYNOISE",skysig);
256  cpl_propertylist_set_comment(plist,"ESO DRS SKYNOISE",
257  "[adu] Pixel noise at sky level");
258 
259  /* Take mean sky level out of data */
260 
261  for (i = 0; i < nx*ny; i++)
262  indata[i] -= skymed;
263 
264  /* Work out isophotal detection threshold levels */
265 
266  thresh = threshold*skysig;
267 
268  /* Minimum intensity for consideration */
269 
270  xintmin = 1.5*thresh*((float)ipix);
271 
272  /* Actual areal profile levels: T, 2T, 4T, 8T,...but written wrt T
273  i.e. threshold as a power of 2 */
274 
275  offset = logf(thresh)*fconst;
276 
277  /* Define a few things more things in ap structure */
278 
279  ap.areal_offset = offset;
280  ap.thresh = thresh;
281  ap.xintmin = xintmin;
282  ap.sigma = skysig;
283  ap.background = skymed;
284  ap.saturation = isat;
285 
286  /* Right, now for the extraction loop. Begin by defining a group of
287  three rows of data and confidence */
288 
289  for (j = nw2; j < ny-nw2; j++) {
290  current = indata + j*nx;
291  currentc = confsqrt + j*nx;
292  convolve(j);
293 
294  /* Do the detection now */
295 
296  apline(&ap,current,currentc,smoothed,smoothedc,j,NULL);
297 
298  /* Make sure we're not overruning the stacks */
299 
300  if (ap.ibstack > (ap.maxbl - ap.lsiz))
301  apfu(&ap);
302  if (ap.ipstack > (ap.maxpa*3/4))
303  for (i = 0; i < ap.maxpa*3/8; i++)
304  apfu(&ap);
305 
306  /* See if there are any images to terminate */
307 
308  if (ap.ipstack > 1)
309  terminate(&ap);
310  }
311 
312  /* Restore input data to its former glory. Update confidence map */
313 
314  memmove(indata,incopy,npix*sizeof(*indata));
315  nclip = 0;
316  opm = cpl_mask_get_data(ap.opmask);
317  for (i = 0; i < npix; i++) {
318  if (opm[i]) {
319  confdata[i] = 0;
320  opm[i] = 0;
321  nclip++;
322  }
323  }
324  if (ap.backmap.bvals != NULL) {
325  for (i = 0; i < ap.backmap.nby; i++)
326  freespace(ap.backmap.bvals[i]);
327  freespace(ap.backmap.bvals);
328  }
329  if (nclip == 0)
330  break;
331  }
332  opm = cpl_mask_get_data(ap.opmask);
333  for (i = 0; i < npix; i++)
334  opm[i] = (confdata[i] == 0);
335  memmove(confdata,ccopy,npix*sizeof(*confdata));
336  retval = tabclose(&ap);
337 
338  /* Tidy and exit */
339 
340  tidy();
341  return(VIR_OK);
342 }
343 
344 /*---------------------------------------------------------------------------*/
361 /*---------------------------------------------------------------------------*/
362 
363 static void crweights(float filtfwhm) {
364  int i,j,nw2,n;
365  double gsigsq,di,dj;
366  float renorm;
367 
368  /* Get the kernel size */
369 
370  nw2 = NW/2;
371 
372  /* Set the normalisation constants */
373 
374  gsigsq = 1.0/(2.0*pow(MAX(1.0,(double)filtfwhm)/2.35,2.0));
375  renorm = 0.0;
376 
377  /* Now work out the weights */
378 
379  n = -1;
380  for (i = -nw2; i <= nw2; i++) {
381  di = (double)i;
382  di *= gsigsq*di;
383  for (j = -nw2; j <= nw2; j++) {
384  dj = (double)j;
385  dj *= gsigsq*dj;
386  n++;
387  weights[n] = (float)exp(-(di + dj));
388  renorm += weights[n];
389  }
390  }
391 
392  /* Now normalise the weights */
393 
394  n = -1;
395  for (i = -nw2; i <= nw2; i++) {
396  for (j = -nw2; j <= nw2; j++) {
397  n++;
398  weights[n] /= renorm;
399  /* weightc[n] = 0.01*weights[n]; */
400  weightc[n] = weights[n];
401  }
402  }
403 }
404 
405 /*---------------------------------------------------------------------------*/
423 /*---------------------------------------------------------------------------*/
424 
425 static void convolve(int ir) {
426  int i,nw2,ix,jx,jy,n;
427  float *idata,*cdata;
428 
429  /* Zero the summations */
430 
431  for (i = 0; i < nx; i++) {
432  smoothed[i] = 0.0;
433  smoothedc[i] = 0.0;
434  }
435 
436  /* Now big is the smoothing kernel? */
437 
438  nw2 = NW/2;
439 
440  /* Now loop for each column */
441 
442  for (ix = nw2; ix < nx-nw2; ix++) {
443  n = -1;
444  for (jy = ir-nw2; jy <= ir+nw2; jy++) {
445  idata = indata + jy*nx;
446  cdata = confsqrt + jy*nx;
447  for (jx = ix-nw2; jx <= ix+nw2; jx++) {
448  n++;
449  smoothed[ix] += weights[n]*idata[jx];
450  smoothedc[ix] += weightc[n]*idata[jx]*cdata[jx];
451  }
452  }
453  }
454 }
455 
456 static void tidy(void) {
457 
458  if (freeconf)
459  freespace(confdata);
460  freespace(confsqrt);
461  freespace(smoothed);
462  freespace(smoothedc);
463  freespace(mflag);
464  freespace(incopy);
465  freespace(ccopy);
466  apclose(&ap);
467 }
468 
469 /*
470 
471 $Log: not supported by cvs2svn $
472 Revision 1.5 2010/09/10 11:23:09 jim
473 Fixed declaration of currentc
474 
475 Revision 1.4 2010/09/09 12:09:49 jim
476 Modified to use sqrt weighting with confidence maps. Also added docs
477 
478 Revision 1.3 2010/06/03 11:40:00 jim
479 fixed definition of tidy routine to include 'void' as argument list
480 
481 Revision 1.2 2009/09/09 09:42:25 jim
482 modified to use CPL defined macros for constants
483 
484 Revision 1.1 2008/10/13 08:07:26 jim
485 New entry
486 
487 
488 */