36 #include "naco_recipe.h"
42 #define RECIPE_STRING "naco_img_lampflat"
48 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist *,
49 const irplib_framelist *,
52 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist *,
54 const irplib_framelist *);
56 static cpl_error_code naco_img_lampflat_save(cpl_frameset *,
57 const cpl_parameterlist *,
58 const cpl_propertylist *,
59 const cpl_propertylist *,
61 int,
const irplib_framelist *);
63 static char * naco_img_lampflat_make_tag(
const cpl_frame*,
64 const cpl_propertylist *,
int);
66 NACO_RECIPE_DEFINE(naco_img_lampflat, NACO_PARAM_REJBORD,
67 "Flat recipe using a lamp",
68 RECIPE_STRING
" -- NACO imaging flat-field creation from "
70 "The files listed in the Set Of Frames (sof-file) "
72 "NACO-raw-file.fits " NACO_IMG_LAMPFLAT_RAW
"\n"
74 "Furthermore, the input set of frames must have values of "
76 NACO_PFITS_INT_LAMP2
" that alternate between zero and "
77 "non-zero (with non-zero for the first frame).\n"
78 "It is further required that the light from the lamp is "
79 "in a range without a significant thermal background.");
100 static int naco_img_lampflat(cpl_frameset * framelist,
101 const cpl_parameterlist * parlist)
103 cpl_errorstate cleanstate = cpl_errorstate_get();
104 irplib_framelist * allframes = NULL;
105 irplib_framelist * rawframes = NULL;
106 irplib_framelist * f_one = NULL;
107 const char ** taglist = NULL;
108 const char * rej_bord;
109 cpl_image * lamp_flat = NULL;
110 cpl_propertylist * qclist = cpl_propertylist_new();
111 cpl_propertylist * paflist = cpl_propertylist_new();
114 int rej_left, rej_right, rej_bottom, rej_top;
121 skip_if_ne(sscanf(rej_bord,
"%d %d %d %d",
122 &rej_left, &rej_right, &rej_bottom, &rej_top), 4,
123 "number(s) in string parameter (%s): \"%s\"",
124 CPL_XSTRINGIFY(NACO_PARAM_REJBORD), rej_bord);
129 allframes = irplib_framelist_cast(framelist);
130 skip_if(allframes == NULL);
132 rawframes = irplib_framelist_extract(allframes, NACO_IMG_LAMPFLAT_RAW);
133 skip_if(rawframes == NULL);
134 irplib_framelist_empty(allframes);
136 skip_if(irplib_framelist_load_propertylist_all(rawframes, 0,
"^("
137 IRPLIB_PFITS_REGEXP_RECAL
"|"
138 NACO_PFITS_REGEXP_LAMPFLAT
"|"
139 NACO_PFITS_REGEXP_LAMPFLAT_PAF
144 skip_if(taglist == NULL);
146 cpl_msg_info(cpl_func,
"Identified %d setting(s) in %d frames",
147 nsets, irplib_framelist_get_size(rawframes));
150 for (i=0 ; i < nsets ; i++) {
153 cpl_msg_info(cpl_func,
"Reducing data set %d of %d", i+1, nsets);
156 f_one = irplib_framelist_extract(rawframes, taglist[i]);
159 skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_LAMPFLAT_RAW));
161 cpl_msg_info(cpl_func,
"Reducing frame set %d of %d (size=%d) with "
162 "setting: %s", i+1, nsets,
163 irplib_framelist_get_size(f_one), taglist[i]);
165 skip_if (f_one == NULL);
167 lamp_flat = naco_img_lampflat_reduce(qclist, f_one, rej_left, rej_right,
168 rej_bottom, rej_top);
171 if (lamp_flat == NULL) {
173 irplib_error_recover(cleanstate,
"Could not compute the flat for "
176 skip_if(naco_img_lampflat_qc(qclist, paflist, f_one));
178 bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
179 NACO_IMG_LAMPFLAT_RES));
180 skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
181 lamp_flat, i+1, f_one));
182 cpl_image_delete(lamp_flat);
186 cpl_propertylist_empty(qclist);
187 cpl_propertylist_empty(paflist);
188 irplib_framelist_delete(f_one);
192 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
193 "None of the %d sets could be reduced", nsets);
198 cpl_image_delete(lamp_flat);
199 irplib_framelist_delete(f_one);
200 irplib_framelist_delete(allframes);
201 irplib_framelist_delete(rawframes);
202 cpl_propertylist_delete(qclist);
203 cpl_propertylist_delete(paflist);
205 return cpl_error_get_code();
220 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
221 const irplib_framelist * framelist,
222 int rej_left,
int rej_right,
223 int rej_bottom,
int rej_top)
226 cpl_image * image = NULL;
227 cpl_image * aver = NULL;
228 cpl_image * diff = NULL;
229 cpl_image * prev = NULL;
230 cpl_image * image0= NULL;
231 double gain, fp_noise;
232 double lamp_flux = DBL_MAX;
234 double mean = DBL_MAX;
239 bug_if (framelist == NULL);
241 nfiles = irplib_framelist_get_size(framelist);
244 skip_if_lt(nfiles, 4,
"frames");
247 irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
248 "The number of frames must be even, not %d", nfiles);
250 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
251 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
253 skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
254 CPL_TYPE_INT, CPL_FALSE, 0.0));
258 for (i=0 ; i < nfiles ; i++) {
259 const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
260 const char * name = cpl_frame_get_filename(frame);
261 const cpl_propertylist * plist
262 = irplib_framelist_get_propertylist_const(framelist, i);
265 skip_if(name == NULL);
266 skip_if(plist == NULL);
273 cpl_msg_info(cpl_func,
"Filter: [%s]", sval);
276 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER OBS",
280 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER NDENS",
284 skip_if(cpl_propertylist_append_string(qclist,
"ESO QC FILTER POL",
288 cpl_msg_info(cpl_func,
"File %02d: %s", i+1, name);
293 irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
294 "Frame number %d must have %s set to zero, not %d",
295 i+1, NACO_PFITS_INT_LAMP2, ival);
297 irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
298 "Frame number %d must have a non-zero %s",
299 i+1, NACO_PFITS_INT_LAMP2);
302 irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
303 "Could not load FITS-image from %s", name);
306 irplib_check(mean = cpl_image_get_mean(image),
307 "Could not compute mean");
308 image0 = image; image = NULL;
310 const int ifirst = i == 3 ? 1 : 0;
315 irplib_check(diff = cpl_image_subtract_create(image0, image),
316 "Could not subtract the images %d and %d",
319 irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
321 "Could not compute noise on difference between"
322 " images %d and %d", ifirst+1, i+1);
324 std_diff[i-1] = noise * noise;
329 const double median = cpl_image_get_median(diff);
332 skip_if (cpl_error_get_code());
333 skip_if (ditval <= 0.0);
335 lamp_flux = median / ditval;
341 cpl_image_delete(diff);
344 cpl_image_delete(image0);
346 image0 = i == 2 ? prev : NULL;
351 if (i > 1 && i % 2 != 0) {
353 irplib_check(cpl_image_subtract(prev, image),
354 "Could not correct for the dark");
357 irplib_check(cpl_image_add(aver, prev),
358 "Could not sum up the dark corrected images");
360 cpl_image_delete(image);
361 cpl_image_delete(prev);
370 cpl_msg_info(cpl_func,
"Computing the QC parameters");
373 square = std_diff[1] - std_diff[2];
374 if (square != 0.0) square = 2.0*mean/square;
375 gain = square > 0.0 ? sqrt(square) : 0.0;
378 square = std_diff[0] - std_diff[1] - std_diff[2];
379 fp_noise = square > 0.0 ? sqrt(square) : 0.0;
382 cpl_msg_info(cpl_func,
"Gain: %g", gain);
383 cpl_msg_info(cpl_func,
"Noise: %g", fp_noise);
384 cpl_msg_info(cpl_func,
"Lamp flux: %g", lamp_flux);
387 cpl_msg_info(cpl_func,
"Average the dark corrected frames");
388 irplib_check(cpl_image_divide_scalar(aver, (
double)(nfiles/2)),
389 "Could not average the %d dark corrected frames", nfiles/2);
393 = cpl_image_get_mean_window(aver, rej_left,
394 cpl_image_get_size_x(aver)
397 cpl_image_get_size_y(aver)
399 cpl_image_divide_scalar(aver, mean),
400 "Could not average the %d dark corrected frames", nfiles/2);
403 skip_if(cpl_propertylist_append_double(qclist,
"ESO QC GAIN", gain));
404 skip_if(cpl_propertylist_append_double(qclist,
"ESO QC FPNOISE", fp_noise));
405 skip_if(cpl_propertylist_append_double(qclist,
"ESO QC LAMPFLUX",
410 if (cpl_error_get_code()) {
411 cpl_image_delete(aver);
415 cpl_image_delete(image);
416 cpl_image_delete(diff);
417 cpl_image_delete(prev);
418 cpl_image_delete(image0);
433 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist * qclist,
434 cpl_propertylist * paflist,
435 const irplib_framelist * rawframes)
438 const cpl_propertylist * reflist
439 = irplib_framelist_get_propertylist_const(rawframes, 0);
440 const char pafcopy[] =
"^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF
")$";
447 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
449 skip_if (cpl_propertylist_append(paflist, qclist));
451 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
452 IRPLIB_PFITS_REGEXP_RECAL
457 return cpl_error_get_code();
473 static cpl_error_code naco_img_lampflat_save(cpl_frameset * set_tot,
474 const cpl_parameterlist * parlist,
475 const cpl_propertylist * qclist,
476 const cpl_propertylist * paflist,
477 const cpl_image * flat,
479 const irplib_framelist * rawframes)
481 cpl_frameset * proframes = irplib_frameset_cast(rawframes);
482 char * filename = NULL;
490 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_FITS, set_nb);
491 skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
492 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
493 NACO_IMG_LAMPFLAT_RES, qclist, NULL,
494 naco_pipe_id, filename));
498 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_PAF, set_nb);
499 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist, filename));
501 bug_if(paflist == NULL);
507 cpl_frameset_delete(proframes);
509 return cpl_error_get_code();
525 static char * naco_img_lampflat_make_tag(
const cpl_frame*
self,
526 const cpl_propertylist * plist,
539 skip_if (cpl_error_get_code());
541 skip_if(
self == NULL);
542 skip_if(plist == NULL);
548 skip_if(cpl_error_get_code());
552 skip_if(cpl_error_get_code());
556 skip_if(cpl_error_get_code());
560 skip_if(cpl_error_get_code());
564 skip_if(cpl_error_get_code());
568 skip_if(cpl_error_get_code());
571 tag = cpl_sprintf(
"%s:%s:%s:%s:%s:%.5f", filter,
572 opti7, opti3, rom, mode, dit);
577 if (cpl_error_get_code()) {
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
int naco_pfits_get_lamp2(const cpl_propertylist *self)
find out the INS.LAMP2.SET keyword
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
const char * naco_pfits_get_opti7_name(const cpl_propertylist *self)
find out the OPTI7.NAME key
const char * naco_pfits_get_opti3_name(const cpl_propertylist *self)
find out the OPTI3.NAME key
const char * naco_pfits_get_rom_name(const cpl_propertylist *self)
find out the read out mode name
const char * naco_pfits_get_opti4_name(const cpl_propertylist *self)
find out the OPTI4.NAME key
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter
const char ** naco_framelist_set_tag(irplib_framelist *self, char *(*pftag)(const cpl_frame *, const cpl_propertylist *, int), int *pntags)
Retag a framelist according to the given tagging function.