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 cpl_vector_fill(qc_orderpos, 0.0) ;
832 cpl_vector_fill(qc_overexposed, 0.0) ;
833 for (det_nr = 1; det_nr <= CR2RES_NB_DETECTORS; det_nr++)
836 qc_name = cpl_sprintf(
"%s%02d",
837 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]);
838 if (cpl_propertylist_has(ext_plist[i][det_nr - 1], qc_name))
840 cpl_vector_set(qc_overexposed, det_nr - 1,
841 cpl_propertylist_get_double(
842 ext_plist[i][det_nr - 1], qc_name));
846 qc_name = cpl_sprintf(
"%s%02d",
847 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]);
848 if (cpl_propertylist_has(ext_plist[i][det_nr - 1], qc_name))
850 cpl_vector_set(qc_orderpos, det_nr - 1,
851 cpl_propertylist_get_double(
852 ext_plist[i][det_nr - 1], qc_name));
858 qc_name = cpl_sprintf(
"%s%02d AVG",
859 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]) ;
860 cpl_propertylist_append_double(qc_main,
861 qc_name, cpl_vector_get_mean(qc_overexposed)) ;
864 qc_name = cpl_sprintf(
"%s%02d RMS",
865 CR2RES_HEADER_QC_OVEREXPOSED, orders[j]) ;
866 cpl_propertylist_append_double(qc_main,
867 qc_name, cpl_vector_get_stdev(qc_overexposed)) ;
869 cpl_vector_delete(qc_overexposed) ;
872 qc_name = cpl_sprintf(
"%s%02d AVG",
873 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]) ;
874 cpl_propertylist_append_double(qc_main,
875 qc_name, cpl_vector_get_mean(qc_orderpos)) ;
878 qc_name = cpl_sprintf(
"%s%02d RMS",
879 CR2RES_HEADER_QC_FLAT_ORDERPOS, orders[j]) ;
880 cpl_propertylist_append_double(qc_main,
881 qc_name, cpl_vector_get_stdev(qc_orderpos)) ;
883 cpl_vector_delete(qc_orderpos) ;
896 out_file = cpl_sprintf(
"%s_%s_master_flat.fits",
897 RECIPE_STRING, decker_desc[i]) ;
899 out_file = cpl_sprintf(
"%s_%s_%s_master_flat.fits",
900 RECIPE_STRING, setting_id, decker_desc[i]) ;
903 frameset, parlist, master_flat, qc_main,
904 ext_plist[i], CR2RES_CAL_FLAT_MASTER_PROCATG,
910 out_file = cpl_sprintf(
"%s_%s_slit_model.fits",
911 RECIPE_STRING, decker_desc[i]) ;
913 out_file = cpl_sprintf(
"%s_%s_%s_slit_model.fits",
914 RECIPE_STRING, setting_id, decker_desc[i]) ;
917 frameset, parlist, slit_model, qc_main,
918 ext_plist[i], CR2RES_CAL_FLAT_SLIT_MODEL_PROCATG,
924 out_file = cpl_sprintf(
"%s_%s_blaze.fits",
925 RECIPE_STRING, decker_desc[i]) ;
927 out_file = cpl_sprintf(
"%s_%s_%s_blaze.fits",
928 RECIPE_STRING, setting_id, decker_desc[i]) ;
931 frameset, parlist, extract_1d, qc_main,
932 ext_plist[i], CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG,
938 out_file = cpl_sprintf(
"%s_%s_tw.fits",
939 RECIPE_STRING, decker_desc[i]) ;
941 out_file = cpl_sprintf(
"%s_%s_%s_tw.fits",
942 RECIPE_STRING, setting_id, decker_desc[i]) ;
945 frameset, parlist, trace_wave[i], qc_main,
946 ext_plist[i], CR2RES_CAL_FLAT_TW_PROCATG, RECIPE_STRING);
951 out_file = cpl_sprintf(
"%s_%s_slit_func.fits",
952 RECIPE_STRING, decker_desc[i]) ;
954 out_file = cpl_sprintf(
"%s_%s_%s_slit_func.fits",
955 RECIPE_STRING, setting_id, decker_desc[i]) ;
958 frameset, parlist, slit_func, qc_main,
959 ext_plist[i], CR2RES_CAL_FLAT_SLIT_FUNC_PROCATG,
965 out_file = cpl_sprintf(
"%s_%s_bpm.fits",
966 RECIPE_STRING, decker_desc[i]) ;
968 out_file = cpl_sprintf(
"%s_%s_%s_bpm.fits",
969 RECIPE_STRING, setting_id, decker_desc[i]) ;
972 frameset, parlist, bpm, qc_main, ext_plist[i],
973 CR2RES_CAL_FLAT_BPM_PROCATG, RECIPE_STRING) ;
977 if (qc_main != NULL) cpl_propertylist_delete(qc_main) ;
978 cpl_frameset_delete(raw_one_setting_decker) ;
979 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
980 if (master_flat[det_nr-1] != NULL)
982 if (slit_func[det_nr-1] != NULL)
983 cpl_table_delete(slit_func[det_nr-1]) ;
984 if (extract_1d[det_nr-1] != NULL)
985 cpl_table_delete(extract_1d[det_nr-1]) ;
986 if (slit_model[det_nr-1] != NULL)
988 if (bpm[det_nr-1] != NULL)
989 cpl_image_delete(bpm[det_nr-1]) ;
991 cpl_msg_indent_less() ;
995 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
997 if (trace_wave[0][det_nr-1] != NULL)
998 trace_wave_merged[det_nr-1] =
999 cpl_table_duplicate(trace_wave[0][det_nr-1]) ;
1001 trace_wave_merged[det_nr-1] = NULL ;
1003 for (i=1 ; i<CR2RES_NB_DECKER_POSITIONS ; i++) {
1004 trace_wave1 = trace_wave_merged[det_nr-1] ;
1005 trace_wave2 = trace_wave[i][det_nr-1] ;
1006 if (trace_wave1 == NULL && trace_wave2 == NULL) {
1008 trace_wave_merged[det_nr-1] = NULL ;
1009 }
else if (trace_wave1 == NULL && trace_wave2 != NULL) {
1010 trace_wave_merged[det_nr-1] =
1011 cpl_table_duplicate(trace_wave2) ;
1012 }
else if (trace_wave1 != NULL && trace_wave2 == NULL) {
1016 if (merged == NULL) {
1017 cpl_msg_error(__func__,
"Failed merging") ;
1019 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1020 trace_wave_merged[det_nr-1] = merged ;
1027 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++)
1028 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1029 if (trace_wave[i][det_nr-1] != NULL)
1030 cpl_table_delete(trace_wave[i][det_nr-1]) ;
1035 out_file = cpl_sprintf(
"%s_tw_merged.fits",
1038 out_file = cpl_sprintf(
"%s_%s_tw_merged.fits", RECIPE_STRING,
1046 trace_wave_merged, NULL, ext_plist[0],
1047 CR2RES_CAL_FLAT_TW_MERGED_PROCATG, RECIPE_STRING) ;
1049 cpl_free(setting_id) ;
1052 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++)
1053 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1054 if (ext_plist[i][det_nr-1] != NULL)
1055 cpl_propertylist_delete(ext_plist[i][det_nr-1]) ;
1058 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
1059 if (trace_wave_merged[det_nr-1] != NULL)
1060 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1062 cpl_frameset_delete(raw_one_setting) ;
1063 cpl_msg_indent_less() ;
1066 cpl_frameset_delete(rawframes) ;
1068 return (
int)cpl_error_get_code();
1110static int cr2res_cal_flat_reduce(
1111 const cpl_frameset * rawframes,
1112 const cpl_frame * tw_frame,
1113 const cpl_frame * detlin_frame,
1114 const cpl_frame * master_dark_frame,
1115 const cpl_frame * bpm_frame,
1117 int subtract_nolight_rows,
1123 int trace_min_cluster,
1126 double trace_threshold,
1128 cr2res_extr_method extr_method,
1129 int extract_oversample,
1130 int extract_swath_width,
1132 double extract_smooth_slit,
1133 double extract_smooth_spec,
1137 hdrl_image ** master_flat,
1138 cpl_table ** trace_wave,
1139 cpl_table ** slit_func,
1140 cpl_table ** extract_1d,
1141 hdrl_image ** slit_model,
1143 cpl_propertylist ** ext_plist)
1145 const char * first_file ;
1146 hdrl_image * first_image ;
1147 hdrl_imagelist * imlist ;
1148 hdrl_imagelist * imlist_calibrated ;
1149 hdrl_image * collapsed ;
1150 cpl_image * contrib ;
1151 cpl_propertylist * plist ;
1152 hdrl_image * master_flat_loc ;
1153 cpl_image * my_master_flat ;
1154 cpl_image * bpm_im ;
1155 cpl_image * bpm_flat ;
1156 cpl_mask * bpm_mask ;
1157 cpl_table * computed_traces ;
1158 cpl_table * filtered_traces ;
1159 cpl_table * traces ;
1160 cpl_bivector ** spectrum ;
1161 cpl_vector ** slit_func_vec ;
1162 hdrl_image * model_master;
1163 cpl_table * slit_func_tab ;
1164 cpl_table * extract_tab ;
1165 hdrl_image * model_tmp ;
1167 cpl_vector * ndits ;
1169 double * qc_order_pos ;
1171 double qc_mean, qc_median, qc_flux, qc_rms, qc_s2n,
1172 qc_trace_centery, dit,
1173 gain, error_factor, bl_tot ;
1174 int i, ext_nr, nb_traces,
1175 nb_orders, qc_nbbad, nbvals, ngood, bl_good ;
1178 int extract_niter = 10;
1179 double extract_kappa = 10;
1182 if (rawframes == NULL)
return -1 ;
1183 if (extr_method != CR2RES_EXTR_OPT_CURV &&
1184 extr_method != CR2RES_EXTR_SUM) {
1185 cpl_msg_error(__func__,
"Failed to read the dits") ;
1190 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
1191 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
1192 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
1194 cpl_msg_error(__func__,
"Failed to get the Gain value") ;
1199 first_file = cpl_frame_get_filename(
1200 cpl_frameset_get_position_const(rawframes, 0)) ;
1204 cpl_msg_error(__func__,
"Failed to read the dits") ;
1212 if (imlist == NULL) {
1213 cpl_msg_error(__func__,
"Failed to load the images") ;
1214 cpl_vector_delete(dits) ;
1215 cpl_vector_delete(ndits) ;
1220 error_factor = gain * cpl_vector_get(ndits, 0) *
1221 cpl_frameset_get_size(rawframes) ;
1223 for (i=0; i<cpl_vector_get_size(ndits); i++){
1224 if (cpl_vector_get(ndits,i) != cpl_vector_get(ndits, 0))
1225 cpl_msg_warning(__func__,
"Raw frames have different NDIT! "
1226 "Error spectrum will likely be scaled incorrectly.");
1230 cpl_msg_info(__func__,
"Compute the traces") ;
1231 cpl_msg_indent_more() ;
1234 trace_smooth_x, trace_smooth_y, trace_threshold,
1235 trace_opening, trace_degree, trace_min_cluster)) == NULL) {
1236 cpl_msg_error(__func__,
"Failed compute the traces") ;
1237 cpl_vector_delete(dits) ;
1238 cpl_vector_delete(ndits) ;
1240 cpl_msg_indent_less() ;
1243 cpl_msg_indent_less() ;
1246 cpl_msg_info(__func__,
"Calibrate the input images") ;
1247 cpl_msg_indent_more() ;
1249 0, subtract_nolight_rows, 0, cosmics, NULL,
1250 master_dark_frame, bpm_frame, detlin_frame, dits, ndits))==NULL) {
1251 cpl_msg_error(__func__,
"Failed to Calibrate the Data") ;
1252 cpl_vector_delete(dits) ;
1253 cpl_vector_delete(ndits) ;
1255 cpl_table_delete(computed_traces) ;
1256 cpl_msg_indent_less() ;
1261 imlist = imlist_calibrated ;
1263 cpl_vector_delete(dits) ;
1264 cpl_vector_delete(ndits) ;
1265 cpl_msg_indent_less() ;
1268 cpl_msg_info(__func__,
"Collapse the input images") ;
1269 cpl_msg_indent_more() ;
1272 cpl_msg_error(__func__,
"Failed to Collapse") ;
1274 cpl_table_delete(computed_traces) ;
1275 cpl_msg_indent_less() ;
1279 cpl_image_delete(contrib) ;
1280 cpl_msg_indent_less() ;
1286 if (filter_traces) {
1289 cpl_msg_info(__func__,
"Filter out the traces") ;
1290 cpl_msg_indent_more() ;
1293 plist = cpl_propertylist_load(first_file, 0) ;
1295 zp_order = cr2res_pfits_get_order_zp(plist) ;
1296 cpl_propertylist_delete(plist) ;
1298 setting_id, zp_order) ;
1299 cpl_free(setting_id) ;
1300 cpl_table_delete(computed_traces) ;
1301 computed_traces = filtered_traces ;
1302 cpl_msg_indent_less() ;
1303 if (cpl_table_get_nrow(computed_traces) == 0) {
1304 cpl_msg_error(__func__,
"All traces are filtered out") ;
1306 cpl_table_delete(computed_traces) ;
1307 cpl_msg_indent_less() ;
1316 if (traces == NULL) {
1317 cpl_msg_error(__func__,
"Cannot Load the provided TW file") ;
1319 cpl_table_delete(computed_traces) ;
1323 traces = cpl_table_duplicate(computed_traces) ;
1325 cpl_table_delete(computed_traces) ;
1328 nb_traces = cpl_table_get_nrow(traces) ;
1329 spectrum = cpl_malloc(nb_traces *
sizeof(cpl_bivector *)) ;
1330 slit_func_vec = cpl_malloc(nb_traces *
sizeof(cpl_vector *)) ;
1331 model_master =
hdrl_image_new(CR2RES_DETECTOR_SIZE, CR2RES_DETECTOR_SIZE) ;
1335 cpl_msg_info(__func__,
"Extract the traces") ;
1336 cpl_msg_indent_more() ;
1337 for (i=0 ; i<nb_traces ; i++) {
1338 int order, trace_id;
1340 slit_func_vec[i] = NULL ;
1341 spectrum[i] = NULL ;
1345 order = cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL) ;
1346 trace_id = cpl_table_get(traces, CR2RES_COL_TRACENB, i, NULL) ;
1349 if (reduce_order > -1 && order != reduce_order) continue ;
1352 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1354 cpl_msg_info(__func__,
"Process Order %d/Trace %d", order, trace_id) ;
1355 cpl_msg_indent_more() ;
1358 if (extr_method == CR2RES_EXTR_SUM) {
1360 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1362 cpl_msg_error(__func__,
"Cannot (sum-)extract the trace") ;
1363 slit_func_vec[i] = NULL ;
1364 spectrum[i] = NULL ;
1367 cpl_msg_indent_less() ;
1370 }
else if (extr_method == CR2RES_EXTR_MEDIAN) {
1372 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1374 cpl_msg_error(__func__,
"Cannot (median-)extract the trace") ;
1375 slit_func_vec[i] = NULL ;
1376 spectrum[i] = NULL ;
1379 cpl_msg_indent_less() ;
1382 }
else if (extr_method == CR2RES_EXTR_TILTSUM) {
1384 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1386 cpl_msg_error(__func__,
"Cannot (tiltsum-)extract the trace") ;
1387 slit_func_vec[i] = NULL ;
1388 spectrum[i] = NULL ;
1391 cpl_msg_indent_less() ;
1394 }
else if (extr_method == CR2RES_EXTR_OPT_CURV) {
1396 trace_id, extract_height, extract_swath_width,
1397 extract_oversample, extract_smooth_slit,
1398 extract_smooth_spec, extract_niter, extract_kappa,
1400 &(slit_func_vec[i]), &(spectrum[i]), &model_tmp) != 0) {
1401 cpl_msg_error(__func__,
"Cannot (slitdec-) extract the trace") ;
1402 slit_func_vec[i] = NULL ;
1403 spectrum[i] = NULL ;
1406 cpl_msg_indent_less() ;
1412 if (model_tmp != NULL) {
1416 cpl_msg_indent_less() ;
1418 cpl_msg_indent_less() ;
1427 for (i=0 ; i<nb_traces ; i++) {
1428 if (slit_func_vec[i] != NULL) cpl_vector_delete(slit_func_vec[i]) ;
1429 if (spectrum[i] != NULL) cpl_bivector_delete(spectrum[i]) ;
1431 cpl_free(spectrum) ;
1432 cpl_free(slit_func_vec) ;
1435 cpl_msg_info(__func__,
"Compute the master flat") ;
1436 cpl_msg_indent_more() ;
1438 model_master, bpm_low, bpm_high, bpm_linemax,
1439 &bpm_flat)) == NULL) {
1440 cpl_msg_error(__func__,
"Failed compute the Master Flat") ;
1441 cpl_table_delete(slit_func_tab) ;
1442 cpl_table_delete(traces) ;
1443 cpl_table_delete(extract_tab) ;
1446 cpl_msg_indent_less() ;
1449 cpl_msg_indent_less() ;
1454 if (bpm_frame != NULL) {
1456 cpl_frame_get_filename(bpm_frame),
1457 reduce_det, 1)) == NULL) {
1458 cpl_msg_warning(__func__,
"Failed to Load the Master BPM") ;
1461 if (bpm_im == NULL) {
1462 bpm_im = cpl_image_duplicate(bpm_flat) ;
1464 if (cpl_image_or(bpm_im, NULL, bpm_flat)) {
1465 cpl_msg_error(__func__,
"Failed to add the mask to the BPM") ;
1466 cpl_table_delete(traces) ;
1467 cpl_table_delete(slit_func_tab) ;
1468 cpl_table_delete(extract_tab) ;
1471 cpl_image_delete(bpm_im) ;
1472 cpl_image_delete(bpm_flat) ;
1473 cpl_msg_indent_less() ;
1477 cpl_image_delete(bpm_flat) ;
1490 plist = cpl_propertylist_load(first_file, 0) ;
1492 cpl_propertylist_delete(plist) ;
1493 qc_flux = qc_mean / dit ;
1496 cpl_image_reject_from_mask(my_master_flat, bpm_mask) ;
1497 ngood = CR2RES_DETECTOR_SIZE* CR2RES_DETECTOR_SIZE -
1498 cpl_mask_count(bpm_mask) ;
1499 cpl_mask_delete(bpm_mask);
1500 qc_rms = sqrt(cpl_image_get_sqflux(my_master_flat) / ngood) ;
1501 cpl_image_delete(my_master_flat) ;
1513 plist = cpl_propertylist_load(first_file, ext_nr) ;
1514 if (plist == NULL) {
1516 cpl_table_delete(traces) ;
1517 cpl_table_delete(slit_func_tab) ;
1518 cpl_table_delete(extract_tab) ;
1521 cpl_image_delete(bpm_im) ;
1522 cpl_msg_error(__func__,
"Failed to load the plist") ;
1531 for (i=0 ; i<nb_orders ; i++) {
1532 double qc_overexposed;
1535 char * qc_name = cpl_sprintf(
"%s%02d",
1536 CR2RES_HEADER_QC_OVEREXPOSED, orders[i]) ;
1537 cpl_propertylist_append_double(plist, qc_name, qc_overexposed);
1544 if (qc_order_nb != NULL && qc_order_pos != NULL) {
1545 for (i=0 ; i<nbvals ; i++) {
1546 char * qc_name = cpl_sprintf(
"%s%02d",
1547 CR2RES_HEADER_QC_FLAT_ORDERPOS, qc_order_nb[i]) ;
1548 cpl_propertylist_append_double(plist, qc_name, qc_order_pos[i]);
1552 if (qc_order_nb != NULL) cpl_free(qc_order_nb) ;
1553 if (qc_order_pos != NULL) cpl_free(qc_order_pos) ;
1555 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEAN,
1557 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEDIAN,
1559 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_FLUX,
1561 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_RMS,
1563 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_S2N,
1565 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_CENTERY,
1567 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_FLAT_NBBAD,
1569 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_BLAZE_NGOOD,
1571 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_BLAZE_TOT,
1575 *trace_wave = traces ;
1576 *slit_func = slit_func_tab ;
1577 *extract_1d = extract_tab ;
1578 *slit_model = model_master ;
1579 *master_flat = master_flat_loc ;
1580 *ext_plist = plist ;
1593static int cr2res_cal_flat_compare(
1594 const cpl_frame * frame1,
1595 const cpl_frame * frame2)
1598 cpl_propertylist * plist1 ;
1599 cpl_propertylist * plist2 ;
1600 const char * sval1 ;
1601 const char * sval2 ;
1604 if (frame1==NULL || frame2==NULL)
return -1 ;
1607 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1608 cpl_msg_error(__func__,
"getting header from reference frame");
1611 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1612 cpl_msg_error(__func__,
"getting header from reference frame");
1613 cpl_propertylist_delete(plist1) ;
1618 if (cpl_error_get_code()) {
1619 cpl_propertylist_delete(plist1) ;
1620 cpl_propertylist_delete(plist2) ;
1629 if (cpl_error_get_code()) {
1630 cpl_msg_error(__func__,
"Cannot get the reference wavelength");
1631 cpl_propertylist_delete(plist1) ;
1632 cpl_propertylist_delete(plist2) ;
1635 if (strcmp(sval1, sval2)) comparison = 0 ;
1637 cpl_propertylist_delete(plist1) ;
1638 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.