CR2RE Pipeline Reference Manual 1.6.8
cr2res_cal_flat.c
1/*
2 * This file is part of the CR2RES Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include <string.h>
29#include <cpl.h>
30
31#include "cr2res_utils.h"
32#include "cr2res_calib.h"
33#include "cr2res_pfits.h"
34#include "cr2res_dfs.h"
35#include "cr2res_qc.h"
36#include "cr2res_flat.h"
37#include "cr2res_bpm.h"
38#include "cr2res_trace.h"
39#include "cr2res_extract.h"
40#include "cr2res_io.h"
41
42/*-----------------------------------------------------------------------------
43 Define
44 -----------------------------------------------------------------------------*/
45
46#define RECIPE_STRING "cr2res_cal_flat"
47
48/*-----------------------------------------------------------------------------
49 Plugin registration
50 -----------------------------------------------------------------------------*/
51
52int cpl_plugin_get_info(cpl_pluginlist * list);
53
54/*-----------------------------------------------------------------------------
55 Private function prototypes
56 -----------------------------------------------------------------------------*/
57
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,
67 int filter_traces,
68 int subtract_nolight_rows,
69 int cosmics,
70 double bpm_low,
71 double bpm_high,
72 double bpm_linemax,
73 int trace_degree,
74 int trace_min_cluster,
75 int trace_smooth_x,
76 int trace_smooth_y,
77 double trace_threshold,
78 int trace_opening,
79 cr2res_extr_method extr_method,
80 int extract_oversample,
81 int extract_swath_width,
82 int extract_height,
83 double extract_smooth_slit,
84 double extract_smooth_spec,
85 int reduce_det,
86 int reduce_order,
87 int reduce_trace,
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,
93 cpl_image ** bpm,
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 *);
99
100/*-----------------------------------------------------------------------------
101 Static variables
102 -----------------------------------------------------------------------------*/
103
104static char cr2res_cal_flat_description[] = "\
105Flat \n\
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\
111 \n\
112 Inputs \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\
127 \n\
128 Outputs \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\
143 \n\
144 Algorithm \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\
156 Save bpm(g,p) \n\
157 Merge the trace_wave(g,p,d) into trace_wave(g,d) \n\
158 Save trace_wave(g) \n\
159 \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\
166 on avg \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\
178 Compute QCs \n\
179 store the qc parameters in the returned property list \n\
180 \n\
181 Library functions used: \n\
182 cr2res_io_extract_decker_frameset() \n\
183 cr2res_trace() \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\
199";
200
201/*-----------------------------------------------------------------------------
202 Function code
203 -----------------------------------------------------------------------------*/
204
205/*----------------------------------------------------------------------------*/
215/*----------------------------------------------------------------------------*/
216int cpl_plugin_get_info(cpl_pluginlist * list)
217{
218 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
219 cpl_plugin * plugin = &recipe->interface;
220
221 if (cpl_plugin_init(plugin,
222 CPL_PLUGIN_API,
223 CR2RES_BINARY_VERSION,
224 CPL_PLUGIN_TYPE_RECIPE,
225 RECIPE_STRING,
226 "Flat recipe",
227 cr2res_cal_flat_description,
228 CR2RES_PIPELINE_AUTHORS,
229 PACKAGE_BUGREPORT,
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);
236 return 1;
237 }
238
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);
242 return 1;
243 }
244
245 return 0;
246}
247
248/*----------------------------------------------------------------------------*/
256/*----------------------------------------------------------------------------*/
257static int cr2res_cal_flat_create(cpl_plugin * plugin)
258{
259 cpl_recipe * recipe ;
260 cpl_parameter * p ;
261
262 /* Check that the plugin is part of a valid recipe */
263 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
264 recipe = (cpl_recipe *)plugin;
265 else
266 return -1;
267
268 /* Create the parameters list in the cpl_recipe object */
269 recipe->parameters = cpl_parameterlist_new();
270
271 /* Fill the parameters list */
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);
278
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);
285
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);
292
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);
299
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);
306
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);
313
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);
320
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);
327
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);
334
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);
341
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);
348
349 /*
350 p = cpl_parameter_new_value("cr2res.cr2res_cal_flat.trace_filter",
351 CPL_TYPE_BOOL, "Only keep the predefined order traces",
352 "cr2res.cr2res_cal_flat", TRUE);
353 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_filter");
354 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
355 cpl_parameterlist_append(recipe->parameters, p);
356 */
357
358 p = cpl_parameter_new_value("cr2res.cr2res_cal_flat.extract_method",
359 CPL_TYPE_STRING, "Extraction method (SUM / MEDIAN / TILTSUM / "
360 "OPT_CURV )",
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);
365
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);
372
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);
378
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);
385
386 p = cpl_parameter_new_value("cr2res.cr2res_cal_flat.extract_smooth_slit",
387 CPL_TYPE_DOUBLE,
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);
393
394 p = cpl_parameter_new_value("cr2res.cr2res_cal_flat.extract_smooth_spec",
395 CPL_TYPE_DOUBLE,
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);
401
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);
408
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);
415
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);
422
423 return 0;
424}
425
426/*----------------------------------------------------------------------------*/
432/*----------------------------------------------------------------------------*/
433static int cr2res_cal_flat_exec(cpl_plugin * plugin)
434{
435 cpl_recipe *recipe;
436
437 /* Get the recipe out of the plugin */
438 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
439 recipe = (cpl_recipe *)plugin;
440 else return -1;
441
442 return cr2res_cal_flat(recipe->frames, recipe->parameters);
443}
444
445/*----------------------------------------------------------------------------*/
451/*----------------------------------------------------------------------------*/
452static int cr2res_cal_flat_destroy(cpl_plugin * plugin)
453{
454 cpl_recipe *recipe;
455
456 /* Get the recipe out of the plugin */
457 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
458 recipe = (cpl_recipe *)plugin;
459 else return -1 ;
460
461 cpl_parameterlist_delete(recipe->parameters);
462 return 0 ;
463}
464
465/*----------------------------------------------------------------------------*/
472/*----------------------------------------------------------------------------*/
473static int cr2res_cal_flat(
474 cpl_frameset * frameset,
475 const cpl_parameterlist * parlist)
476{
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;
488 const char * sval ;
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 ;
496 cpl_size * labels ;
497 cpl_size nlabels ;
498 cpl_propertylist * qc_main ;
499
500 hdrl_image * master_flat[CR2RES_NB_DETECTORS] ;
501 cpl_table * trace_wave[CR2RES_NB_DECKER_POSITIONS][CR2RES_NB_DETECTORS] ;
502 cpl_propertylist *
503 ext_plist[CR2RES_NB_DECKER_POSITIONS][CR2RES_NB_DETECTORS] ;
504 cpl_table * trace_wave_merged[CR2RES_NB_DETECTORS];
505 cpl_table * merged ;
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] ;
512 char * qc_name;
513 char * out_file;
514 int * orders ;
515 cpl_vector * qc_mean,
516 * qc_median,
517 * qc_flux,
518 * qc_rms,
519 * qc_s2n,
520 * qc_nbbad,
521 * qc_centery,
522 * qc_bltot,
523 * qc_blgood,
524 * qc_orderpos,
525 * qc_overexposed ;
526 int l, i, j, det_nr, nb_orders;
527
528 /* Initialise */
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"} ;
533
534 /* RETRIEVE INPUT PARAMETERS */
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);
568 /*
569 param = cpl_parameterlist_find_const(parlist,
570 "cr2res.cr2res_cal_flat.trace_filter");
571 trace_filter = cpl_parameter_get_bool(param);
572 */
573 trace_filter = 0 ;
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;
582 else {
583 cpl_msg_error(__func__, "Invalid Extraction Method specified");
584 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
585 return -1;
586 }
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);
611
612 /* Identify the RAW and CALIB frames in the input frameset */
613 if (cr2res_dfs_set_groups(frameset)) {
614 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
615 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
616 return -1 ;
617 }
618
619 /* Get Calibration frames */
620 trace_wave_frame = cr2res_io_find_TRACE_WAVE(frameset) ;
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) ;
625 bpm_frame = cr2res_io_find_BPM(frameset) ;
626
627 /* Extract RAW frames */
628 used_tag = CR2RES_FLAT_RAW ;
629 rawframes = cr2res_extract_frameset(frameset, used_tag) ;
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) ;
633 return -1 ;
634 }
635
636 /* Label the raw frames with the different settings */
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) ;
642 return -1 ;
643 }
644
645 /* Loop on the settings */
646 for (l = 0; l < (int)nlabels; l++) {
647 cpl_frameset *raw_one_setting;
648 cpl_propertylist *plist;
649 char *setting_id;
650 /* Get the frames for the current setting */
651 raw_one_setting = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
652
653 /* Get the current setting */
654 plist = cpl_propertylist_load(cpl_frame_get_filename(
655 cpl_frameset_get_position(raw_one_setting, 0)), 0) ;
656 setting_id = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
657 cr2res_format_setting(setting_id) ;
658 cpl_propertylist_delete(plist) ;
659
660 cpl_msg_info(__func__, "Process SETTING %s", setting_id) ;
661 cpl_msg_indent_more() ;
662
663 /* Loop on the decker positions */
664 for (i=0 ; i<CR2RES_NB_DECKER_POSITIONS ; i++) {
665 /* Initialise */
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 ;
669 }
670
671 /* Get the Frames for the current decker position */
672 raw_one_setting_decker = cr2res_io_extract_decker_frameset(
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",
676 decker_desc[i]) ;
677 continue ;
678 }
679 cpl_msg_info(__func__, "Reduce %s Frames", decker_desc[i]) ;
680 cpl_msg_indent_more() ;
681
682 /* Loop on the detectors */
683 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
684 /* Initialise */
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 ;
690
691 /* Compute only one detector */
692 if (reduce_det != 0 && det_nr != reduce_det) continue ;
693
694 cpl_msg_info(__func__, "Process Detector %d", det_nr) ;
695 cpl_msg_indent_more() ;
696
697 /* Call the reduction function */
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]),
713 &(bpm[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]);
718 cpl_error_reset() ;
719 }
720 cpl_msg_indent_less() ;
721 }
722
723
724 /* Compute QCs for the main header */
725 qc_main = NULL ;
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)) ;
764 }
765
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) ;
821
822 if (trace_wave[i][0] != NULL) {
823 /* Special treatment for ORDERPOSn and OVEREXPOSEDn */
824 /* Get all orders - Use the TW from detector 1 */
826 trace_wave[i][0], &nb_orders) ;
827 /* Loop on the 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++){
832 // OVEREXPOSEDn
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)) ;
838 cpl_free(qc_name) ;
839 // ORDERPOSn
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)) ;
845 cpl_free(qc_name) ;
846 }
847
848 // OVEREXPOSEDn.AVG/RMS
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)) ;
853 cpl_free(qc_name) ;
854
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)) ;
859 cpl_free(qc_name) ;
860 cpl_vector_delete(qc_overexposed) ;
861
862 // ORDERPOSn.AVG/RMS
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)) ;
867 cpl_free(qc_name) ;
868
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)) ;
873 cpl_free(qc_name) ;
874 cpl_vector_delete(qc_orderpos) ;
875 }
876 cpl_free(orders) ;
877 }
878 }
879
880 /* Save Products */
881
882 /* Save only the used RAW ? : raw_one_... instead of 2nd frameset */
883 /* Beware that the calibration PRO RECi CAL will be missing */
884
885 /* MASTER_FLAT */
886 if (nlabels == 1) {
887 out_file = cpl_sprintf("%s_%s_master_flat.fits",
888 RECIPE_STRING, decker_desc[i]) ;
889 } else {
890 out_file = cpl_sprintf("%s_%s_%s_master_flat.fits",
891 RECIPE_STRING, setting_id, decker_desc[i]) ;
892 }
893 cr2res_io_save_MASTER_FLAT(out_file, frameset,
894 frameset, parlist, master_flat, qc_main,
895 ext_plist[i], CR2RES_CAL_FLAT_MASTER_PROCATG,
896 RECIPE_STRING);
897 cpl_free(out_file);
898
899 /* SLIT_MODEL */
900 if (nlabels == 1) {
901 out_file = cpl_sprintf("%s_%s_slit_model.fits",
902 RECIPE_STRING, decker_desc[i]) ;
903 } else {
904 out_file = cpl_sprintf("%s_%s_%s_slit_model.fits",
905 RECIPE_STRING, setting_id, decker_desc[i]) ;
906 }
907 cr2res_io_save_SLIT_MODEL(out_file, frameset,
908 frameset, parlist, slit_model, qc_main,
909 ext_plist[i], CR2RES_CAL_FLAT_SLIT_MODEL_PROCATG,
910 RECIPE_STRING);
911 cpl_free(out_file);
912
913 /* BLAZE */
914 if (nlabels == 1) {
915 out_file = cpl_sprintf("%s_%s_blaze.fits",
916 RECIPE_STRING, decker_desc[i]) ;
917 } else {
918 out_file = cpl_sprintf("%s_%s_%s_blaze.fits",
919 RECIPE_STRING, setting_id, decker_desc[i]) ;
920 }
921 cr2res_io_save_EXTRACT_1D(out_file, frameset,
922 frameset, parlist, extract_1d, qc_main,
923 ext_plist[i], CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG,
924 RECIPE_STRING);
925 cpl_free(out_file);
926
927 /* TRACE_WAVE */
928 if (nlabels == 1) {
929 out_file = cpl_sprintf("%s_%s_tw.fits",
930 RECIPE_STRING, decker_desc[i]) ;
931 } else {
932 out_file = cpl_sprintf("%s_%s_%s_tw.fits",
933 RECIPE_STRING, setting_id, decker_desc[i]) ;
934 }
935 cr2res_io_save_TRACE_WAVE(out_file, frameset,
936 frameset, parlist, trace_wave[i], qc_main,
937 ext_plist[i], CR2RES_CAL_FLAT_TW_PROCATG, RECIPE_STRING);
938 cpl_free(out_file);
939
940 /* SLIT_FUNC */
941 if (nlabels == 1) {
942 out_file = cpl_sprintf("%s_%s_slit_func.fits",
943 RECIPE_STRING, decker_desc[i]) ;
944 } else {
945 out_file = cpl_sprintf("%s_%s_%s_slit_func.fits",
946 RECIPE_STRING, setting_id, decker_desc[i]) ;
947 }
948 cr2res_io_save_SLIT_FUNC(out_file, frameset,
949 frameset, parlist, slit_func, qc_main,
950 ext_plist[i], CR2RES_CAL_FLAT_SLIT_FUNC_PROCATG,
951 RECIPE_STRING);
952 cpl_free(out_file);
953
954 /* BPM */
955 if (nlabels == 1) {
956 out_file = cpl_sprintf("%s_%s_bpm.fits",
957 RECIPE_STRING, decker_desc[i]) ;
958 } else {
959 out_file = cpl_sprintf("%s_%s_%s_bpm.fits",
960 RECIPE_STRING, setting_id, decker_desc[i]) ;
961 }
962 cr2res_io_save_BPM(out_file, frameset,
963 frameset, parlist, bpm, qc_main, ext_plist[i],
964 CR2RES_CAL_FLAT_BPM_PROCATG, RECIPE_STRING) ;
965 cpl_free(out_file);
966
967 /* Free */
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)
972 hdrl_image_delete(master_flat[det_nr-1]) ;
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)
978 hdrl_image_delete(slit_model[det_nr-1]) ;
979 if (bpm[det_nr-1] != NULL)
980 cpl_image_delete(bpm[det_nr-1]) ;
981 }
982 cpl_msg_indent_less() ;
983 }
984
985 /* Merge the Decker positions TRACE_WAVE files in a single one */
986 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
987 /* Initialise */
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]) ;
991 else
992 trace_wave_merged[det_nr-1] = NULL ;
993 /* Loop on the other detectors */
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) {
998 /* Do nothing - go to next iteration */
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) {
1004 /* Do nothing - go to next iteration */
1005 } else {
1006 merged = cr2res_trace_merge(trace_wave1, trace_wave2) ;
1007 if (merged == NULL) {
1008 cpl_msg_error(__func__, "Failed merging") ;
1009 } else {
1010 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1011 trace_wave_merged[det_nr-1] = merged ;
1012 }
1013 }
1014 }
1015 }
1016
1017 /* Free the traces */
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]) ;
1022
1023
1024 /* Save TRACE_WAVE_MERGED */
1025 if (nlabels == 1) {
1026 out_file = cpl_sprintf("%s_tw_merged.fits",
1027 RECIPE_STRING) ;
1028 } else {
1029 out_file = cpl_sprintf("%s_%s_tw_merged.fits", RECIPE_STRING,
1030 setting_id) ;
1031 }
1032
1033 /* Save only the used RAW ? : raw_one_... instead of 2nd frameset */
1034 /* Beware that the calibration PRO RECi CAL will be missing */
1035
1036 cr2res_io_save_TRACE_WAVE(out_file, frameset, frameset, parlist,
1037 trace_wave_merged, NULL, ext_plist[0],
1038 CR2RES_CAL_FLAT_TW_MERGED_PROCATG, RECIPE_STRING) ;
1039 cpl_free(out_file);
1040 cpl_free(setting_id) ;
1041
1042 /* Free extensions */
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]) ;
1047
1048 /* Free the merged traces */
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]) ;
1052
1053 cpl_frameset_delete(raw_one_setting) ;
1054 cpl_msg_indent_less() ;
1055 }
1056 cpl_free(labels);
1057 cpl_frameset_delete(rawframes) ;
1058
1059 return (int)cpl_error_get_code();
1060}
1061
1062/*----------------------------------------------------------------------------*/
1100/*----------------------------------------------------------------------------*/
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,
1107 int filter_traces,
1108 int subtract_nolight_rows,
1109 int cosmics,
1110 double bpm_low,
1111 double bpm_high,
1112 double bpm_linemax,
1113 int trace_degree,
1114 int trace_min_cluster,
1115 int trace_smooth_x,
1116 int trace_smooth_y,
1117 double trace_threshold,
1118 int trace_opening,
1119 cr2res_extr_method extr_method,
1120 int extract_oversample,
1121 int extract_swath_width,
1122 int extract_height,
1123 double extract_smooth_slit,
1124 double extract_smooth_spec,
1125 int reduce_det,
1126 int reduce_order,
1127 int reduce_trace,
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,
1133 cpl_image ** bpm,
1134 cpl_propertylist ** ext_plist)
1135{
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 ;
1157 cpl_vector * dits ;
1158 cpl_vector * ndits ;
1159 int * qc_order_nb ;
1160 double * qc_order_pos ;
1161 int * orders ;
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 ;
1167
1168 /* TODO, make parameters */
1169 int extract_niter = 10;
1170 double extract_kappa = 10;
1171
1172 /* Check Inputs */
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") ;
1177 return -1 ;
1178 }
1179
1180 /* Get the Gain */
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 ;
1184 else {
1185 cpl_msg_error(__func__, "Failed to get the Gain value") ;
1186 return -1 ;
1187 }
1188
1189 /* Get the First RAW file */
1190 first_file = cpl_frame_get_filename(
1191 cpl_frameset_get_position_const(rawframes, 0)) ;
1192
1193 /* Get the DIT for the Dark correction */
1194 if ((dits = cr2res_io_read_dits(rawframes)) == NULL) {
1195 cpl_msg_error(__func__, "Failed to read the dits") ;
1196 return -1 ;
1197 }
1198 /*Load the NDITs */
1199 ndits = cr2res_io_read_ndits(rawframes);
1200
1201 /* Load the image list */
1202 imlist = cr2res_io_load_image_list_from_set(rawframes, reduce_det) ;
1203 if (imlist == NULL) {
1204 cpl_msg_error(__func__, "Failed to load the images") ;
1205 cpl_vector_delete(dits) ;
1206 cpl_vector_delete(ndits) ;
1207 return -1 ;
1208 }
1209
1210 /* Set the error factor. */
1211 error_factor = gain * cpl_vector_get(ndits, 0) *
1212 cpl_frameset_get_size(rawframes) ;
1213
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.");
1218 }
1219
1220 /* Compute traces */
1221 cpl_msg_info(__func__, "Compute the traces") ;
1222 cpl_msg_indent_more() ;
1223 if ((computed_traces = cr2res_trace(
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) ;
1230 hdrl_imagelist_delete(imlist) ;
1231 cpl_msg_indent_less() ;
1232 return -1 ;
1233 }
1234 cpl_msg_indent_less() ;
1235
1236 /* Calibrate the Data */
1237 cpl_msg_info(__func__, "Calibrate the input images") ;
1238 cpl_msg_indent_more() ;
1239 if ((imlist_calibrated = cr2res_calib_imagelist(imlist, reduce_det,
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) ;
1245 hdrl_imagelist_delete(imlist) ;
1246 cpl_table_delete(computed_traces) ;
1247 cpl_msg_indent_less() ;
1248 return -1 ;
1249 } else {
1250 /* Replace the calibrated image in the list */
1251 hdrl_imagelist_delete(imlist) ;
1252 imlist = imlist_calibrated ;
1253 }
1254 cpl_vector_delete(dits) ;
1255 cpl_vector_delete(ndits) ;
1256 cpl_msg_indent_less() ;
1257
1258 /* Collapse */
1259 cpl_msg_info(__func__, "Collapse the input images") ;
1260 cpl_msg_indent_more() ;
1261 if (hdrl_imagelist_collapse_mean(imlist, &collapsed, &contrib) !=
1262 CPL_ERROR_NONE) {
1263 cpl_msg_error(__func__, "Failed to Collapse") ;
1264 hdrl_imagelist_delete(imlist) ;
1265 cpl_table_delete(computed_traces) ;
1266 cpl_msg_indent_less() ;
1267 return -1 ;
1268 }
1269 hdrl_imagelist_delete(imlist) ;
1270 cpl_image_delete(contrib) ;
1271 cpl_msg_indent_less() ;
1272
1273 /* Add The remaining Columns to the trace table */
1274 cr2res_trace_add_extra_columns(computed_traces, first_file, reduce_det) ;
1275
1276 /* Filter out traces */
1277 if (filter_traces) {
1278 char *setting_id;
1279 int zp_order;
1280 cpl_msg_info(__func__, "Filter out the traces") ;
1281 cpl_msg_indent_more() ;
1282
1283 /* Get the setting and the zp_order */
1284 plist = cpl_propertylist_load(first_file, 0) ;
1285 setting_id = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
1286 zp_order = cr2res_pfits_get_order_zp(plist) ;
1287 cpl_propertylist_delete(plist) ;
1288 filtered_traces = cr2res_trace_filter(computed_traces,
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") ;
1296 hdrl_image_delete(collapsed) ;
1297 cpl_table_delete(computed_traces) ;
1298 cpl_msg_indent_less() ;
1299 return -1 ;
1300 }
1301 }
1302
1303 /* Use the input traces for extraction if they are provided */
1304 if (tw_frame) {
1305 traces = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(tw_frame),
1306 reduce_det) ;
1307 if (traces == NULL) {
1308 cpl_msg_error(__func__, "Cannot Load the provided TW file") ;
1309 hdrl_image_delete(collapsed) ;
1310 cpl_table_delete(computed_traces) ;
1311 return -1 ;
1312 }
1313 } else {
1314 traces = cpl_table_duplicate(computed_traces) ;
1315 }
1316 cpl_table_delete(computed_traces) ;
1317
1318 /* Extract */
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) ;
1323 hdrl_image_mul_scalar(model_master, (hdrl_value){0.0, 0.0}) ;
1324
1325 /* Loop over the traces and extract them */
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;
1330 /* Initialise */
1331 slit_func_vec[i] = NULL ;
1332 spectrum[i] = NULL ;
1333 model_tmp = NULL ;
1334
1335 /* Get Order and trace id */
1336 order = cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL) ;
1337 trace_id = cpl_table_get(traces, CR2RES_COL_TRACENB, i, NULL) ;
1338
1339 /* Check if this order needs to be skipped */
1340 if (reduce_order > -1 && order != reduce_order) continue ;
1341
1342 /* Check if this trace needs to be skipped */
1343 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1344
1345 cpl_msg_info(__func__, "Process Order %d/Trace %d", order, trace_id) ;
1346 cpl_msg_indent_more() ;
1347
1348 /* Call the Extraction */
1349 if (extr_method == CR2RES_EXTR_SUM) {
1350 if (cr2res_extract_sum_vert(collapsed, traces, order, trace_id,
1351 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1352 &model_tmp) != 0) {
1353 cpl_msg_error(__func__, "Cannot (sum-)extract the trace") ;
1354 slit_func_vec[i] = NULL ;
1355 spectrum[i] = NULL ;
1356 model_tmp = NULL ;
1357 cpl_error_reset() ;
1358 cpl_msg_indent_less() ;
1359 continue ;
1360 }
1361 } else if (extr_method == CR2RES_EXTR_MEDIAN) {
1362 if (cr2res_extract_median(collapsed, traces, order, trace_id,
1363 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1364 &model_tmp) != 0) {
1365 cpl_msg_error(__func__, "Cannot (median-)extract the trace") ;
1366 slit_func_vec[i] = NULL ;
1367 spectrum[i] = NULL ;
1368 model_tmp = NULL ;
1369 cpl_error_reset() ;
1370 cpl_msg_indent_less() ;
1371 continue ;
1372 }
1373 } else if (extr_method == CR2RES_EXTR_TILTSUM) {
1374 if (cr2res_extract_sum_tilt(collapsed, traces, order, trace_id,
1375 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1376 &model_tmp) != 0) {
1377 cpl_msg_error(__func__, "Cannot (tiltsum-)extract the trace") ;
1378 slit_func_vec[i] = NULL ;
1379 spectrum[i] = NULL ;
1380 model_tmp = NULL ;
1381 cpl_error_reset() ;
1382 cpl_msg_indent_less() ;
1383 continue ;
1384 }
1385 } else if (extr_method == CR2RES_EXTR_OPT_CURV) {
1386 if (cr2res_extract_slitdec_curved(collapsed, traces, NULL,order,
1387 trace_id, extract_height, extract_swath_width,
1388 extract_oversample, extract_smooth_slit,
1389 extract_smooth_spec, extract_niter, extract_kappa,
1390 error_factor,
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 ;
1395 model_tmp = NULL ;
1396 cpl_error_reset() ;
1397 cpl_msg_indent_less() ;
1398 continue ;
1399 }
1400 }
1401
1402 /* Update the model global image */
1403 if (model_tmp != NULL) {
1404 hdrl_image_add_image(model_master, model_tmp) ;
1405 hdrl_image_delete(model_tmp) ;
1406 }
1407 cpl_msg_indent_less() ;
1408 }
1409 cpl_msg_indent_less() ;
1410
1411 /* Create the slit_func_tab for the current detector */
1412 slit_func_tab = cr2res_extract_SLITFUNC_create(slit_func_vec, traces) ;
1413
1414 /* Create the extracted_tab for the current detector */
1415 extract_tab = cr2res_extract_EXTRACT1D_create(spectrum, traces) ;
1416
1417 /* Deallocate Vectors */
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]) ;
1421 }
1422 cpl_free(spectrum) ;
1423 cpl_free(slit_func_vec) ;
1424
1425 /* Compute the Master flat */
1426 cpl_msg_info(__func__, "Compute the master flat") ;
1427 cpl_msg_indent_more() ;
1428 if ((master_flat_loc = cr2res_master_flat(collapsed,
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) ;
1435 hdrl_image_delete(model_master) ;
1436 hdrl_image_delete(collapsed) ;
1437 cpl_msg_indent_less() ;
1438 return -1 ;
1439 }
1440 cpl_msg_indent_less() ;
1441 hdrl_image_delete(collapsed) ;
1442
1443 /* Create BPM image */
1444 bpm_im = NULL ;
1445 if (bpm_frame != NULL) {
1446 if ((bpm_im = cr2res_io_load_BPM(
1447 cpl_frame_get_filename(bpm_frame),
1448 reduce_det, 1)) == NULL) {
1449 cpl_msg_warning(__func__, "Failed to Load the Master BPM") ;
1450 }
1451 }
1452 if (bpm_im == NULL) {
1453 bpm_im = cpl_image_duplicate(bpm_flat) ;
1454 } else {
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) ;
1460 hdrl_image_delete(model_master) ;
1461 hdrl_image_delete(master_flat_loc) ;
1462 cpl_image_delete(bpm_im) ;
1463 cpl_image_delete(bpm_flat) ;
1464 cpl_msg_indent_less() ;
1465 return -1 ;
1466 }
1467 }
1468 cpl_image_delete(bpm_flat) ;
1469
1470 /* Compute the QC parameters */
1471
1472 /* Load the first RAW image */
1473 first_image = cr2res_io_load_image(first_file, reduce_det) ;
1474
1475 /* Set the BPM */
1476 bpm_mask = cr2res_bpm_extract_mask(bpm_im, CR2RES_BPM_ALL) ;
1477
1478 cpl_image_reject_from_mask(hdrl_image_get_image(first_image), bpm_mask) ;
1479 qc_mean = cpl_image_get_mean(hdrl_image_get_image(first_image)) ;
1480 qc_median = cpl_image_get_median(hdrl_image_get_image(first_image)) ;
1481 plist = cpl_propertylist_load(first_file, 0) ;
1482 dit = cr2res_pfits_get_dit(plist) ;
1483 cpl_propertylist_delete(plist) ;
1484 qc_flux = qc_mean / dit ;
1485
1486 my_master_flat = cpl_image_duplicate(hdrl_image_get_image(master_flat_loc));
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) ;
1493
1494 qc_s2n = cr2res_qc_flat_s2n(extract_tab) ;
1495
1496 cr2res_util_blaze_stat(extract_tab, &bl_good, &bl_tot);
1497
1498 qc_trace_centery = cr2res_qc_flat_trace_center_y(traces) ;
1499 qc_nbbad = cr2res_bpm_count(bpm_im, CR2RES_BPM_FLAT) ;
1500 cr2res_qc_flat_order_positions(traces, &qc_order_nb, &qc_order_pos,&nbvals);
1501
1502 /* Load the extension header for saving */
1503 ext_nr = cr2res_io_get_ext_idx(first_file, reduce_det, 1) ;
1504 plist = cpl_propertylist_load(first_file, ext_nr) ;
1505 if (plist == NULL) {
1506 hdrl_image_delete(first_image) ;
1507 cpl_table_delete(traces) ;
1508 cpl_table_delete(slit_func_tab) ;
1509 cpl_table_delete(extract_tab) ;
1510 hdrl_image_delete(model_master) ;
1511 hdrl_image_delete(master_flat_loc) ;
1512 cpl_image_delete(bpm_im) ;
1513 cpl_msg_error(__func__, "Failed to load the plist") ;
1514 return -1 ;
1515 }
1516
1517 /* QC.OVEREXPOSED */
1518
1519 /* Get all orders */
1520 orders = cr2res_trace_get_order_idx_values(traces, &nb_orders) ;
1521 /* Loop on the orders */
1522 for (i=0 ; i<nb_orders ; i++) {
1523 double qc_overexposed;
1524 qc_overexposed = cr2res_qc_overexposed(
1525 hdrl_image_get_image(first_image), traces, orders[i]) ;
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);
1529 cpl_free(qc_name) ;
1530 }
1531 cpl_free(orders) ;
1532 hdrl_image_delete(first_image) ;
1533
1534 /* Store the QC parameters in the plist */
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]);
1540 cpl_free(qc_name) ;
1541 }
1542 }
1543 if (qc_order_nb != NULL) cpl_free(qc_order_nb) ;
1544 if (qc_order_pos != NULL) cpl_free(qc_order_pos) ;
1545
1546 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEAN,
1547 qc_mean) ;
1548 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEDIAN,
1549 qc_median);
1550 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_FLUX,
1551 qc_flux) ;
1552 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_RMS,
1553 qc_rms) ;
1554 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_S2N,
1555 qc_s2n) ;
1556 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_CENTERY,
1557 qc_trace_centery) ;
1558 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_FLAT_NBBAD,
1559 qc_nbbad) ;
1560 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_BLAZE_NGOOD,
1561 bl_good) ;
1562 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_BLAZE_TOT,
1563 bl_tot) ;
1564
1565 /* Return the results */
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 ;
1572 *bpm = bpm_im ;
1573 return 0 ;
1574}
1575
1576/*----------------------------------------------------------------------------*/
1583/*----------------------------------------------------------------------------*/
1584static int cr2res_cal_flat_compare(
1585 const cpl_frame * frame1,
1586 const cpl_frame * frame2)
1587{
1588 int comparison ;
1589 cpl_propertylist * plist1 ;
1590 cpl_propertylist * plist2 ;
1591 const char * sval1 ;
1592 const char * sval2 ;
1593
1594 /* Test entries */
1595 if (frame1==NULL || frame2==NULL) return -1 ;
1596
1597 /* Get property lists */
1598 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1599 cpl_msg_error(__func__, "getting header from reference frame");
1600 return -1 ;
1601 }
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) ;
1605 return -1 ;
1606 }
1607
1608 /* Test status */
1609 if (cpl_error_get_code()) {
1610 cpl_propertylist_delete(plist1) ;
1611 cpl_propertylist_delete(plist2) ;
1612 return -1 ;
1613 }
1614
1615 comparison = 1 ;
1616
1617 /* Compare the SETTING used */
1618 sval1 = cr2res_pfits_get_wlen_id(plist1) ;
1619 sval2 = cr2res_pfits_get_wlen_id(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) ;
1624 return -1 ;
1625 }
1626 if (strcmp(sval1, sval2)) comparison = 0 ;
1627
1628 cpl_propertylist_delete(plist1) ;
1629 cpl_propertylist_delete(plist2) ;
1630 return comparison ;
1631}
1632
1633
int cr2res_bpm_count(cpl_image *bpm, cr2res_bpm_type type)
Count BPM of a given type.
Definition: cr2res_bpm.c:148
cpl_mask * cr2res_bpm_extract_mask(const cpl_image *bpm_ima, cr2res_bpm_type bpm_type)
Extract a mask from a BPM image.
Definition: cr2res_bpm.c:247
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.
Definition: cr2res_calib.c:71
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: cr2res_dfs.c:53
cpl_table * cr2res_extract_EXTRACT1D_create(cpl_bivector **spectrum, const cpl_table *trace_table)
Create the extract 1D table to be saved.
int cr2res_extract_median(const hdrl_image *hdrl_in, const cpl_table *trace_tab, int order, int trace_id, int height, cpl_vector **slit_func, cpl_bivector **spec, hdrl_image **model)
Simple extraction function with the median.
int cr2res_extract_slitdec_curved(const hdrl_image *img_hdrl, const cpl_table *trace_tab, const cpl_vector *slit_func_vec_in, int order, int trace_id, int height, int swath, int oversample, double smooth_slit, double smooth_spec, int niter, double kappa, double error_factor, cpl_vector **slit_func, cpl_bivector **spec, hdrl_image **model)
Extract optimally (slit-decomposition) with polynomial slit.
int cr2res_extract_sum_tilt(const hdrl_image *hdrl_in, const cpl_table *trace_tab, int order, int trace_id, int height, cpl_vector **slit_func, cpl_bivector **spec, hdrl_image **model)
Simple extraction function with curvature correction.
int cr2res_extract_sum_vert(const hdrl_image *hdrl_in, const cpl_table *trace_tab, int order, int trace_id, int height, cpl_vector **slit_func, cpl_bivector **spec, hdrl_image **model)
Simple extraction function.
cpl_table * cr2res_extract_SLITFUNC_create(cpl_vector **slit_func, const cpl_table *trace_table)
Create the slit functions table to be saved.
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.
Definition: cr2res_flat.c:63
const cpl_frame * cr2res_io_find_BPM(const cpl_frameset *in)
Get the first CR2RES_BPM_DRSTYPE frame from a frameset.
Definition: cr2res_io.c:369
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.
Definition: cr2res_io.c:1823
const cpl_frame * cr2res_io_find_TRACE_WAVE(const cpl_frameset *in)
Get the first CR2RES_TW_DRSTYPE frame from a frameset.
Definition: cr2res_io.c:231
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.
Definition: cr2res_io.c:1670
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.
Definition: cr2res_io.c:527
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
Definition: cr2res_io.c:432
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.
Definition: cr2res_io.c:1732
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
Definition: cr2res_io.c:808
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.
Definition: cr2res_io.c:1639
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
Definition: cr2res_io.c:644
hdrl_image * cr2res_io_load_image(const char *in, int detector)
Load an hdrl image from a image file.
Definition: cr2res_io.c:704
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.
Definition: cr2res_io.c:1792
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.
Definition: cr2res_io.c:1555
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
Definition: cr2res_io.c:1109
cpl_image * cr2res_io_load_BPM(const char *filename, int detector, int data)
Load an image from a BPM.
Definition: cr2res_io.c:957
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
Definition: cr2res_io.c:462
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
Definition: cr2res_pfits.c:137
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: cr2res_pfits.c:199
double cr2res_qc_overexposed(const cpl_image *ima, const cpl_table *tw, int order_idx)
Computes the Overexposed fraction.
Definition: cr2res_qc.c:796
double cr2res_qc_flat_s2n(const cpl_table *extracted)
Computes the S2N on the flat.
Definition: cr2res_qc.c:375
int cr2res_qc_flat_order_positions(const cpl_table *tw, int **order_nb, double **order_pos, int *nbvals)
Compute the central orders positions.
Definition: cr2res_qc.c:235
double cr2res_qc_flat_trace_center_y(const cpl_table *trace)
Computes the mean Y coord of the central order.
Definition: cr2res_qc.c:325
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.
Definition: cr2res_trace.c:163
int cr2res_trace_add_extra_columns(cpl_table *traces, const char *infile, int det_nr)
Add extra columns to the plain trace table.
Definition: cr2res_trace.c:972
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.
Definition: cr2res_trace.c:431
cpl_table * cr2res_trace_merge(const cpl_table *trace_wave1, const cpl_table *trace_wave2)
Merge 2 trace_wave tables.
Definition: cr2res_trace.c:592
int cr2res_format_setting(char *setting_id)
Format the setting.
Definition: cr2res_utils.c:152
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
Definition: hdrl_image.c:105
hdrl_image * hdrl_image_new(cpl_size nx, cpl_size ny)
create new zero filled hdrl image
Definition: hdrl_image.c:311
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
Definition: hdrl_image.c:379
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.