VIRCAM Pipeline  2.3.12
imcore_conf.c
1 /* $Id: imcore_conf.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 
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 
34 #include <cpl.h>
35 #include "casu_fits.h"
36 #include "casu_wcsutils.h"
37 
38 #include "ap.h"
39 #include "util.h"
40 #include "imcore.h"
41 #include "floatmath.h"
42 #include "imcore_version.h"
43 
44 #define FATAL_ERR(_a) {freetable(tab); cpl_msg_error(fctid,_a); tidy(); return(CASU_FATAL);}
45 
46 #define NW 5
47 
48 static float *smoothed = NULL;
49 static float *smoothedc = NULL;
50 static unsigned char *mflag = NULL;
51 static float *indata = NULL;
52 static int *confdata = NULL;
53 static float *confsqrt = NULL;
54 static ap_t ap;
55 static int freeconf = 0;
56 
57 static float weights[NW*NW];
58 static float weightc[NW*NW];
59 static long nx;
60 static long ny;
61 
62 static void crweights(float);
63 static void convolve(int);
64 static void tidy(void);
65 
68 /*---------------------------------------------------------------------------*/
145 /*---------------------------------------------------------------------------*/
146 
147 extern int imcore_conf(casu_fits *infile, casu_fits *conf, int ipix,
148  float threshold, int icrowd, float rcore, int nbsize,
149  int cattype, float filtfwhm, float gain,
150  casu_tfits **outcat) {
151 
152  int i,retval,mulpix,j,nw2,status,nobjects,imcore_xcol,imcore_ycol;
153  float fconst,nullval,skymed,skysig,thresh,xintmin,offset;
154  float *current,isatbc,isat,junk,*currentc;
155  long npix,nxc,nyc,npts;
156  cpl_image *map,*cmap;
157  cpl_propertylist *plist,*extra;
158  cpl_table *tab;
159  char card[64];
160  const char *fctid = "imcore_conf";
161 
162  /* Initialise output */
163 
164  *outcat = NULL;
165 
166  /* Useful constants */
167 
168  fconst = CPL_MATH_LOG2E;
169  nullval = 0.0;
170  nobjects = 0;
171 
172  /* Open input image */
173 
174  tab = NULL;
175  map = casu_fits_get_image(infile);
176  if ((indata = cpl_image_get_data_float(map)) == NULL)
177  FATAL_ERR("Error getting image data");
178  nx = (long)cpl_image_get_size_x(map);
179  ny = (long)cpl_image_get_size_y(map);
180  npts = nx*ny;
181 
182  /* Open the associated confidence map, if it exists */
183 
184  if (conf != NULL) {
185  cmap = casu_fits_get_image(conf);
186  if ((confdata = cpl_image_get_data(cmap)) == NULL)
187  FATAL_ERR("Error getting confidence map data");
188  nxc = (long)cpl_image_get_size_x(cmap);
189  nyc = (long)cpl_image_get_size_y(cmap);
190  if ((nx != nxc) || (ny != nyc))
191  FATAL_ERR("Input image and confidence dimensions don't match");
192  freeconf = 0;
193  } else {
194  confdata = cpl_malloc(npts*sizeof(*confdata));
195  for (i = 0; i < npts; i++)
196  confdata[i] = 100;
197  freeconf = 1;
198  cmap = NULL;
199  }
200  confsqrt = cpl_malloc(npts*sizeof(*confsqrt));
201  for (i = 0; i < npts; i++)
202  confsqrt[i] = sqrt(0.01*(float)confdata[i]);
203 
204  /* Get mflag array for flagging saturated pixels */
205 
206  npix = nx*ny;
207  mflag = cpl_calloc(npix,sizeof(*mflag));
208 
209  /* Open the ap structure and define some stuff in it */
210 
211  ap.lsiz = nx;
212  ap.csiz = ny;
213  ap.inframe = map;
214  ap.conframe = cmap;
215  ap.xtnum = casu_fits_get_nexten(infile);
216  imcore_apinit(&ap);
217  ap.indata = indata;
218  ap.confdata = confdata;
219  ap.multiply = 1;
220  ap.ipnop = ipix;
221  ap.mflag = mflag;
222  ap.rcore = rcore;
223  ap.filtfwhm = filtfwhm;
224  ap.icrowd = icrowd;
225  ap.fconst = fconst;
226 
227  /* Open the output catalogue FITS table */
228 
229  imcore_tabinit(&ap,&imcore_xcol,&imcore_ycol,cattype,&tab);
230 
231  /* Set up the data flags */
232 
233  for (i = 0; i < npix; i++)
234  if (confdata[i] == 0)
235  mflag[i] = MF_ZEROCONF;
236  else if (indata[i] < STUPID_VALUE)
237  mflag[i] = MF_STUPID_VALUE;
238  else
239  mflag[i] = MF_CLEANPIX;
240 
241  /* Compute a saturation level before background correction. */
242 
243  retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isatbc);
244  if (retval != CASU_OK)
245  FATAL_ERR("Error calculating saturation level");
246 
247  /* Flag up regions where the value is above the saturation level
248  determined above. */
249 
250  for (i = 0; i < npix ; i++)
251  if (mflag[i] == MF_CLEANPIX && indata[i] > isatbc)
252  mflag[i] = MF_SATURATED;
253 
254  /* Compute the background variation and remove it from the data*/
255 
256  retval = imcore_background(&ap,nbsize,nullval);
257  if (retval != CASU_OK)
258  FATAL_ERR("Error calculating background");
259 
260  /* Compute a saturation level after background correction. */
261 
262  retval = imcore_backstats(&ap,nullval,1,&skymed,&skysig,&isat);
263  if (retval != CASU_OK)
264  FATAL_ERR("Error calculating saturation");
265 
266 
267  /* Compute background statistics */
268 
269  retval = imcore_backstats(&ap,nullval,0,&skymed,&skysig,&junk);
270  if (retval != CASU_OK)
271  FATAL_ERR("Error calculating background stats");
272 
273  /* Get the propertly list for the input file and add some info*/
274 
275  plist = casu_fits_get_ehu(infile);
276  cpl_propertylist_update_float(plist,"ESO DRS SKYLEVEL",skymed);
277  cpl_propertylist_set_comment(plist,"ESO DRS SKYLEVEL",
278  "[adu] Median sky brightness");
279  cpl_propertylist_update_float(plist,"ESO DRS SKYNOISE",skysig);
280  cpl_propertylist_set_comment(plist,"ESO DRS SKYNOISE",
281  "[adu] Pixel noise at sky level");
282 
283  /* Take mean sky level out of data. Uncomment the bit below if
284  we start working out the covariance in dribbled data. See cirdr
285  version. */
286 
287  for (i = 0; i < nx*ny; i++) {
288  indata[i] -= skymed;
289  /* if (indata[i]*confsqrt[i] > 3.0*skysig && */
290  /* mflag[i] != MF_SATURATED && mflag[i] != MF_STUPID_VALUE) */
291  /* mflag[i] = MF_3SIG; */
292  }
293 
294  /* Work out isophotal detection threshold levels */
295 
296  thresh = threshold*skysig;
297 
298  /* Minimum intensity for consideration */
299 
300  xintmin = 1.5*thresh*((float)ipix);
301 
302  /* Minimum size for considering multiple images */
303 
304  mulpix = MAX(8,2*ipix);
305 
306  /* Actual areal profile levels: T, 2T, 4T, 8T,...but written wrt T
307  i.e. threshold as a power of 2 */
308 
309  offset = logf(thresh)*fconst;
310 
311  /* Get a bit of workspace for buffers */
312 
313  smoothed = cpl_malloc(nx*sizeof(*smoothed));
314  smoothedc = cpl_malloc(nx*sizeof(*smoothedc));
315 
316  /* Define a few things more things in ap structure */
317 
318  ap.mulpix = mulpix;
319  ap.areal_offset = offset;
320  ap.thresh = thresh;
321  ap.xintmin = xintmin;
322  ap.sigma = skysig;
323  ap.background = skymed;
324  ap.saturation = (float)isat;
325 
326  /* Set the weights */
327 
328  crweights(filtfwhm);
329  nw2 = NW/2;
330 
331  /* Right, now for the extraction loop. Begin by defining a group of
332  three rows of data and confidence */
333 
334  for (j = nw2; j < ny-nw2; j++) {
335  current = indata + j*nx;
336  currentc = confsqrt + j*nx;
337  convolve(j);
338 
339  /* Do the detection now */
340 
341  imcore_apline(&ap,current,currentc,smoothed,smoothedc,j,NULL);
342 
343  /* Make sure we're not overruning the stacks */
344 
345  if (ap.ibstack > (ap.maxbl - ap.lsiz))
346  imcore_apfu(&ap);
347  if (ap.ipstack > (ap.maxpa*3/4))
348  for (i = 0; i < ap.maxpa*3/8; i++)
349  imcore_apfu(&ap);
350 
351  /* See if there are any images to terminate */
352 
353  if (ap.ipstack > 1)
354  imcore_terminate(&ap,cattype,gain,&nobjects,tab);
355  }
356 
357  /* Post process. First truncate the cpl_table to the correct size and then
358  work out an estimate of the seeing */
359 
360  cpl_table_set_size(tab,nobjects);
361  retval = imcore_do_seeing(&ap,cattype,nobjects,tab);
362  if (retval != CASU_OK)
363  FATAL_ERR("Error working out seeing");
364  imcore_tabclose(&ap,cattype);
365 
366  /* Create a property list with extra parameters. First QC parameters */
367 
368  extra = cpl_propertylist_duplicate(casu_fits_get_ehu(infile));
369  cpl_propertylist_update_float(extra,"ESO QC SATURATION",ap.saturation);
370  cpl_propertylist_set_comment(extra,"ESO QC SATURATION",
371  "[adu] Saturation level");
372  cpl_propertylist_update_float(extra,"ESO QC MEAN_SKY",ap.background);
373  cpl_propertylist_set_comment(extra,"ESO QC MEAN_SKY",
374  "[adu] Median sky brightness");
375  cpl_propertylist_update_float(extra,"ESO QC SKY_NOISE",ap.sigma);
376  cpl_propertylist_set_comment(extra,"ESO QC SKY_NOISE",
377  "[adu] Pixel noise at sky level");
378 
379  /* Now DRS parameters */
380 
381  cpl_propertylist_update_float(extra,"ESO DRS THRESHOL",ap.thresh);
382  cpl_propertylist_set_comment(extra,"ESO DRS THRESHOL",
383  "[adu] Isophotal analysis threshold");
384  cpl_propertylist_update_int(extra,"ESO DRS MINPIX",ap.ipnop);
385  cpl_propertylist_set_comment(extra,"ESO DRS MINPIX",
386  "[pixels] Minimum size for images");
387  cpl_propertylist_update_int(extra,"ESO DRS CROWDED",ap.icrowd);
388  cpl_propertylist_set_comment(extra,"ESO DRS CROWDED",
389  "Crowded field analysis flag");
390  cpl_propertylist_update_float(extra,"ESO DRS RCORE",ap.rcore);
391  cpl_propertylist_set_comment(extra,"ESO DRS RCORE",
392  "[pixels] Core radius for default profile fit");
393  cpl_propertylist_update_float(extra,"ESO DRS SEEING",ap.fwhm);
394  cpl_propertylist_set_comment(extra,"ESO DRS SEEING",
395  "[pixels] Average FWHM");
396  cpl_propertylist_update_float(extra,"ESO DRS FILTFWHM",ap.filtfwhm);
397  cpl_propertylist_set_comment(extra,"ESO DRS FILTFWHM",
398  "[pixels] FWHM of smoothing kernel");
399  cpl_propertylist_update_int(extra,"ESO DRS XCOL",imcore_xcol);
400  cpl_propertylist_set_comment(extra,"ESO DRS XCOL","Column for X position");
401  cpl_propertylist_update_int(extra,"ESO DRS YCOL",imcore_ycol);
402  cpl_propertylist_set_comment(extra,"ESO DRS YCOL","Column for Y position");
403  cpl_propertylist_update_int(extra,"ESO DRS NXOUT",nx);
404  cpl_propertylist_set_comment(extra,"ESO DRS NXOUT",
405  "X Dimension of input image");
406  cpl_propertylist_update_int(extra,"ESO DRS NYOUT",ny);
407  cpl_propertylist_set_comment(extra,"ESO DRS NYOUT",
408  "Y Dimension of input image");
409  snprintf(card,64,"IMCORE version: %s",imcore_version);
410  cpl_propertylist_append_string(extra,"HISTORY",card);
411 
412  /* Now wrap all this stuff up and send it back */
413 
414  plist = cpl_propertylist_duplicate(casu_fits_get_phu(infile));
415  status = CASU_OK;
416  (void)casu_tabwcs(extra,imcore_xcol,imcore_ycol,&status);
417  *outcat = casu_tfits_wrap(tab,NULL,plist,extra);
418 
419  /* Tidy and exit */
420 
421  tidy();
422  return(CASU_OK);
423 }
424 
425 /*---------------------------------------------------------------------------*/
442 /*---------------------------------------------------------------------------*/
443 
444 static void crweights(float filtfwhm) {
445  int i,j,nw2,n;
446  double gsigsq,di,dj;
447  float renorm;
448 
449  /* Get the kernel size */
450 
451  nw2 = NW/2;
452 
453  /* Set the normalisation constants */
454 
455  gsigsq = 1.0/(2.0*pow(MAX(1.0,(double)filtfwhm)/2.35,2.0));
456  renorm = 0.0;
457 
458  /* Now work out the weights */
459 
460  n = -1;
461  for (i = -nw2; i <= nw2; i++) {
462  di = (double)i;
463  di *= gsigsq*di;
464  for (j = -nw2; j <= nw2; j++) {
465  dj = (double)j;
466  dj *= gsigsq*dj;
467  n++;
468  weights[n] = (float)exp(-(di + dj));
469  renorm += weights[n];
470  }
471  }
472 
473  /* Now normalise the weights */
474 
475  n = -1;
476  for (i = -nw2; i <= nw2; i++) {
477  for (j = -nw2; j <= nw2; j++) {
478  n++;
479  weights[n] /= renorm;
480  /* weightc[n] = 0.01*weights[n]; */
481  weightc[n] = weights[n];
482  }
483  }
484 }
485 
486 /*---------------------------------------------------------------------------*/
504 /*---------------------------------------------------------------------------*/
505 
506 static void convolve(int ir) {
507  int i,nw2,ix,jx,jy,n;
508  float *idata,*cdata;
509 
510  /* Zero the summations */
511 
512  for (i = 0; i < nx; i++) {
513  smoothed[i] = 0.0;
514  smoothedc[i] = 0.0;
515  }
516 
517  /* Now big is the smoothing kernel? */
518 
519  nw2 = NW/2;
520 
521  /* Now loop for each column */
522 
523  for (ix = nw2; ix < nx-nw2; ix++) {
524  n = -1;
525  for (jy = ir-nw2; jy <= ir+nw2; jy++) {
526  idata = indata + jy*nx;
527  cdata = confsqrt + jy*nx;
528  for (jx = ix-nw2; jx <= ix+nw2; jx++) {
529  n++;
530  smoothed[ix] += weights[n]*idata[jx];
531  smoothedc[ix] += weightc[n]*idata[jx]*cdata[jx];
532  }
533  }
534  }
535 }
536 
537 static void tidy(void) {
538 
539  if (freeconf)
540  freespace(confdata);
541  freespace(confsqrt);
542  freespace(smoothed);
543  freespace(smoothedc);
544  freespace(mflag);
545  imcore_apclose(&ap);
546 }
547 
550 /*
551 
552 $Log: imcore_conf.c,v $
553 Revision 1.4 2015/08/12 11:16:55 jim
554 Modified procedure names to protect namespace
555 
556 Revision 1.3 2015/08/07 13:06:54 jim
557 Fixed copyright to ESO
558 
559 Revision 1.2 2015/08/06 05:34:02 jim
560 Fixes to get rid of compiler moans
561 
562 Revision 1.1.1.1 2015/06/12 10:44:32 jim
563 Initial import
564 
565 Revision 1.5 2015/01/09 11:42:36 jim
566 Fixed routines to remove globals
567 
568 Revision 1.4 2014/12/11 12:23:34 jim
569 new version
570 
571 Revision 1.3 2014/04/09 09:09:51 jim
572 Detabbed
573 
574 Revision 1.2 2014/03/26 15:25:19 jim
575 Modified for floating point confidence maps
576 
577 Revision 1.1.1.1 2013/08/27 12:07:48 jim
578 Imported
579 
580 
581 */
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
cpl_propertylist * casu_fits_get_phu(casu_fits *p)
Definition: casu_fits.c:531
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
casu_tfits * casu_tfits_wrap(cpl_table *tab, casu_tfits *model, cpl_propertylist *phu, cpl_propertylist *ehu)
Definition: casu_tfits.c:739
int casu_tabwcs(cpl_propertylist *p, int xcol, int ycol, int *status)
int imcore_background(ap_t *ap, int nbsize, float nullval)
Model and create background map.
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
int imcore_conf(casu_fits *infile, casu_fits *conf, int ipix, float threshold, int icrowd, float rcore, int nbsize, int cattype, float filtfwhm, float gain, casu_tfits **outcat)
Do source extraction.
Definition: imcore_conf.c:147
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
int imcore_do_seeing(ap_t *ap, int cattype, int nobjects, cpl_table *tab)
Do seeing estimate.
Definition: create_table.c:118
void imcore_apinit(ap_t *ap)
Initialise the ap structure.
Definition: apinit.c:65