31#include "cr2res_utils.h"
32#include "cr2res_calib.h"
33#include "cr2res_pfits.h"
34#include "cr2res_dfs.h"
36#include "cr2res_flat.h"
37#include "cr2res_bpm.h"
38#include "cr2res_trace.h"
39#include "cr2res_extract.h"
46#define RECIPE_STRING "cr2res_cal_flat"
52int cpl_plugin_get_info(cpl_pluginlist * list);
58static int cr2res_cal_flat_compare(
59 const cpl_frame * frame1,
60 const cpl_frame * frame2) ;
61static int cr2res_cal_flat_reduce(
62 const cpl_frameset * rawframes,
63 const cpl_frame * tw_frame,
64 const cpl_frame * detlin_frame,
65 const cpl_frame * master_dark_frame,
66 const cpl_frame * bpm_frame,
68 int subtract_nolight_rows,
74 int trace_min_cluster,
77 double trace_threshold,
79 cr2res_extr_method extr_method,
80 int extract_oversample,
81 int extract_swath_width,
83 double extract_smooth_slit,
84 double extract_smooth_spec,
88 hdrl_image ** master_flat,
89 cpl_table ** trace_wave,
90 cpl_table ** slit_func,
91 cpl_table ** extract_1d,
92 hdrl_image ** slit_model,
94 cpl_propertylist ** ext_plist) ;
95static int cr2res_cal_flat_create(cpl_plugin *);
96static int cr2res_cal_flat_exec(cpl_plugin *);
97static int cr2res_cal_flat_destroy(cpl_plugin *);
98static int cr2res_cal_flat(cpl_frameset *,
const cpl_parameterlist *);
104static char cr2res_cal_flat_description[] =
"\
106 Compute the master flat and perform the traces detection. \n\
107 If a TW file is provided, its traces and slit curvatures are used \n\
108 for the extraction needed to create the master flat. \n\
109 If not provided, the measured traces are used, and the slit is \n\
110 considered vertical. \n\
113 raw.fits " CR2RES_FLAT_RAW
" [1 to n] \n\
114 trace.fits " CR2RES_CAL_FLAT_TW_PROCATG
" [0 to 1] \n\
115 or " CR2RES_CAL_FLAT_TW_MERGED_PROCATG
" \n\
116 or " CR2RES_UTIL_TRACE_TW_PROCATG
" \n\
117 or " CR2RES_UTIL_WAVE_TW_PROCATG
" \n\
118 or " CR2RES_CAL_WAVE_TW_PROCATG
" \n\
119 or " CR2RES_UTIL_SLIT_CURV_TW_PROCATG
" \n\
120 detlin.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG
" [0 to 1] \n\
121 master_dark.fits " CR2RES_CAL_DARK_MASTER_PROCATG
" [0 to 1] \n\
122 bpm.fits " CR2RES_CAL_DARK_BPM_PROCATG
" [0 to 1] \n\
123 or " CR2RES_CAL_FLAT_BPM_PROCATG
" \n\
124 or " CR2RES_CAL_DETLIN_BPM_PROCATG
" \n\
125 or " CR2RES_UTIL_BPM_SPLIT_PROCATG
" \n\
126 or " CR2RES_UTIL_NORM_BPM_PROCATG
" \n\
129 cr2res_cal_flat_[setting]_[Decker]_bpm.fits "
130 CR2RES_CAL_FLAT_BPM_PROCATG
"\n\
131 cr2res_cal_flat_[setting]_[Decker]_blaze.fits "
132 CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG
"\n\
133 cr2res_cal_flat_[setting]_[Decker]_slit_model.fits "
134 CR2RES_CAL_FLAT_SLIT_MODEL_PROCATG
"\n\
135 cr2res_cal_flat_[setting]_[Decker]_slit_func.fits "
136 CR2RES_CAL_FLAT_SLIT_FUNC_PROCATG
"\n\
137 cr2res_cal_flat_[setting]_[Decker]_master_flat.fits "
138 CR2RES_CAL_FLAT_MASTER_PROCATG
"\n\
139 cr2res_cal_flat_[setting]_[Decker]_tw.fits "
140 CR2RES_CAL_FLAT_TW_PROCATG
"\n\
141 cr2res_cal_flat_[setting]_tw_merged.fits "
142 CR2RES_CAL_FLAT_TW_MERGED_PROCATG
"\n\
145 group the input frames by different settings \n\
146 loop on groups g: \n\
147 loop on decker positions p: \n\
148 loop on detectors d: \n\
149 cr2res_cal_flat_reduce() computes (master_flat, trace_wave, \n\
150 slit_func,extract_1d,slit_model,bpm)(g,p,d) \n\
151 Save slit_model(g,p) \n\
152 Save extract_1d(g,p) \n\
153 Save master_flat(g,p) \n\
154 Save trace_wave(g,p) \n\
155 Save slit_func(g,p) \n\
157 Merge the trace_wave(g,p,d) into trace_wave(g,d) \n\
158 Save trace_wave(g) \n\
160 cr2res_cal_flat_reduce() \n\
161 Load the images list \n\
162 Apply the detlin / dark / bpm calibrations \n\
163 Average the images to avg \n\
164 Compute the traces with cr2res_trace(--trace_degree, \n\
165 --trace_min_cluster, --trace_smooth, --trace_opening) \n\
167 For the following step, the computed TW is used if there is no \n\
168 input TW provided, the provided one is used otherwise. \n\
169 loop on the traces t: \n\
170 cr2res_extract_slitdec_curved(--extract_oversample, \n\
171 --extract_swath_width, --extract_height, \n\
172 --extract_smooth_slit, --extract_smooth_spec) \n\
173 -> slit_func(t), extract_1d(t), slit_model(t) \n\
174 Compute the master flat with cr2res_master_flat(avg, slit_model, \n\
175 --bpm_low, --bpm_high, --bpm_lines_ratio) \n\
176 -> master_flat, bpm \n\
177 Merge the bpm with the input bpm \n\
179 store the qc parameters in the returned property list \n\
181 Library functions used: \n\
182 cr2res_io_extract_decker_frameset() \n\
184 cr2res_extract_slitdec_curved() \n\
185 cr2res_master_flat() \n\
186 cr2res_qc_flat_lamp_ints() \n\
187 cr2res_qc_flat_mean_level() \n\
188 cr2res_qc_flat_mean_med_flux() \n\
189 cr2res_qc_flat_med_snr() \n\
190 cr2res_qc_overexposed() \n\
191 cr2res_qc_flat_trace_center_y() \n\
192 cr2res_trace_merge() \n\
193 cr2res_io_save_SLIT_MODEL() \n\
194 cr2res_io_save_EXTRACT_1D() \n\
195 cr2res_io_save_MASTER_FLAT() \n\
196 cr2res_io_save_TRACE_WAVE() \n\
197 cr2res_io_save_SLIT_FUNC() \n\
198 cr2res_io_save_BPM() \n\
216int cpl_plugin_get_info(cpl_pluginlist * list)
218 cpl_recipe * recipe = cpl_calloc(1,
sizeof *recipe );
219 cpl_plugin * plugin = &recipe->interface;
221 if (cpl_plugin_init(plugin,
223 CR2RES_BINARY_VERSION,
224 CPL_PLUGIN_TYPE_RECIPE,
227 cr2res_cal_flat_description,
228 CR2RES_PIPELINE_AUTHORS,
231 cr2res_cal_flat_create,
232 cr2res_cal_flat_exec,
233 cr2res_cal_flat_destroy)) {
234 cpl_msg_error(cpl_func,
"Plugin initialization failed");
235 (void)cpl_error_set_where(cpl_func);
239 if (cpl_pluginlist_append(list, plugin)) {
240 cpl_msg_error(cpl_func,
"Error adding plugin to list");
241 (void)cpl_error_set_where(cpl_func);
257static int cr2res_cal_flat_create(cpl_plugin * plugin)
259 cpl_recipe * recipe ;
263 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
264 recipe = (cpl_recipe *)plugin;
269 recipe->parameters = cpl_parameterlist_new();
272 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.subtract_nolight_rows",
273 CPL_TYPE_BOOL,
"Subtract the no-light rows",
274 "cr2res.cr2res_cal_flat", FALSE);
275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"subtract_nolight_rows");
276 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
277 cpl_parameterlist_append(recipe->parameters, p);
279 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.cosmics",
280 CPL_TYPE_BOOL,
"Find and mark cosmic rays hits as bad",
281 "cr2res.cr2res_cal_flat", FALSE);
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
283 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
284 cpl_parameterlist_append(recipe->parameters, p);
286 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.bpm_low",
287 CPL_TYPE_DOUBLE,
"Low threshold for BPM detection",
288 "cr2res.cr2res_cal_flat", 0.8);
289 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm_low");
290 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
291 cpl_parameterlist_append(recipe->parameters, p);
293 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.bpm_high",
294 CPL_TYPE_DOUBLE,
"High threshold for BPM detection",
295 "cr2res.cr2res_cal_flat", 1.2);
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm_high");
297 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
298 cpl_parameterlist_append(recipe->parameters, p);
300 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.bpm_lines_ratio",
301 CPL_TYPE_DOUBLE,
"Maximum ratio of bad pixels per line",
302 "cr2res.cr2res_cal_flat", 0.5);
303 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm_lines_ratio");
304 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
305 cpl_parameterlist_append(recipe->parameters, p);
307 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_degree",
308 CPL_TYPE_INT,
"polynomial degree for the fit to the orders",
309 "cr2res.cr2res_cal_flat", 2);
310 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_degree");
311 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
312 cpl_parameterlist_append(recipe->parameters, p);
314 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_min_cluster",
315 CPL_TYPE_INT,
"size in pixels of the smallest allowed cluster",
316 "cr2res.cr2res_cal_flat", 100000);
317 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_min_cluster");
318 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
319 cpl_parameterlist_append(recipe->parameters, p);
321 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_smooth_x",
322 CPL_TYPE_INT,
"Length of the smoothing kernel in x",
323 "cr2res.cr2res_cal_flat", 111);
324 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_smooth_x");
325 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
326 cpl_parameterlist_append(recipe->parameters, p);
328 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_smooth_y",
329 CPL_TYPE_INT,
"Length of the smoothing kernel in y",
330 "cr2res.cr2res_cal_flat", 401);
331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_smooth_y");
332 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
333 cpl_parameterlist_append(recipe->parameters, p);
335 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_threshold",
336 CPL_TYPE_DOUBLE,
"Detection Threshold",
337 "cr2res.cr2res_cal_flat", 1.0);
338 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_threshold");
339 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
340 cpl_parameterlist_append(recipe->parameters, p);
342 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_opening",
343 CPL_TYPE_BOOL,
"Use a morphological opening to rejoin clusters",
344 "cr2res.cr2res_cal_flat", TRUE);
345 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_opening");
346 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
347 cpl_parameterlist_append(recipe->parameters, p);
358 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_method",
359 CPL_TYPE_STRING,
"Extraction method (SUM / MEDIAN / TILTSUM / "
361 "cr2res.cr2res_util_extract",
"OPT_CURV");
362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_method");
363 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
364 cpl_parameterlist_append(recipe->parameters, p);
366 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_oversample",
367 CPL_TYPE_INT,
"factor by which to oversample the extraction",
368 "cr2res.cr2res_cal_flat", 5);
369 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_oversample");
370 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
371 cpl_parameterlist_append(recipe->parameters, p);
373 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_swath_width",
374 CPL_TYPE_INT,
"The swath width",
"cr2res.cr2res_cal_flat", 800);
375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_swath_width");
376 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
377 cpl_parameterlist_append(recipe->parameters, p);
379 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_height",
380 CPL_TYPE_INT,
"Extraction height",
381 "cr2res.cr2res_cal_flat", -1);
382 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_height");
383 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
384 cpl_parameterlist_append(recipe->parameters, p);
386 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_smooth_slit",
388 "Smoothing along the slit",
389 "cr2res.cr2res_cal_flat", 3.0);
390 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_slit");
391 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
392 cpl_parameterlist_append(recipe->parameters, p);
394 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.extract_smooth_spec",
396 "Smoothing along the spectrum",
397 "cr2res.cr2res_cal_flat", 2.0) ;
398 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_spec");
399 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
400 cpl_parameterlist_append(recipe->parameters, p);
402 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.detector",
403 CPL_TYPE_INT,
"Only reduce the specified detector",
404 "cr2res.cr2res_cal_flat", 0);
405 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detector");
406 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
407 cpl_parameterlist_append(recipe->parameters, p);
409 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.order",
410 CPL_TYPE_INT,
"Only reduce the specified order",
411 "cr2res.cr2res_cal_flat", -1);
412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"order");
413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
414 cpl_parameterlist_append(recipe->parameters, p);
416 p = cpl_parameter_new_value(
"cr2res.cr2res_cal_flat.trace_nb",
417 CPL_TYPE_INT,
"Only reduce the specified trace number",
418 "cr2res.cr2res_cal_flat", -1);
419 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"trace_nb");
420 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
421 cpl_parameterlist_append(recipe->parameters, p);
433static int cr2res_cal_flat_exec(cpl_plugin * plugin)
438 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
439 recipe = (cpl_recipe *)plugin;
442 return cr2res_cal_flat(recipe->frames, recipe->parameters);
452static int cr2res_cal_flat_destroy(cpl_plugin * plugin)
457 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
458 recipe = (cpl_recipe *)plugin;
461 cpl_parameterlist_delete(recipe->parameters);
473static int cr2res_cal_flat(
474 cpl_frameset * frameset,
475 const cpl_parameterlist * parlist)
477 const cpl_parameter * param ;
478 int subtract_nolight_rows, cosmics,
479 trace_degree, trace_min_cluster,
480 trace_opening, trace_filter,
481 extract_oversample, extract_swath_width,
482 extract_height, reduce_det, reduce_order,
483 reduce_trace, trace_smooth_x, trace_smooth_y ;
484 double bpm_low, bpm_high, bpm_lines_ratio,
485 trace_threshold, extract_smooth_slit,
486 extract_smooth_spec ;
487 cr2res_extr_method extr_method;
489 const cpl_frame * trace_wave_frame ;
490 const cpl_frame * detlin_frame ;
491 const cpl_frame * master_dark_frame ;
492 const cpl_frame * bpm_frame ;
493 cpl_frameset * rawframes ;
494 const char * used_tag ;
495 cpl_frameset * raw_one_setting_decker ;
498 cpl_propertylist * qc_main ;
500 hdrl_image * master_flat[CR2RES_NB_DETECTORS] ;
501 cpl_table * trace_wave[CR2RES_NB_DECKER_POSITIONS][CR2RES_NB_DETECTORS] ;
503 ext_plist[CR2RES_NB_DECKER_POSITIONS][CR2RES_NB_DETECTORS] ;
504 cpl_table * trace_wave_merged[CR2RES_NB_DETECTORS];
506 cpl_table * trace_wave1 ;
507 cpl_table * trace_wave2 ;
508 cpl_table * slit_func[CR2RES_NB_DETECTORS] ;
509 cpl_table * extract_1d[CR2RES_NB_DETECTORS] ;
510 hdrl_image * slit_model[CR2RES_NB_DETECTORS] ;
511 cpl_image * bpm[CR2RES_NB_DETECTORS] ;
515 cpl_vector * qc_mean,
526 int l, i, j, det_nr, nb_orders;
529 cr2res_decker decker_values[CR2RES_NB_DECKER_POSITIONS] =
530 {CR2RES_DECKER_NONE, CR2RES_DECKER_1_3, CR2RES_DECKER_2_4} ;
531 char * decker_desc[CR2RES_NB_DECKER_POSITIONS] =
532 {
"Open",
"Decker1",
"Decker2"} ;
535 param = cpl_parameterlist_find_const(parlist,
536 "cr2res.cr2res_cal_flat.subtract_nolight_rows");
537 subtract_nolight_rows = cpl_parameter_get_bool(param);
538 param = cpl_parameterlist_find_const(parlist,
539 "cr2res.cr2res_cal_flat.cosmics");
540 cosmics = cpl_parameter_get_bool(param);
541 param = cpl_parameterlist_find_const(parlist,
542 "cr2res.cr2res_cal_flat.bpm_low");
543 bpm_low = cpl_parameter_get_double(param);
544 param = cpl_parameterlist_find_const(parlist,
545 "cr2res.cr2res_cal_flat.bpm_high");
546 bpm_high = cpl_parameter_get_double(param);
547 param = cpl_parameterlist_find_const(parlist,
548 "cr2res.cr2res_cal_flat.bpm_lines_ratio");
549 bpm_lines_ratio = cpl_parameter_get_double(param);
550 param = cpl_parameterlist_find_const(parlist,
551 "cr2res.cr2res_cal_flat.trace_degree");
552 trace_degree = cpl_parameter_get_int(param);
553 param = cpl_parameterlist_find_const(parlist,
554 "cr2res.cr2res_cal_flat.trace_min_cluster");
555 trace_min_cluster = cpl_parameter_get_int(param);
556 param = cpl_parameterlist_find_const(parlist,
557 "cr2res.cr2res_cal_flat.trace_smooth_x");
558 trace_smooth_x = cpl_parameter_get_int(param);
559 param = cpl_parameterlist_find_const(parlist,
560 "cr2res.cr2res_cal_flat.trace_smooth_y");
561 trace_smooth_y = cpl_parameter_get_int(param);
562 param = cpl_parameterlist_find_const(parlist,
563 "cr2res.cr2res_cal_flat.trace_threshold");
564 trace_threshold = cpl_parameter_get_double(param);
565 param = cpl_parameterlist_find_const(parlist,
566 "cr2res.cr2res_cal_flat.trace_opening");
567 trace_opening = cpl_parameter_get_bool(param);
574 param = cpl_parameterlist_find_const(parlist,
575 "cr2res.cr2res_cal_flat.extract_method");
576 sval = cpl_parameter_get_string(param);
577 if (!strcmp(sval,
"")) extr_method = CR2RES_EXTR_OPT_CURV;
578 else if (!strcmp(sval,
"OPT_CURV")) extr_method = CR2RES_EXTR_OPT_CURV;
579 else if (!strcmp(sval,
"SUM")) extr_method = CR2RES_EXTR_SUM;
580 else if (!strcmp(sval,
"MEDIAN")) extr_method = CR2RES_EXTR_MEDIAN;
581 else if (!strcmp(sval,
"TILTSUM")) extr_method = CR2RES_EXTR_TILTSUM;
583 cpl_msg_error(__func__,
"Invalid Extraction Method specified");
584 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
587 param = cpl_parameterlist_find_const(parlist,
588 "cr2res.cr2res_cal_flat.extract_oversample");
589 extract_oversample = cpl_parameter_get_int(param);
590 param = cpl_parameterlist_find_const(parlist,
591 "cr2res.cr2res_cal_flat.extract_swath_width");
592 extract_swath_width = cpl_parameter_get_int(param);
593 param = cpl_parameterlist_find_const(parlist,
594 "cr2res.cr2res_cal_flat.extract_height");
595 extract_height = cpl_parameter_get_int(param);
596 param = cpl_parameterlist_find_const(parlist,
597 "cr2res.cr2res_cal_flat.extract_smooth_slit");
598 extract_smooth_slit = cpl_parameter_get_double(param);
599 param = cpl_parameterlist_find_const(parlist,
600 "cr2res.cr2res_cal_flat.extract_smooth_spec");
601 extract_smooth_spec = cpl_parameter_get_double(param);
602 param = cpl_parameterlist_find_const(parlist,
603 "cr2res.cr2res_cal_flat.detector");
604 reduce_det = cpl_parameter_get_int(param);
605 param = cpl_parameterlist_find_const(parlist,
606 "cr2res.cr2res_cal_flat.order");
607 reduce_order = cpl_parameter_get_int(param);
608 param = cpl_parameterlist_find_const(parlist,
609 "cr2res.cr2res_cal_flat.trace_nb");
610 reduce_trace = cpl_parameter_get_int(param);
614 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
615 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
621 detlin_frame = cpl_frameset_find_const(frameset,
622 CR2RES_CAL_DETLIN_COEFFS_PROCATG);
623 master_dark_frame = cpl_frameset_find_const(frameset,
624 CR2RES_CAL_DARK_MASTER_PROCATG) ;
628 used_tag = CR2RES_FLAT_RAW ;
630 if (rawframes==NULL || cpl_frameset_get_size(rawframes) <= 0) {
631 cpl_msg_error(__func__,
"Cannot find any RAW file") ;
632 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND) ;
637 if ((labels = cpl_frameset_labelise(rawframes, cr2res_cal_flat_compare,
638 &nlabels)) == NULL) {
639 cpl_msg_error(__func__,
"Cannot label input frames") ;
640 cpl_frameset_delete(rawframes) ;
641 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
646 for (l = 0; l < (int)nlabels; l++) {
647 cpl_frameset *raw_one_setting;
648 cpl_propertylist *plist;
651 raw_one_setting = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
654 plist = cpl_propertylist_load(cpl_frame_get_filename(
655 cpl_frameset_get_position(raw_one_setting, 0)), 0) ;
658 cpl_propertylist_delete(plist) ;
660 cpl_msg_info(__func__,
"Process SETTING %s", setting_id) ;
661 cpl_msg_indent_more() ;
664 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++) {
666 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
667 trace_wave[i][det_nr-1] = NULL ;
668 ext_plist[i][det_nr-1] = NULL ;
673 raw_one_setting, used_tag, decker_values[i]) ;
674 if (raw_one_setting_decker == NULL) {
675 cpl_msg_info(__func__,
"No files for decker: %s",
679 cpl_msg_info(__func__,
"Reduce %s Frames", decker_desc[i]) ;
680 cpl_msg_indent_more() ;
683 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
685 master_flat[det_nr-1] = NULL ;
686 slit_func[det_nr-1] = NULL ;
687 extract_1d[det_nr-1] = NULL ;
688 slit_model[det_nr-1] = NULL ;
689 bpm[det_nr-1] = NULL ;
692 if (reduce_det != 0 && det_nr != reduce_det) continue ;
694 cpl_msg_info(__func__,
"Process Detector %d", det_nr) ;
695 cpl_msg_indent_more() ;
698 if (cr2res_cal_flat_reduce(raw_one_setting_decker,
699 trace_wave_frame, detlin_frame, master_dark_frame,
700 bpm_frame, trace_filter, subtract_nolight_rows,
701 cosmics, bpm_low, bpm_high,
702 bpm_lines_ratio, trace_degree, trace_min_cluster,
703 trace_smooth_x, trace_smooth_y, trace_threshold,
704 trace_opening, extr_method, extract_oversample,
705 extract_swath_width, extract_height,
706 extract_smooth_slit, extract_smooth_spec, det_nr,
707 reduce_order, reduce_trace,
708 &(master_flat[det_nr-1]),
709 &(trace_wave[i][det_nr-1]),
710 &(slit_func[det_nr-1]),
711 &(extract_1d[det_nr-1]),
712 &(slit_model[det_nr-1]),
714 &(ext_plist[i][det_nr-1])) == -1) {
715 cpl_msg_warning(__func__,
716 "Failed to reduce detector %d of %s Frames",
717 det_nr, decker_desc[i]);
720 cpl_msg_indent_less() ;
726 if (reduce_det == 0) {
727 qc_mean = cpl_vector_new(CR2RES_NB_DETECTORS) ;
728 qc_median = cpl_vector_new(CR2RES_NB_DETECTORS) ;
729 qc_flux = cpl_vector_new(CR2RES_NB_DETECTORS) ;
730 qc_rms = cpl_vector_new(CR2RES_NB_DETECTORS) ;
731 qc_s2n = cpl_vector_new(CR2RES_NB_DETECTORS) ;
732 qc_nbbad = cpl_vector_new(CR2RES_NB_DETECTORS) ;
733 qc_centery = cpl_vector_new(CR2RES_NB_DETECTORS) ;
734 qc_blgood = cpl_vector_new(CR2RES_NB_DETECTORS) ;
735 qc_bltot = cpl_vector_new(CR2RES_NB_DETECTORS) ;
736 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
737 cpl_vector_set(qc_mean, det_nr-1,
738 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
739 CR2RES_HEADER_QC_FLAT_MEAN)) ;
740 cpl_vector_set(qc_median, det_nr-1,
741 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
742 CR2RES_HEADER_QC_FLAT_MEDIAN)) ;
743 cpl_vector_set(qc_flux, det_nr-1,
744 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
745 CR2RES_HEADER_QC_FLAT_FLUX)) ;
746 cpl_vector_set(qc_rms, det_nr-1,
747 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
748 CR2RES_HEADER_QC_FLAT_RMS)) ;
749 cpl_vector_set(qc_s2n, det_nr-1,
750 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
751 CR2RES_HEADER_QC_FLAT_S2N)) ;
752 cpl_vector_set(qc_nbbad, det_nr-1,
753 (
double)cpl_propertylist_get_int(ext_plist[i][det_nr-1],
754 CR2RES_HEADER_QC_FLAT_NBBAD)) ;
755 cpl_vector_set(qc_centery, det_nr-1,
756 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
757 CR2RES_HEADER_QC_FLAT_CENTERY)) ;
758 cpl_vector_set(qc_blgood, det_nr-1,
759 (
double)cpl_propertylist_get_int(ext_plist[i][det_nr-1],
760 CR2RES_HEADER_QC_BLAZE_NGOOD)) ;
761 cpl_vector_set(qc_bltot, det_nr-1,
762 cpl_propertylist_get_double(ext_plist[i][det_nr-1],
763 CR2RES_HEADER_QC_BLAZE_TOT)) ;
766 qc_main = cpl_propertylist_new() ;
767 cpl_propertylist_append_double(qc_main,
768 CR2RES_HEADER_QC_FLAT_MEAN_AVG,
769 cpl_vector_get_mean(qc_mean)) ;
770 cpl_propertylist_append_double(qc_main,
771 CR2RES_HEADER_QC_FLAT_MEAN_RMS,
772 cpl_vector_get_stdev(qc_mean)) ;
773 cpl_propertylist_append_double(qc_main,
774 CR2RES_HEADER_QC_FLAT_MEDIAN_AVG,
775 cpl_vector_get_mean(qc_median)) ;
776 cpl_propertylist_append_double(qc_main,
777 CR2RES_HEADER_QC_FLAT_MEDIAN_RMS,
778 cpl_vector_get_stdev(qc_median)) ;
779 cpl_propertylist_append_double(qc_main,
780 CR2RES_HEADER_QC_FLAT_FLUX_AVG,
781 cpl_vector_get_mean(qc_flux)) ;
782 cpl_propertylist_append_double(qc_main,
783 CR2RES_HEADER_QC_FLAT_FLUX_RMS,
784 cpl_vector_get_stdev(qc_flux)) ;
785 cpl_propertylist_append_double(qc_main,
786 CR2RES_HEADER_QC_FLAT_RMS_AVG,
787 cpl_vector_get_mean(qc_rms)) ;
788 cpl_propertylist_append_double(qc_main,
789 CR2RES_HEADER_QC_FLAT_RMS_RMS,
790 cpl_vector_get_stdev(qc_rms)) ;
791 cpl_propertylist_append_double(qc_main,
792 CR2RES_HEADER_QC_FLAT_S2N_AVG,
793 cpl_vector_get_mean(qc_s2n)) ;
794 cpl_propertylist_append_double(qc_main,
795 CR2RES_HEADER_QC_FLAT_S2N_RMS,
796 cpl_vector_get_stdev(qc_s2n)) ;
797 cpl_propertylist_append_double(qc_main,
798 CR2RES_HEADER_QC_FLAT_NBBAD_AVG,
799 cpl_vector_get_mean(qc_nbbad)) ;
800 cpl_propertylist_append_double(qc_main,
801 CR2RES_HEADER_QC_FLAT_NBBAD_RMS,
802 cpl_vector_get_stdev(qc_nbbad)) ;
803 cpl_propertylist_append_double(qc_main,
804 CR2RES_HEADER_QC_FLAT_CENTERY_AVG,
805 cpl_vector_get_mean(qc_centery)) ;
806 cpl_propertylist_append_double(qc_main,
807 CR2RES_HEADER_QC_FLAT_CENTERY_RMS,
808 cpl_vector_get_stdev(qc_centery)) ;
809 cpl_propertylist_append_double(qc_main,
810 CR2RES_HEADER_QC_BLAZE_NORM,
811 cpl_vector_get_sum(qc_bltot)/cpl_vector_get_sum(qc_blgood)) ;
812 cpl_vector_delete(qc_mean) ;
813 cpl_vector_delete(qc_median) ;
814 cpl_vector_delete(qc_flux) ;
815 cpl_vector_delete(qc_rms) ;
816 cpl_vector_delete(qc_s2n) ;
817 cpl_vector_delete(qc_nbbad) ;
818 cpl_vector_delete(qc_centery) ;
819 cpl_vector_delete(qc_blgood) ;
820 cpl_vector_delete(qc_bltot) ;
822 if (trace_wave[i][0] != NULL) {
826 trace_wave[i][0], &nb_orders) ;
828 for (j=0 ; j<nb_orders ; j++) {
829 qc_orderpos = cpl_vector_new(CR2RES_NB_DETECTORS) ;
830 qc_overexposed = cpl_vector_new(CR2RES_NB_DETECTORS) ;
831 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++){
833 qc_name = cpl_sprintf(
"%s%02d",
834 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]) ;
835 cpl_vector_set(qc_overexposed, det_nr-1,
836 cpl_propertylist_get_double(
837 ext_plist[i][det_nr-1], qc_name)) ;
840 qc_name = cpl_sprintf(
"%s%02d",
841 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]) ;
842 cpl_vector_set(qc_orderpos, det_nr-1,
843 cpl_propertylist_get_double(
844 ext_plist[i][det_nr-1], qc_name)) ;
849 qc_name = cpl_sprintf(
"%s%02d AVG",
850 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]) ;
851 cpl_propertylist_append_double(qc_main,
852 qc_name, cpl_vector_get_mean(qc_overexposed)) ;
855 qc_name = cpl_sprintf(
"%s%02d RMS",
856 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]) ;
857 cpl_propertylist_append_double(qc_main,
858 qc_name, cpl_vector_get_stdev(qc_overexposed)) ;
860 cpl_vector_delete(qc_overexposed) ;
863 qc_name = cpl_sprintf(
"%s%02d AVG",
864 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]) ;
865 cpl_propertylist_append_double(qc_main,
866 qc_name, cpl_vector_get_mean(qc_orderpos)) ;
869 qc_name = cpl_sprintf(
"%s%02d RMS",
870 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]) ;
871 cpl_propertylist_append_double(qc_main,
872 qc_name, cpl_vector_get_stdev(qc_orderpos)) ;
874 cpl_vector_delete(qc_orderpos) ;
887 out_file = cpl_sprintf(
"%s_%s_master_flat.fits",
888 RECIPE_STRING, decker_desc[i]) ;
890 out_file = cpl_sprintf(
"%s_%s_%s_master_flat.fits",
891 RECIPE_STRING, setting_id, decker_desc[i]) ;
894 frameset, parlist, master_flat, qc_main,
895 ext_plist[i], CR2RES_CAL_FLAT_MASTER_PROCATG,
901 out_file = cpl_sprintf(
"%s_%s_slit_model.fits",
902 RECIPE_STRING, decker_desc[i]) ;
904 out_file = cpl_sprintf(
"%s_%s_%s_slit_model.fits",
905 RECIPE_STRING, setting_id, decker_desc[i]) ;
908 frameset, parlist, slit_model, qc_main,
909 ext_plist[i], CR2RES_CAL_FLAT_SLIT_MODEL_PROCATG,
915 out_file = cpl_sprintf(
"%s_%s_blaze.fits",
916 RECIPE_STRING, decker_desc[i]) ;
918 out_file = cpl_sprintf(
"%s_%s_%s_blaze.fits",
919 RECIPE_STRING, setting_id, decker_desc[i]) ;
922 frameset, parlist, extract_1d, qc_main,
923 ext_plist[i], CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG,
929 out_file = cpl_sprintf(
"%s_%s_tw.fits",
930 RECIPE_STRING, decker_desc[i]) ;
932 out_file = cpl_sprintf(
"%s_%s_%s_tw.fits",
933 RECIPE_STRING, setting_id, decker_desc[i]) ;
936 frameset, parlist, trace_wave[i], qc_main,
937 ext_plist[i], CR2RES_CAL_FLAT_TW_PROCATG, RECIPE_STRING);
942 out_file = cpl_sprintf(
"%s_%s_slit_func.fits",
943 RECIPE_STRING, decker_desc[i]) ;
945 out_file = cpl_sprintf(
"%s_%s_%s_slit_func.fits",
946 RECIPE_STRING, setting_id, decker_desc[i]) ;
949 frameset, parlist, slit_func, qc_main,
950 ext_plist[i], CR2RES_CAL_FLAT_SLIT_FUNC_PROCATG,
956 out_file = cpl_sprintf(
"%s_%s_bpm.fits",
957 RECIPE_STRING, decker_desc[i]) ;
959 out_file = cpl_sprintf(
"%s_%s_%s_bpm.fits",
960 RECIPE_STRING, setting_id, decker_desc[i]) ;
963 frameset, parlist, bpm, qc_main, ext_plist[i],
964 CR2RES_CAL_FLAT_BPM_PROCATG, RECIPE_STRING) ;
968 if (qc_main != NULL) cpl_propertylist_delete(qc_main) ;
969 cpl_frameset_delete(raw_one_setting_decker) ;
970 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
971 if (master_flat[det_nr-1] != NULL)
973 if (slit_func[det_nr-1] != NULL)
974 cpl_table_delete(slit_func[det_nr-1]) ;
975 if (extract_1d[det_nr-1] != NULL)
976 cpl_table_delete(extract_1d[det_nr-1]) ;
977 if (slit_model[det_nr-1] != NULL)
979 if (bpm[det_nr-1] != NULL)
980 cpl_image_delete(bpm[det_nr-1]) ;
982 cpl_msg_indent_less() ;
986 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
988 if (trace_wave[0][det_nr-1] != NULL)
989 trace_wave_merged[det_nr-1] =
990 cpl_table_duplicate(trace_wave[0][det_nr-1]) ;
992 trace_wave_merged[det_nr-1] = NULL ;
994 for (i=1 ; i<CR2RES_NB_DECKER_POSITIONS ; i++) {
995 trace_wave1 = trace_wave_merged[det_nr-1] ;
996 trace_wave2 = trace_wave[i][det_nr-1] ;
997 if (trace_wave1 == NULL && trace_wave2 == NULL) {
999 trace_wave_merged[det_nr-1] = NULL ;
1000 }
else if (trace_wave1 == NULL && trace_wave2 != NULL) {
1001 trace_wave_merged[det_nr-1] =
1002 cpl_table_duplicate(trace_wave2) ;
1003 }
else if (trace_wave1 != NULL && trace_wave2 == NULL) {
1007 if (merged == NULL) {
1008 cpl_msg_error(__func__,
"Failed merging") ;
1010 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1011 trace_wave_merged[det_nr-1] = merged ;
1018 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++)
1019 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1020 if (trace_wave[i][det_nr-1] != NULL)
1021 cpl_table_delete(trace_wave[i][det_nr-1]) ;
1026 out_file = cpl_sprintf(
"%s_tw_merged.fits",
1029 out_file = cpl_sprintf(
"%s_%s_tw_merged.fits", RECIPE_STRING,
1037 trace_wave_merged, NULL, ext_plist[0],
1038 CR2RES_CAL_FLAT_TW_MERGED_PROCATG, RECIPE_STRING) ;
1040 cpl_free(setting_id) ;
1043 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++)
1044 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1045 if (ext_plist[i][det_nr-1] != NULL)
1046 cpl_propertylist_delete(ext_plist[i][det_nr-1]) ;
1049 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1050 if (trace_wave_merged[det_nr-1] != NULL)
1051 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1053 cpl_frameset_delete(raw_one_setting) ;
1054 cpl_msg_indent_less() ;
1057 cpl_frameset_delete(rawframes) ;
1059 return (
int)cpl_error_get_code();
1101static int cr2res_cal_flat_reduce(
1102 const cpl_frameset * rawframes,
1103 const cpl_frame * tw_frame,
1104 const cpl_frame * detlin_frame,
1105 const cpl_frame * master_dark_frame,
1106 const cpl_frame * bpm_frame,
1108 int subtract_nolight_rows,
1114 int trace_min_cluster,
1117 double trace_threshold,
1119 cr2res_extr_method extr_method,
1120 int extract_oversample,
1121 int extract_swath_width,
1123 double extract_smooth_slit,
1124 double extract_smooth_spec,
1128 hdrl_image ** master_flat,
1129 cpl_table ** trace_wave,
1130 cpl_table ** slit_func,
1131 cpl_table ** extract_1d,
1132 hdrl_image ** slit_model,
1134 cpl_propertylist ** ext_plist)
1136 const char * first_file ;
1137 hdrl_image * first_image ;
1138 hdrl_imagelist * imlist ;
1139 hdrl_imagelist * imlist_calibrated ;
1140 hdrl_image * collapsed ;
1141 cpl_image * contrib ;
1142 cpl_propertylist * plist ;
1143 hdrl_image * master_flat_loc ;
1144 cpl_image * my_master_flat ;
1145 cpl_image * bpm_im ;
1146 cpl_image * bpm_flat ;
1147 cpl_mask * bpm_mask ;
1148 cpl_table * computed_traces ;
1149 cpl_table * filtered_traces ;
1150 cpl_table * traces ;
1151 cpl_bivector ** spectrum ;
1152 cpl_vector ** slit_func_vec ;
1153 hdrl_image * model_master;
1154 cpl_table * slit_func_tab ;
1155 cpl_table * extract_tab ;
1156 hdrl_image * model_tmp ;
1158 cpl_vector * ndits ;
1160 double * qc_order_pos ;
1162 double qc_mean, qc_median, qc_flux, qc_rms, qc_s2n,
1163 qc_trace_centery, dit,
1164 gain, error_factor, bl_tot ;
1165 int i, ext_nr, nb_traces,
1166 nb_orders, qc_nbbad, nbvals, ngood, bl_good ;
1169 int extract_niter = 10;
1170 double extract_kappa = 10;
1173 if (rawframes == NULL)
return -1 ;
1174 if (extr_method != CR2RES_EXTR_OPT_CURV &&
1175 extr_method != CR2RES_EXTR_SUM) {
1176 cpl_msg_error(__func__,
"Failed to read the dits") ;
1181 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
1182 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
1183 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
1185 cpl_msg_error(__func__,
"Failed to get the Gain value") ;
1190 first_file = cpl_frame_get_filename(
1191 cpl_frameset_get_position_const(rawframes, 0)) ;
1195 cpl_msg_error(__func__,
"Failed to read the dits") ;
1203 if (imlist == NULL) {
1204 cpl_msg_error(__func__,
"Failed to load the images") ;
1205 cpl_vector_delete(dits) ;
1206 cpl_vector_delete(ndits) ;
1211 error_factor = gain * cpl_vector_get(ndits, 0) *
1212 cpl_frameset_get_size(rawframes) ;
1214 for (i=0; i<cpl_vector_get_size(ndits); i++){
1215 if (cpl_vector_get(ndits,i) != cpl_vector_get(ndits, 0))
1216 cpl_msg_warning(__func__,
"Raw frames have different NDIT! "
1217 "Error spectrum will likely be scaled incorrectly.");
1221 cpl_msg_info(__func__,
"Compute the traces") ;
1222 cpl_msg_indent_more() ;
1225 trace_smooth_x, trace_smooth_y, trace_threshold,
1226 trace_opening, trace_degree, trace_min_cluster)) == NULL) {
1227 cpl_msg_error(__func__,
"Failed compute the traces") ;
1228 cpl_vector_delete(dits) ;
1229 cpl_vector_delete(ndits) ;
1231 cpl_msg_indent_less() ;
1234 cpl_msg_indent_less() ;
1237 cpl_msg_info(__func__,
"Calibrate the input images") ;
1238 cpl_msg_indent_more() ;
1240 0, subtract_nolight_rows, 0, cosmics, NULL,
1241 master_dark_frame, bpm_frame, detlin_frame, dits, ndits))==NULL) {
1242 cpl_msg_error(__func__,
"Failed to Calibrate the Data") ;
1243 cpl_vector_delete(dits) ;
1244 cpl_vector_delete(ndits) ;
1246 cpl_table_delete(computed_traces) ;
1247 cpl_msg_indent_less() ;
1252 imlist = imlist_calibrated ;
1254 cpl_vector_delete(dits) ;
1255 cpl_vector_delete(ndits) ;
1256 cpl_msg_indent_less() ;
1259 cpl_msg_info(__func__,
"Collapse the input images") ;
1260 cpl_msg_indent_more() ;
1263 cpl_msg_error(__func__,
"Failed to Collapse") ;
1265 cpl_table_delete(computed_traces) ;
1266 cpl_msg_indent_less() ;
1270 cpl_image_delete(contrib) ;
1271 cpl_msg_indent_less() ;
1277 if (filter_traces) {
1280 cpl_msg_info(__func__,
"Filter out the traces") ;
1281 cpl_msg_indent_more() ;
1284 plist = cpl_propertylist_load(first_file, 0) ;
1286 zp_order = cr2res_pfits_get_order_zp(plist) ;
1287 cpl_propertylist_delete(plist) ;
1289 setting_id, zp_order) ;
1290 cpl_free(setting_id) ;
1291 cpl_table_delete(computed_traces) ;
1292 computed_traces = filtered_traces ;
1293 cpl_msg_indent_less() ;
1294 if (cpl_table_get_nrow(computed_traces) == 0) {
1295 cpl_msg_error(__func__,
"All traces are filtered out") ;
1297 cpl_table_delete(computed_traces) ;
1298 cpl_msg_indent_less() ;
1307 if (traces == NULL) {
1308 cpl_msg_error(__func__,
"Cannot Load the provided TW file") ;
1310 cpl_table_delete(computed_traces) ;
1314 traces = cpl_table_duplicate(computed_traces) ;
1316 cpl_table_delete(computed_traces) ;
1319 nb_traces = cpl_table_get_nrow(traces) ;
1320 spectrum = cpl_malloc(nb_traces *
sizeof(cpl_bivector *)) ;
1321 slit_func_vec = cpl_malloc(nb_traces *
sizeof(cpl_vector *)) ;
1322 model_master =
hdrl_image_new(CR2RES_DETECTOR_SIZE, CR2RES_DETECTOR_SIZE) ;
1326 cpl_msg_info(__func__,
"Extract the traces") ;
1327 cpl_msg_indent_more() ;
1328 for (i=0 ; i<nb_traces ; i++) {
1329 int order, trace_id;
1331 slit_func_vec[i] = NULL ;
1332 spectrum[i] = NULL ;
1336 order = cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL) ;
1337 trace_id = cpl_table_get(traces, CR2RES_COL_TRACENB, i, NULL) ;
1340 if (reduce_order > -1 && order != reduce_order) continue ;
1343 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1345 cpl_msg_info(__func__,
"Process Order %d/Trace %d", order, trace_id) ;
1346 cpl_msg_indent_more() ;
1349 if (extr_method == CR2RES_EXTR_SUM) {
1351 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1353 cpl_msg_error(__func__,
"Cannot (sum-)extract the trace") ;
1354 slit_func_vec[i] = NULL ;
1355 spectrum[i] = NULL ;
1358 cpl_msg_indent_less() ;
1361 }
else if (extr_method == CR2RES_EXTR_MEDIAN) {
1363 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1365 cpl_msg_error(__func__,
"Cannot (median-)extract the trace") ;
1366 slit_func_vec[i] = NULL ;
1367 spectrum[i] = NULL ;
1370 cpl_msg_indent_less() ;
1373 }
else if (extr_method == CR2RES_EXTR_TILTSUM) {
1375 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1377 cpl_msg_error(__func__,
"Cannot (tiltsum-)extract the trace") ;
1378 slit_func_vec[i] = NULL ;
1379 spectrum[i] = NULL ;
1382 cpl_msg_indent_less() ;
1385 }
else if (extr_method == CR2RES_EXTR_OPT_CURV) {
1387 trace_id, extract_height, extract_swath_width,
1388 extract_oversample, extract_smooth_slit,
1389 extract_smooth_spec, extract_niter, extract_kappa,
1391 &(slit_func_vec[i]), &(spectrum[i]), &model_tmp) != 0) {
1392 cpl_msg_error(__func__,
"Cannot (slitdec-) extract the trace") ;
1393 slit_func_vec[i] = NULL ;
1394 spectrum[i] = NULL ;
1397 cpl_msg_indent_less() ;
1403 if (model_tmp != NULL) {
1407 cpl_msg_indent_less() ;
1409 cpl_msg_indent_less() ;
1418 for (i=0 ; i<nb_traces ; i++) {
1419 if (slit_func_vec[i] != NULL) cpl_vector_delete(slit_func_vec[i]) ;
1420 if (spectrum[i] != NULL) cpl_bivector_delete(spectrum[i]) ;
1422 cpl_free(spectrum) ;
1423 cpl_free(slit_func_vec) ;
1426 cpl_msg_info(__func__,
"Compute the master flat") ;
1427 cpl_msg_indent_more() ;
1429 model_master, bpm_low, bpm_high, bpm_linemax,
1430 &bpm_flat)) == NULL) {
1431 cpl_msg_error(__func__,
"Failed compute the Master Flat") ;
1432 cpl_table_delete(slit_func_tab) ;
1433 cpl_table_delete(traces) ;
1434 cpl_table_delete(extract_tab) ;
1437 cpl_msg_indent_less() ;
1440 cpl_msg_indent_less() ;
1445 if (bpm_frame != NULL) {
1447 cpl_frame_get_filename(bpm_frame),
1448 reduce_det, 1)) == NULL) {
1449 cpl_msg_warning(__func__,
"Failed to Load the Master BPM") ;
1452 if (bpm_im == NULL) {
1453 bpm_im = cpl_image_duplicate(bpm_flat) ;
1455 if (cpl_image_or(bpm_im, NULL, bpm_flat)) {
1456 cpl_msg_error(__func__,
"Failed to add the mask to the BPM") ;
1457 cpl_table_delete(traces) ;
1458 cpl_table_delete(slit_func_tab) ;
1459 cpl_table_delete(extract_tab) ;
1462 cpl_image_delete(bpm_im) ;
1463 cpl_image_delete(bpm_flat) ;
1464 cpl_msg_indent_less() ;
1468 cpl_image_delete(bpm_flat) ;
1481 plist = cpl_propertylist_load(first_file, 0) ;
1483 cpl_propertylist_delete(plist) ;
1484 qc_flux = qc_mean / dit ;
1487 cpl_image_reject_from_mask(my_master_flat, bpm_mask) ;
1488 ngood = CR2RES_DETECTOR_SIZE* CR2RES_DETECTOR_SIZE -
1489 cpl_mask_count(bpm_mask) ;
1490 cpl_mask_delete(bpm_mask);
1491 qc_rms = sqrt(cpl_image_get_sqflux(my_master_flat) / ngood) ;
1492 cpl_image_delete(my_master_flat) ;
1504 plist = cpl_propertylist_load(first_file, ext_nr) ;
1505 if (plist == NULL) {
1507 cpl_table_delete(traces) ;
1508 cpl_table_delete(slit_func_tab) ;
1509 cpl_table_delete(extract_tab) ;
1512 cpl_image_delete(bpm_im) ;
1513 cpl_msg_error(__func__,
"Failed to load the plist") ;
1522 for (i=0 ; i<nb_orders ; i++) {
1523 double qc_overexposed;
1526 char * qc_name = cpl_sprintf(
"%s%02d",
1527 CR2RES_HEADER_QC_OVEREXPOSED, orders[i]) ;
1528 cpl_propertylist_append_double(plist, qc_name, qc_overexposed);
1535 if (qc_order_nb != NULL && qc_order_pos != NULL) {
1536 for (i=0 ; i<nbvals ; i++) {
1537 char * qc_name = cpl_sprintf(
"%s%02d",
1538 CR2RES_HEADER_QC_FLAT_ORDERPOS, qc_order_nb[i]) ;
1539 cpl_propertylist_append_double(plist, qc_name, qc_order_pos[i]);
1543 if (qc_order_nb != NULL) cpl_free(qc_order_nb) ;
1544 if (qc_order_pos != NULL) cpl_free(qc_order_pos) ;
1546 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEAN,
1548 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEDIAN,
1550 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_FLUX,
1552 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_RMS,
1554 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_S2N,
1556 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_CENTERY,
1558 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_FLAT_NBBAD,
1560 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_BLAZE_NGOOD,
1562 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_BLAZE_TOT,
1566 *trace_wave = traces ;
1567 *slit_func = slit_func_tab ;
1568 *extract_1d = extract_tab ;
1569 *slit_model = model_master ;
1570 *master_flat = master_flat_loc ;
1571 *ext_plist = plist ;
1584static int cr2res_cal_flat_compare(
1585 const cpl_frame * frame1,
1586 const cpl_frame * frame2)
1589 cpl_propertylist * plist1 ;
1590 cpl_propertylist * plist2 ;
1591 const char * sval1 ;
1592 const char * sval2 ;
1595 if (frame1==NULL || frame2==NULL)
return -1 ;
1598 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1599 cpl_msg_error(__func__,
"getting header from reference frame");
1602 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1603 cpl_msg_error(__func__,
"getting header from reference frame");
1604 cpl_propertylist_delete(plist1) ;
1609 if (cpl_error_get_code()) {
1610 cpl_propertylist_delete(plist1) ;
1611 cpl_propertylist_delete(plist2) ;
1620 if (cpl_error_get_code()) {
1621 cpl_msg_error(__func__,
"Cannot get the reference wavelength");
1622 cpl_propertylist_delete(plist1) ;
1623 cpl_propertylist_delete(plist2) ;
1626 if (strcmp(sval1, sval2)) comparison = 0 ;
1628 cpl_propertylist_delete(plist1) ;
1629 cpl_propertylist_delete(plist2) ;
int cr2res_bpm_count(cpl_image *bpm, cr2res_bpm_type type)
Count BPM of a given type.
cpl_mask * cr2res_bpm_extract_mask(const cpl_image *bpm_ima, cr2res_bpm_type bpm_type)
Extract a mask from a BPM image.
hdrl_imagelist * cr2res_calib_imagelist(const hdrl_imagelist *in, int chip, int clean_bad, int subtract_nolight_rows, int subtract_interorder_column, int cosmics_corr, const cpl_frame *flat, const cpl_frame *dark, const cpl_frame *bpm, const cpl_frame *detlin, const cpl_vector *dits, const cpl_vector *ndits)
The images calibration routine for a given chip on a list.
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
hdrl_image * cr2res_master_flat(const hdrl_image *collapsed, const hdrl_image *model_master, double low, double high, double bad_per_line_limit, cpl_image **bpm)
Compute the Master Flat.
const cpl_frame * cr2res_io_find_BPM(const cpl_frameset *in)
Get the first CR2RES_BPM_DRSTYPE frame from a frameset.
int cr2res_io_save_SLIT_MODEL(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_image **data, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_MODEL.
const cpl_frame * cr2res_io_find_TRACE_WAVE(const cpl_frameset *in)
Get the first CR2RES_TW_DRSTYPE frame from a frameset.
int cr2res_io_save_TRACE_WAVE(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a TRACE_WAVE.
cpl_frameset * cr2res_io_extract_decker_frameset(const cpl_frameset *in, const char *tag, cr2res_decker decker)
Extract the frames with the given tag and Decker position.
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
int cr2res_io_save_EXTRACT_1D(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a 1D extracted spectrum.
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
int cr2res_io_save_MASTER_FLAT(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_image **master_flats, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a MASTER_FLAT.
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
hdrl_image * cr2res_io_load_image(const char *in, int detector)
Load an hdrl image from a image file.
int cr2res_io_save_SLIT_FUNC(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **slit_func, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_FUNC.
int cr2res_io_save_BPM(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_image **bpms, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a BPM.
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
cpl_image * cr2res_io_load_BPM(const char *filename, int detector, int data)
Load an image from a BPM.
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
double cr2res_qc_overexposed(const cpl_image *ima, const cpl_table *tw, int order_idx)
Computes the Overexposed fraction.
double cr2res_qc_flat_s2n(const cpl_table *extracted)
Computes the S2N on the flat.
int cr2res_qc_flat_order_positions(const cpl_table *tw, int **order_nb, double **order_pos, int *nbvals)
Compute the central orders positions.
double cr2res_qc_flat_trace_center_y(const cpl_table *trace)
Computes the mean Y coord of the central order.
cpl_table * cr2res_trace_filter(const cpl_table *tw, const char *setting, int zp_order)
Only keep the predefined orders of the setting.
cpl_table * cr2res_trace(cpl_image *ima, int smooth_x, int smooth_y, double threshold, int opening, int degree, int min_cluster)
Main function for running all parts of the trace algorithm.
int cr2res_trace_add_extra_columns(cpl_table *traces, const char *infile, int det_nr)
Add extra columns to the plain trace table.
int * cr2res_trace_get_order_idx_values(const cpl_table *trace, int *nb_order_idx_values)
Count and return the different order_idx values from a TW table.
cpl_table * cr2res_trace_merge(const cpl_table *trace_wave1, const cpl_table *trace_wave2)
Merge 2 trace_wave tables.
int cr2res_format_setting(char *setting_id)
Format the setting.
double cr2res_util_blaze_stat(const cpl_table *blaze, int *ngood, double *blaze_tot)
Computes the average of the blaze.
cpl_frameset * cr2res_extract_frameset(const cpl_frameset *in, const char *tag)
Extract the frames with the given tag from a frameset.
const char * cr2res_get_license(void)
Get the pipeline copyright and license.
cpl_error_code hdrl_image_add_image(hdrl_image *self, const hdrl_image *other)
Add two images, store the result in the first image.
cpl_error_code hdrl_image_mul_scalar(hdrl_image *self, hdrl_value value)
Elementwise multiplication of an image with a scalar.
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.