38 #include "naco_recipe.h"
39 #include "irplib_flat.h"
45 #define RECIPE_STRING "naco_img_twflat"
51 static cpl_imagelist * naco_img_twflat_reduce(
const irplib_framelist *,
52 const irplib_framelist *);
54 static cpl_error_code naco_img_twflat_qc(cpl_propertylist *,
55 const irplib_framelist *);
57 static cpl_error_code naco_img_twflat_save(cpl_frameset *,
58 const cpl_parameterlist *,
59 const cpl_propertylist *,
60 const cpl_imagelist *,
61 const cpl_image *,
int,
62 const irplib_framelist *);
64 static char * naco_img_twflat_make_tag(
const cpl_frame*,
65 const cpl_propertylist *,
int);
67 static char * naco_img_twflat_make_dark_tag(
const cpl_frame*,
68 const cpl_propertylist *,
int);
70 NACO_RECIPE_DEFINE(naco_img_twflat,
77 "Twilight flat recipe",
78 RECIPE_STRING
" -- NACO imaging flat-field creation from "
80 "The files listed in the Set Of Frames (sof-file) must be tagged:\n"
81 "raw-file.fits " NACO_IMG_TWFLAT_RAW
" or\n"
82 "raw-or-calib-file.fits " NACO_IMG_DARK_RAW
"\n"
83 "The flat frames are divided into groups, each group having identical "
84 "instrument settings. Each group of flats is reduced independently of "
85 "each other. For each group of flats, the set of frames shall contain "
86 "either zero, one or n dark frames with the same instrument settings, "
87 "where n is the number of flats in the group.");
104 } naco_img_twflat_config;
124 static int naco_img_twflat(cpl_frameset * framelist,
125 const cpl_parameterlist * parlist)
127 cpl_errorstate cleanstate = cpl_errorstate_get();
128 irplib_framelist * allframes = NULL;
129 irplib_framelist * flatframes = NULL;
130 irplib_framelist * darkframes = NULL;
131 irplib_framelist * f_one = NULL;
132 irplib_framelist * d_one = NULL;
133 cpl_imagelist * twflat = NULL;
134 cpl_image * bpm_im = NULL;
135 cpl_mask * bpm = NULL;
136 cpl_propertylist * qclist = cpl_propertylist_new();
137 const char ** taglist = NULL;
148 skip_if (sscanf(sval,
"%d %d %d %d",
149 &naco_img_twflat_config.rej_left,
150 &naco_img_twflat_config.rej_right,
151 &naco_img_twflat_config.rej_bottom,
152 &naco_img_twflat_config.rej_top) != 4);
156 NACO_PARAM_BPMTHRES);
158 skip_if (sscanf(sval,
"%lg %lg",
159 &naco_img_twflat_config.low_thresh,
160 &naco_img_twflat_config.high_thresh) !=2 );
162 naco_img_twflat_config.prop_flag
166 naco_img_twflat_config.bpm_flag
170 naco_img_twflat_config.errmap_flag
174 naco_img_twflat_config.intercept_flag
181 skip_if(allframes == NULL);
184 skip_if(flatframes == NULL);
187 IRPLIB_PFITS_REGEXP_RECAL
"|"
188 NACO_PFITS_REGEXP_TWFLAT
194 if (darkframes == NULL) {
195 naco_error_reset(
"The set of frames has no darks:");
201 NACO_PFITS_REGEXP_TWFLAT_DARK
205 naco_img_twflat_make_dark_tag,
212 skip_if(taglist == NULL);
214 cpl_msg_info(cpl_func,
"Identified %d setting(s) in %d flat frame(s)",
218 for (i=0 ; i < nsets ; i++) {
229 cpl_msg_info(cpl_func,
"Reducing flat frame set %d of %d (size=%d) "
230 "with setting: %s", i+1, nsets, nflats, taglist[i]);
232 if (darkframes != NULL) {
233 const char * post_filter = strchr(taglist[i],
':');
235 bug_if(post_filter == NULL);
240 naco_error_reset(
"None of the darks match this setting:");
248 twflat = naco_img_twflat_reduce(f_one, d_one);
250 if (twflat == NULL) {
252 irplib_error_recover(cleanstate,
"Could not reduce set %d:", i+1);
254 if (naco_img_twflat_config.bpm_flag) {
256 if ((bpm = cpl_mask_threshold_image_create(
257 cpl_imagelist_get(twflat, 0),
258 naco_img_twflat_config.low_thresh,
259 naco_img_twflat_config.high_thresh)) == NULL) {
260 cpl_msg_warning(cpl_func,
"Could not create the bad pixel "
261 "map: '%s' at %s", cpl_error_get_message(),
262 cpl_error_get_where());
265 skip_if(cpl_mask_not(bpm));
266 bpm_im = cpl_image_new_from_mask(bpm);
267 cpl_mask_delete(bpm);
272 cpl_msg_info(cpl_func,
"Saving the products");
276 cpl_frame * frame = NULL;
278 == 1 ? CPL_TRUE : CPL_FALSE;
285 bug_if(cpl_frame_set_group(frame,
286 CPL_FRAME_GROUP_CALIB));
292 cpl_frame_delete(frame);
296 skip_if(naco_img_twflat_qc(qclist, f_one));
298 skip_if(naco_img_twflat_save(framelist, parlist, qclist,
299 twflat, bpm_im, i+1, f_one));
301 cpl_propertylist_empty(qclist);
302 cpl_image_delete(bpm_im);
303 cpl_imagelist_delete(twflat);
314 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
315 "None of the %d sets could be reduced", nsets);
324 cpl_mask_delete(bpm);
325 cpl_image_delete(bpm_im);
326 cpl_imagelist_delete(twflat);
328 cpl_propertylist_delete(qclist);
330 return cpl_error_get_code();
346 static cpl_imagelist * naco_img_twflat_reduce(
const irplib_framelist * f_one,
347 const irplib_framelist * d_one)
349 const cpl_propertylist * plist
354 cpl_imagelist * i_one = NULL;
355 cpl_image * dark = NULL;
356 cpl_imagelist * results = NULL;
357 cpl_stats * stats_img = NULL;
359 double min_count = DBL_MAX;
360 double max_count = DBL_MAX;
364 const int ndarks = d_one == NULL ? 0
367 cpl_boolean ok_nonpositive;
372 cpl_msg_info(cpl_func,
"Filter: [%s]", filter);
373 cpl_msg_info(cpl_func,
"Read-out mode: [%s]", rom_name);
374 cpl_msg_info(cpl_func,
"DIT: [%g]", dit);
376 cpl_msg_info(cpl_func,
"Reducing %d flats with subtraction of %d dark(s)",
379 irplib_ensure(ndarks == 0 || ndarks == 1 || ndarks == nflats,
380 CPL_ERROR_INCOMPATIBLE_INPUT,
381 "Cannot reduce %d flats with %d darks", nflats, ndarks);
383 ok_nonpositive = strncmp(tpl_id,
"NACO_img_cal_SkyFlats",
384 IRPLIB_FITS_STRLEN) == 0 &&
385 strncmp(rom_name,
"Uncorr", IRPLIB_FITS_STRLEN) == 0
386 ? CPL_TRUE : CPL_FALSE;
389 cpl_msg_info(cpl_func,
"---> Loading input set");
392 "Could not load the images of the flat frames");
395 cpl_msg_info(cpl_func,
"---> Computing stats");
396 cpl_msg_info(cpl_func,
"image min max med rms");
397 cpl_msg_info(cpl_func,
"---------------------------------------------");
398 for (i = 0 ; i < nflats ; i++) {
401 flat = cpl_imagelist_get(i_one, i);
403 bug_if( flat == NULL);
405 stats_img = cpl_stats_new_from_image(flat, CPL_STATS_MIN
410 bug_if (stats_img == NULL);
412 curr_count = cpl_stats_get_median(stats_img);
414 cpl_msg_info(cpl_func,
"%02d %10.2f %10.2f %10.2f %10.2f", i+1,
415 cpl_stats_get_min(stats_img), cpl_stats_get_max(stats_img),
416 curr_count, cpl_stats_get_stdev(stats_img));
418 cpl_stats_delete(stats_img);
421 if (i==0 || curr_count < min_count) min_count = curr_count;
422 if (i==0 || curr_count > max_count) max_count = curr_count;
426 irplib_ensure (ok_nonpositive || curr_count > 0.0,
427 CPL_ERROR_ILLEGAL_INPUT,
428 "Flat %d has negative flux=%g using template=%s", i+1,
431 if (ndarks == 0)
continue;
435 if (i == 0 || ndarks > 1) {
437 const char * name = cpl_frame_get_filename(frame);
439 cpl_image_delete(dark);
440 irplib_check(dark = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
441 "Could not load FITS-image from %s", name);
444 skip_if (cpl_image_subtract(flat, dark));
448 cpl_msg_info(cpl_func,
"---------------------------------------------");
452 cpl_image_delete(dark);
456 cpl_msg_info(cpl_func,
"Switching to proportional fit");
457 naco_img_twflat_config.prop_flag = 1;
459 }
else if (!naco_img_twflat_config.prop_flag) {
461 const double min_grad = 4.0;
463 if (fabs(max_count) < min_grad * fabs(min_count)) {
464 const double grad = fabs(max_count/min_count);
466 cpl_msg_warning(cpl_func,
"Low flux gradient: %g < %g", grad,
468 cpl_msg_warning(cpl_func,
"A proportional fit may give better "
469 "results (Requires either a single master dark "
470 "frame or one dark per flat frame)");
475 if (naco_img_twflat_config.prop_flag) {
476 cpl_msg_info(cpl_func,
"---> Fitting slopes proportionally");
478 irplib_ensure(results != NULL, CPL_ERROR_ILLEGAL_INPUT,
479 "Could not create twilight flat-field with "
482 cpl_msg_info(cpl_func,
"---> Fitting slopes non-proportionally");
484 irplib_ensure(results != NULL, CPL_ERROR_ILLEGAL_INPUT,
485 "Could not create twilight flat-field with "
486 "non-proportional fit");
488 cpl_imagelist_delete(i_one);
492 flat = cpl_imagelist_get(results, 0);
493 bug_if( flat == NULL);
495 cpl_image_get_mean_window(flat,
496 naco_img_twflat_config.rej_left+1,
497 naco_img_twflat_config.rej_bottom+1,
498 cpl_image_get_size_x(flat)
499 -naco_img_twflat_config.rej_right,
500 cpl_image_get_size_y(flat)
501 -naco_img_twflat_config.rej_top);
502 cpl_image_divide_scalar(flat, norm),
503 "Could not normalize gain with norm=%g", norm);
507 cpl_imagelist_delete(i_one);
508 cpl_stats_delete(stats_img);
509 cpl_image_delete(dark);
511 if (cpl_error_get_code()) {
512 cpl_imagelist_delete(results);
528 static cpl_error_code naco_img_twflat_qc(cpl_propertylist * qclist,
529 const irplib_framelist * rawframes)
532 const cpl_propertylist * reflist
538 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
539 IRPLIB_PFITS_REGEXP_RECAL
546 return cpl_error_get_code();
562 static cpl_error_code naco_img_twflat_save(cpl_frameset * set_tot,
563 const cpl_parameterlist * parlist,
564 const cpl_propertylist * qclist,
565 const cpl_imagelist * flat,
566 const cpl_image * bpm,
568 const irplib_framelist * f_one)
572 char * filename = NULL;
573 const int nflats = cpl_imagelist_get_size(flat);
577 bug_if (nflats != 2 && nflats != 3);
580 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_FITS, set_nb);
582 cpl_imagelist_get_const(flat, 0),
583 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
584 NACO_IMG_TWFLAT_RES, qclist, NULL, naco_pipe_id,
590 filename = cpl_sprintf(RECIPE_STRING
"_set%02d_bpm" CPL_DFS_FITS,
593 CPL_BPP_8_UNSIGNED, RECIPE_STRING,
594 NACO_IMG_TWFLAT_BPM, qclist, NULL,
595 naco_pipe_id, filename));
598 if (naco_img_twflat_config.intercept_flag && nflats == 3) {
601 filename = cpl_sprintf(RECIPE_STRING
"_set%02d_inter"
602 CPL_DFS_FITS, set_nb);
604 cpl_imagelist_get_const(flat, 1),
605 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
606 NACO_IMG_TWFLAT_INTER, qclist, NULL,
607 naco_pipe_id, filename));
610 if (naco_img_twflat_config.errmap_flag) {
613 filename = cpl_sprintf(RECIPE_STRING
"_set%02d_errmap"
614 CPL_DFS_FITS, set_nb);
616 cpl_imagelist_get_const(flat, nflats - 1),
617 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
618 NACO_IMG_TWFLAT_ERRMAP, qclist, NULL,
619 naco_pipe_id, filename));
625 cpl_frameset_delete(rawframes);
627 return cpl_error_get_code();
644 static char * naco_img_twflat_make_tag(
const cpl_frame*
self,
645 const cpl_propertylist* plist,
int dummy)
655 bug_if (cpl_error_get_code());
657 bug_if(
self == NULL);
658 bug_if(plist == NULL);
664 skip_if(cpl_error_get_code());
668 skip_if(cpl_error_get_code());
672 skip_if(cpl_error_get_code());
676 skip_if(cpl_error_get_code());
678 tag = cpl_sprintf(
"%s:%s:%s:%.5f", filter,
684 if (cpl_error_get_code()) {
707 static char * naco_img_twflat_make_dark_tag(
const cpl_frame *
self,
708 const cpl_propertylist * plist,
717 bug_if (cpl_error_get_code());
719 bug_if(
self == NULL);
720 bug_if(plist == NULL);
726 skip_if(cpl_error_get_code());
730 skip_if(cpl_error_get_code());
734 skip_if(cpl_error_get_code());
736 tag = cpl_sprintf(
"%s:%s:%.5f", name, mode, dit);
741 if (cpl_error_get_code()) {
cpl_imagelist * irplib_imagelist_load_framelist(const irplib_framelist *self, cpl_type pixeltype, int planenum, int extnum)
Load an imagelist from a framelist.
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
const char * naco_pfits_get_rom_name(const cpl_propertylist *self)
find out the read out mode name
cpl_imagelist * irplib_flat_fit_set(cpl_imagelist *raw, int mode)
Compute a flat-field out of a set of exposures.
double naco_pfits_get_dit(const cpl_propertylist *self)
find out the DIT
cpl_error_code irplib_framelist_set_tag_all(irplib_framelist *self, const char *tag)
Set the tag of all frames in the list.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
cpl_error_code irplib_framelist_set(irplib_framelist *self, cpl_frame *frame, int pos)
Add a frame to a framelist.
cpl_error_code irplib_pfits_set_airmass(cpl_propertylist *self, const irplib_framelist *rawframes)
Update/Set the AIRMASS property.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
void irplib_framelist_empty(irplib_framelist *self)
Erase all frames from a framelist.
cpl_error_code irplib_dfs_save_image(cpl_frameset *allframes, const cpl_parameterlist *parlist, const cpl_frameset *usedframes, const cpl_image *image, cpl_type_bpp bpp, const char *recipe, const char *procat, const cpl_propertylist *applist, const char *remregexp, const char *pipe_id, const char *filename)
Save an image as a DFS-compliant pipeline product.
cpl_error_code irplib_framelist_load_propertylist_all(irplib_framelist *self, int ind, const char *regexp, cpl_boolean invert)
Load the propertylists of all frames in the framelist.
cpl_frame * irplib_framelist_unset(irplib_framelist *self, int pos, cpl_propertylist **plist)
Erase a frame from a framelist and return it to the caller.
cpl_boolean naco_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO boolean parameter.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a framelist.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
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.
void irplib_framelist_delete(irplib_framelist *self)
Deallocate an irplib_framelist with its frames and properties.
const char * naco_pfits_get_templateid(const cpl_propertylist *self)
find out the template ID
const char * naco_pfits_get_mode(const cpl_propertylist *self)
find out the mode name
irplib_framelist * irplib_framelist_cast(const cpl_frameset *frameset)
Create an irplib_framelist from a cpl_framelist.
const char * naco_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO string parameter.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.
const char * naco_pfits_get_filter(const cpl_propertylist *self)
find out the filter