VIRCAM Pipeline 2.3.15
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
44static float *indata = NULL;
45static int *confdata = NULL;
46static float *confsqrt = NULL;
47static float *smoothed = NULL;
48static float *smoothedc = NULL;
49static unsigned char *mflag = NULL;
50static ap_t ap;
51static int freeconf = 0;
52static float *incopy = NULL;
53static int *ccopy = NULL;
54
55static float weights[NW*NW];
56static float weightc[NW*NW];
57static long nx;
58static long ny;
59
60static void crweights(float);
61static void convolve(int);
62static void tidy(void);
63
66/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
111extern 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
362static 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
424static 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
455static 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 $
471Revision 1.4 2015/08/12 11:16:55 jim
472Modified procedure names to protect namespace
473
474Revision 1.3 2015/08/07 13:06:54 jim
475Fixed copyright to ESO
476
477Revision 1.2 2015/08/06 05:34:02 jim
478Fixes to get rid of compiler moans
479
480Revision 1.1.1.1 2015/06/12 10:44:32 jim
481Initial import
482
483Revision 1.5 2015/01/09 11:42:36 jim
484Fixed routines to remove globals
485
486Revision 1.4 2014/12/11 12:23:34 jim
487new version
488
489Revision 1.3 2014/04/09 09:09:51 jim
490Detabbed
491
492Revision 1.2 2014/03/26 15:25:19 jim
493Modified for floating point confidence maps
494
495Revision 1.1.1.1 2013/08/27 12:07:48 jim
496Imported
497
498
499*/
cpl_image * casu_fits_get_image(casu_fits *p)
Definition: casu_fits.c:436
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
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