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