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
48static float *smoothed = NULL;
49static float *smoothedc = NULL;
50static unsigned char *mflag = NULL;
51static float *indata = NULL;
52static int *confdata = NULL;
53static float *confsqrt = NULL;
54static ap_t ap;
55static int freeconf = 0;
56
57static float weights[NW*NW];
58static float weightc[NW*NW];
59static long nx;
60static long ny;
61
62static void crweights(float);
63static void convolve(int);
64static void tidy(void);
65
68/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147extern 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
444static 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
506static 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
537static 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 $
553Revision 1.4 2015/08/12 11:16:55 jim
554Modified procedure names to protect namespace
555
556Revision 1.3 2015/08/07 13:06:54 jim
557Fixed copyright to ESO
558
559Revision 1.2 2015/08/06 05:34:02 jim
560Fixes to get rid of compiler moans
561
562Revision 1.1.1.1 2015/06/12 10:44:32 jim
563Initial import
564
565Revision 1.5 2015/01/09 11:42:36 jim
566Fixed routines to remove globals
567
568Revision 1.4 2014/12/11 12:23:34 jim
569new version
570
571Revision 1.3 2014/04/09 09:09:51 jim
572Detabbed
573
574Revision 1.2 2014/03/26 15:25:19 jim
575Modified for floating point confidence maps
576
577Revision 1.1.1.1 2013/08/27 12:07:48 jim
578Imported
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
cpl_propertylist * casu_fits_get_ehu(casu_fits *p)
Definition: casu_fits.c:576
int casu_fits_get_nexten(casu_fits *p)
Definition: casu_fits.c:497
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