36 #include "naco_recipe.h"
44 #define RECIPE_STRING "naco_spc_lampflat"
46 #ifndef NACO_SPC_MEDIAN_XSIZE
47 #define NACO_SPC_MEDIAN_XSIZE 200
50 #ifndef NACO_SPC_MEDIAN_YSIZE
51 #define NACO_SPC_MEDIAN_YSIZE NACO_SPC_MEDIAN_XSIZE
58 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist *,
59 const irplib_framelist *,
60 const cpl_parameterlist *);
62 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist *,
64 const irplib_framelist *);
66 static cpl_error_code naco_spc_lampflat_save(cpl_frameset *,
67 const cpl_parameterlist *,
68 const cpl_propertylist *,
69 const cpl_propertylist *,
71 int,
const irplib_framelist *);
73 NACO_RECIPE_DEFINE(naco_spc_lampflat,
74 NACO_PARAM_REJBORD | NACO_PARAM_HOT_LIM | NACO_PARAM_COLD_LIM,
75 "Spectrocopic flat recipe using a lamp",
76 RECIPE_STRING
" -- NACO spectrocopy flat-field creation from "
78 "The files listed in the Set Of Frames (sof-file) "
80 "NACO-raw-file.fits " NACO_SPC_LAMPFLAT_RAW
"\n"
82 NACO_SPC_MAN_MODESPLIT
"\n\n"
83 "Furthermore, the input set of frames must have values of "
85 NACO_PFITS_INT_LAMP2
" that of zero for off-frames and "
86 "non-zero for on-frames.\n");
107 static int naco_spc_lampflat(cpl_frameset * framelist,
108 const cpl_parameterlist * parlist)
110 cpl_errorstate cleanstate = cpl_errorstate_get();
111 irplib_framelist * allframes = NULL;
112 irplib_framelist * rawframes = NULL;
113 irplib_framelist * f_one = NULL;
114 const char ** taglist = NULL;
115 cpl_image * lamp_flat = NULL;
116 cpl_propertylist * qclist = cpl_propertylist_new();
117 cpl_propertylist * paflist = cpl_propertylist_new();
127 skip_if(allframes == NULL);
130 skip_if(rawframes == NULL);
134 NACO_PFITS_REGEXP_SPCFLAT
"|"
135 NACO_PFITS_REGEXP_SPCFLAT_PAF
139 skip_if(taglist == NULL);
141 cpl_msg_info(cpl_func,
"Identified %d setting(s) in %d frames",
145 for (i=0 ; i < nsets ; i++) {
148 cpl_msg_info(cpl_func,
"Reducing data set %d of %d", i+1, nsets);
156 cpl_msg_info(cpl_func,
"Reducing frame set %d of %d (size=%d) with "
157 "setting: %s", i+1, nsets,
160 skip_if (f_one == NULL);
162 lamp_flat = naco_spc_lampflat_reduce(qclist, f_one, parlist);
165 if (lamp_flat == NULL) {
167 irplib_error_recover(cleanstate,
"Could not compute the flat for "
170 skip_if(naco_spc_lampflat_qc(qclist, paflist, f_one));
172 bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
173 NACO_CALIB_SPCFLAT));
174 skip_if(naco_spc_lampflat_save(framelist, parlist, qclist, paflist,
175 lamp_flat, i+1, f_one));
176 cpl_image_delete(lamp_flat);
180 cpl_propertylist_empty(qclist);
181 cpl_propertylist_empty(paflist);
186 irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
187 "None of the %d sets could be reduced", nsets);
192 cpl_image_delete(lamp_flat);
196 cpl_propertylist_delete(qclist);
197 cpl_propertylist_delete(paflist);
199 return cpl_error_get_code();
211 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist * qclist,
212 const irplib_framelist * framelist,
213 const cpl_parameterlist * parlist)
215 cpl_image *
self = NULL;
216 cpl_imagelist * difflist = cpl_imagelist_new();
217 cpl_mask * bpm = NULL;
218 cpl_vector * medians = NULL;
219 const double hot_thresh
222 const double cold_thresh = 1.0 /
224 NACO_PARAM_COLD_LIM);
225 const char * rej_bord
228 cpl_propertylist * lampkeys = cpl_propertylist_new();
229 int rej_left, rej_right, rej_bottom, rej_top;
235 bug_if (qclist == NULL);
236 bug_if (framelist == NULL);
237 bug_if (parlist == NULL);
239 skip_if(cold_thresh <= 0.0);
240 skip_if(cold_thresh >= 1.0);
241 skip_if(hot_thresh <= 1.0);
243 skip_if (sscanf(rej_bord,
"%d %d %d %d",
244 &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
247 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_INT_LAMP2, 1));
248 bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_BOOL_LAMP1, 0));
252 ndiff = cpl_imagelist_get_size(difflist);
254 medians = cpl_vector_new(ndiff);
258 for (idiff = 0, nflat = 0; idiff < ndiff; idiff++) {
259 cpl_image * diff = cpl_imagelist_get(difflist, nflat);
260 const int nx = cpl_image_get_size_x(diff);
261 const int ny = cpl_image_get_size_y(diff);
265 = cpl_image_get_mean_window(diff,
266 rej_left, nx - rej_right,
267 rej_bottom, ny - rej_top);
272 cpl_msg_warning(cpl_func,
"Ignoring difference image %d with an "
273 "invalid mean: %g", 1+idiff, mean);
274 cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
279 median = cpl_image_get_median_window(diff,
280 (nx-NACO_SPC_MEDIAN_XSIZE)/2,
281 (ny-NACO_SPC_MEDIAN_YSIZE)/2,
282 (nx+NACO_SPC_MEDIAN_XSIZE)/2,
283 (ny+NACO_SPC_MEDIAN_YSIZE)/2);
287 bug_if(cpl_image_divide_scalar(diff, mean));
290 bpm = cpl_mask_threshold_image_create(diff, cold_thresh, hot_thresh);
293 if (cpl_mask_is_empty(bpm)) {
294 cpl_msg_warning(cpl_func,
"Ignoring difference image %d with no "
295 "good pixels", 1+idiff);
296 cpl_mask_delete(bpm);
298 cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
302 bug_if(cpl_mask_not(bpm));
304 cpl_msg_info(cpl_func,
"Difference image %d has %d bad pixels", 1+idiff,
305 (
int)cpl_mask_count(bpm));
308 bug_if(cpl_mask_or(cpl_image_get_bpm(diff), bpm));
310 cpl_mask_delete(bpm);
313 bug_if (cpl_vector_set(medians, nflat, median));
318 bug_if(nflat != cpl_imagelist_get_size(difflist));
320 error_if(nflat == 0, CPL_ERROR_DATA_NOT_FOUND,
321 "The %d difference images are all invalid", ndiff);
323 self = cpl_imagelist_collapse_create(difflist);
326 nbad = cpl_image_count_rejected(
self);
330 cpl_msg_info(cpl_func,
"Setting %d bad pixels in master flat to 1.0",
332 bug_if(cpl_image_fill_rejected(
self, 1.0));
335 bug_if(cpl_vector_set_size(medians, nflat));
337 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC SPECFLAT NCOUNTS",
338 cpl_vector_get_mean(medians)));
339 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC SPECFLAT STDEV",
340 cpl_vector_get_stdev(medians)));
344 if (cpl_error_get_code()) {
345 cpl_image_delete(
self);
349 cpl_propertylist_delete(lampkeys);
350 cpl_imagelist_delete(difflist);
351 cpl_mask_delete(bpm);
352 cpl_vector_delete(medians);
367 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist * qclist,
368 cpl_propertylist * paflist,
369 const irplib_framelist * rawframes)
372 const cpl_propertylist * reflist
374 const char pafcopy[] =
"^(" NACO_PFITS_REGEXP_SPCFLAT_PAF
")$";
381 skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
383 skip_if (cpl_propertylist_append(paflist, qclist));
385 bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
"^("
386 IRPLIB_PFITS_REGEXP_RECAL_LAMP
391 return cpl_error_get_code();
407 static cpl_error_code naco_spc_lampflat_save(cpl_frameset * set_tot,
408 const cpl_parameterlist * parlist,
409 const cpl_propertylist * qclist,
410 const cpl_propertylist * paflist,
411 const cpl_image * flat,
413 const irplib_framelist * rawframes)
416 char * filename = NULL;
424 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_FITS, set_nb);
426 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
427 NACO_CALIB_SPCFLAT, qclist, NULL,
428 naco_pipe_id, filename));
432 filename = cpl_sprintf(RECIPE_STRING
"_set%02d" CPL_DFS_PAF, set_nb);
433 skip_if (cpl_dfs_save_paf(
"NACO", RECIPE_STRING, paflist, filename));
435 bug_if(paflist == NULL);
441 cpl_frameset_delete(proframes);
443 return cpl_error_get_code();
cpl_frameset * irplib_frameset_cast(const irplib_framelist *self)
Create a CPL frameset from an irplib_framelist.
cpl_error_code irplib_framelist_set_tag_all(irplib_framelist *self, const char *tag)
Set the tag of all frames in the list.
char * naco_spc_make_tag(const cpl_frame *self, const cpl_propertylist *plist, int dummy)
Create a string suitable for frame comparison in spectroscopy.
int naco_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
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.
double naco_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, naco_parameter bitmask)
Retrieve the value of a NACO parameter of type double.
irplib_framelist * irplib_framelist_extract(const irplib_framelist *self, const char *tag)
Extract the frames with the given tag from a 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.
cpl_error_code naco_imagelist_load_diff(cpl_imagelist *self, const irplib_framelist *onofflist, const cpl_propertylist *onoffkeys)
Fill the list of difference images from on/off frames.
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.