CR2RE Pipeline Reference Manual 1.6.10
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 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++)
834 {
835 // OVEREXPOSEDn
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))
839 {
840 cpl_vector_set(qc_overexposed, det_nr - 1,
841 cpl_propertylist_get_double(
842 ext_plist[i][det_nr - 1], qc_name));
843 }
844 cpl_free(qc_name);
845 // ORDERPOSn
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))
849 {
850 cpl_vector_set(qc_orderpos, det_nr - 1,
851 cpl_propertylist_get_double(
852 ext_plist[i][det_nr - 1], qc_name));
853 }
854 cpl_free(qc_name);
855 }
856
857 // OVEREXPOSEDn.AVG/RMS
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)) ;
862 cpl_free(qc_name) ;
863
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)) ;
868 cpl_free(qc_name) ;
869 cpl_vector_delete(qc_overexposed) ;
870
871 // ORDERPOSn.AVG/RMS
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)) ;
876 cpl_free(qc_name) ;
877
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)) ;
882 cpl_free(qc_name) ;
883 cpl_vector_delete(qc_orderpos) ;
884 }
885 cpl_free(orders) ;
886 }
887 }
888
889 /* Save Products */
890
891 /* Save only the used RAW ? : raw_one_... instead of 2nd frameset */
892 /* Beware that the calibration PRO RECi CAL will be missing */
893
894 /* MASTER_FLAT */
895 if (nlabels == 1) {
896 out_file = cpl_sprintf("%s_%s_master_flat.fits",
897 RECIPE_STRING, decker_desc[i]) ;
898 } else {
899 out_file = cpl_sprintf("%s_%s_%s_master_flat.fits",
900 RECIPE_STRING, setting_id, decker_desc[i]) ;
901 }
902 cr2res_io_save_MASTER_FLAT(out_file, frameset,
903 frameset, parlist, master_flat, qc_main,
904 ext_plist[i], CR2RES_CAL_FLAT_MASTER_PROCATG,
905 RECIPE_STRING);
906 cpl_free(out_file);
907
908 /* SLIT_MODEL */
909 if (nlabels == 1) {
910 out_file = cpl_sprintf("%s_%s_slit_model.fits",
911 RECIPE_STRING, decker_desc[i]) ;
912 } else {
913 out_file = cpl_sprintf("%s_%s_%s_slit_model.fits",
914 RECIPE_STRING, setting_id, decker_desc[i]) ;
915 }
916 cr2res_io_save_SLIT_MODEL(out_file, frameset,
917 frameset, parlist, slit_model, qc_main,
918 ext_plist[i], CR2RES_CAL_FLAT_SLIT_MODEL_PROCATG,
919 RECIPE_STRING);
920 cpl_free(out_file);
921
922 /* BLAZE */
923 if (nlabels == 1) {
924 out_file = cpl_sprintf("%s_%s_blaze.fits",
925 RECIPE_STRING, decker_desc[i]) ;
926 } else {
927 out_file = cpl_sprintf("%s_%s_%s_blaze.fits",
928 RECIPE_STRING, setting_id, decker_desc[i]) ;
929 }
930 cr2res_io_save_EXTRACT_1D(out_file, frameset,
931 frameset, parlist, extract_1d, qc_main,
932 ext_plist[i], CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG,
933 RECIPE_STRING);
934 cpl_free(out_file);
935
936 /* TRACE_WAVE */
937 if (nlabels == 1) {
938 out_file = cpl_sprintf("%s_%s_tw.fits",
939 RECIPE_STRING, decker_desc[i]) ;
940 } else {
941 out_file = cpl_sprintf("%s_%s_%s_tw.fits",
942 RECIPE_STRING, setting_id, decker_desc[i]) ;
943 }
944 cr2res_io_save_TRACE_WAVE(out_file, frameset,
945 frameset, parlist, trace_wave[i], qc_main,
946 ext_plist[i], CR2RES_CAL_FLAT_TW_PROCATG, RECIPE_STRING);
947 cpl_free(out_file);
948
949 /* SLIT_FUNC */
950 if (nlabels == 1) {
951 out_file = cpl_sprintf("%s_%s_slit_func.fits",
952 RECIPE_STRING, decker_desc[i]) ;
953 } else {
954 out_file = cpl_sprintf("%s_%s_%s_slit_func.fits",
955 RECIPE_STRING, setting_id, decker_desc[i]) ;
956 }
957 cr2res_io_save_SLIT_FUNC(out_file, frameset,
958 frameset, parlist, slit_func, qc_main,
959 ext_plist[i], CR2RES_CAL_FLAT_SLIT_FUNC_PROCATG,
960 RECIPE_STRING);
961 cpl_free(out_file);
962
963 /* BPM */
964 if (nlabels == 1) {
965 out_file = cpl_sprintf("%s_%s_bpm.fits",
966 RECIPE_STRING, decker_desc[i]) ;
967 } else {
968 out_file = cpl_sprintf("%s_%s_%s_bpm.fits",
969 RECIPE_STRING, setting_id, decker_desc[i]) ;
970 }
971 cr2res_io_save_BPM(out_file, frameset,
972 frameset, parlist, bpm, qc_main, ext_plist[i],
973 CR2RES_CAL_FLAT_BPM_PROCATG, RECIPE_STRING) ;
974 cpl_free(out_file);
975
976 /* Free */
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)
981 hdrl_image_delete(master_flat[det_nr-1]) ;
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)
987 hdrl_image_delete(slit_model[det_nr-1]) ;
988 if (bpm[det_nr-1] != NULL)
989 cpl_image_delete(bpm[det_nr-1]) ;
990 }
991 cpl_msg_indent_less() ;
992 }
993
994 /* Merge the Decker positions TRACE_WAVE files in a single one */
995 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
996 /* Initialise */
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]) ;
1000 else
1001 trace_wave_merged[det_nr-1] = NULL ;
1002 /* Loop on the other detectors */
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) {
1007 /* Do nothing - go to next iteration */
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) {
1013 /* Do nothing - go to next iteration */
1014 } else {
1015 merged = cr2res_trace_merge(trace_wave1, trace_wave2) ;
1016 if (merged == NULL) {
1017 cpl_msg_error(__func__, "Failed merging") ;
1018 } else {
1019 cpl_table_delete(trace_wave_merged[det_nr-1]) ;
1020 trace_wave_merged[det_nr-1] = merged ;
1021 }
1022 }
1023 }
1024 }
1025
1026 /* Free the traces */
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]) ;
1031
1032
1033 /* Save TRACE_WAVE_MERGED */
1034 if (nlabels == 1) {
1035 out_file = cpl_sprintf("%s_tw_merged.fits",
1036 RECIPE_STRING) ;
1037 } else {
1038 out_file = cpl_sprintf("%s_%s_tw_merged.fits", RECIPE_STRING,
1039 setting_id) ;
1040 }
1041
1042 /* Save only the used RAW ? : raw_one_... instead of 2nd frameset */
1043 /* Beware that the calibration PRO RECi CAL will be missing */
1044
1045 cr2res_io_save_TRACE_WAVE(out_file, frameset, frameset, parlist,
1046 trace_wave_merged, NULL, ext_plist[0],
1047 CR2RES_CAL_FLAT_TW_MERGED_PROCATG, RECIPE_STRING) ;
1048 cpl_free(out_file);
1049 cpl_free(setting_id) ;
1050
1051 /* Free extensions */
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]) ;
1056
1057 /* Free the merged traces */
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]) ;
1061
1062 cpl_frameset_delete(raw_one_setting) ;
1063 cpl_msg_indent_less() ;
1064 }
1065 cpl_free(labels);
1066 cpl_frameset_delete(rawframes) ;
1067
1068 return (int)cpl_error_get_code();
1069}
1070
1071/*----------------------------------------------------------------------------*/
1109/*----------------------------------------------------------------------------*/
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,
1116 int filter_traces,
1117 int subtract_nolight_rows,
1118 int cosmics,
1119 double bpm_low,
1120 double bpm_high,
1121 double bpm_linemax,
1122 int trace_degree,
1123 int trace_min_cluster,
1124 int trace_smooth_x,
1125 int trace_smooth_y,
1126 double trace_threshold,
1127 int trace_opening,
1128 cr2res_extr_method extr_method,
1129 int extract_oversample,
1130 int extract_swath_width,
1131 int extract_height,
1132 double extract_smooth_slit,
1133 double extract_smooth_spec,
1134 int reduce_det,
1135 int reduce_order,
1136 int reduce_trace,
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,
1142 cpl_image ** bpm,
1143 cpl_propertylist ** ext_plist)
1144{
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 ;
1166 cpl_vector * dits ;
1167 cpl_vector * ndits ;
1168 int * qc_order_nb ;
1169 double * qc_order_pos ;
1170 int * orders ;
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 ;
1176
1177 /* TODO, make parameters */
1178 int extract_niter = 10;
1179 double extract_kappa = 10;
1180
1181 /* Check Inputs */
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") ;
1186 return -1 ;
1187 }
1188
1189 /* Get the Gain */
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 ;
1193 else {
1194 cpl_msg_error(__func__, "Failed to get the Gain value") ;
1195 return -1 ;
1196 }
1197
1198 /* Get the First RAW file */
1199 first_file = cpl_frame_get_filename(
1200 cpl_frameset_get_position_const(rawframes, 0)) ;
1201
1202 /* Get the DIT for the Dark correction */
1203 if ((dits = cr2res_io_read_dits(rawframes)) == NULL) {
1204 cpl_msg_error(__func__, "Failed to read the dits") ;
1205 return -1 ;
1206 }
1207 /*Load the NDITs */
1208 ndits = cr2res_io_read_ndits(rawframes);
1209
1210 /* Load the image list */
1211 imlist = cr2res_io_load_image_list_from_set(rawframes, reduce_det) ;
1212 if (imlist == NULL) {
1213 cpl_msg_error(__func__, "Failed to load the images") ;
1214 cpl_vector_delete(dits) ;
1215 cpl_vector_delete(ndits) ;
1216 return -1 ;
1217 }
1218
1219 /* Set the error factor. */
1220 error_factor = gain * cpl_vector_get(ndits, 0) *
1221 cpl_frameset_get_size(rawframes) ;
1222
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.");
1227 }
1228
1229 /* Compute traces */
1230 cpl_msg_info(__func__, "Compute the traces") ;
1231 cpl_msg_indent_more() ;
1232 if ((computed_traces = cr2res_trace(
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) ;
1239 hdrl_imagelist_delete(imlist) ;
1240 cpl_msg_indent_less() ;
1241 return -1 ;
1242 }
1243 cpl_msg_indent_less() ;
1244
1245 /* Calibrate the Data */
1246 cpl_msg_info(__func__, "Calibrate the input images") ;
1247 cpl_msg_indent_more() ;
1248 if ((imlist_calibrated = cr2res_calib_imagelist(imlist, reduce_det,
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) ;
1254 hdrl_imagelist_delete(imlist) ;
1255 cpl_table_delete(computed_traces) ;
1256 cpl_msg_indent_less() ;
1257 return -1 ;
1258 } else {
1259 /* Replace the calibrated image in the list */
1260 hdrl_imagelist_delete(imlist) ;
1261 imlist = imlist_calibrated ;
1262 }
1263 cpl_vector_delete(dits) ;
1264 cpl_vector_delete(ndits) ;
1265 cpl_msg_indent_less() ;
1266
1267 /* Collapse */
1268 cpl_msg_info(__func__, "Collapse the input images") ;
1269 cpl_msg_indent_more() ;
1270 if (hdrl_imagelist_collapse_mean(imlist, &collapsed, &contrib) !=
1271 CPL_ERROR_NONE) {
1272 cpl_msg_error(__func__, "Failed to Collapse") ;
1273 hdrl_imagelist_delete(imlist) ;
1274 cpl_table_delete(computed_traces) ;
1275 cpl_msg_indent_less() ;
1276 return -1 ;
1277 }
1278 hdrl_imagelist_delete(imlist) ;
1279 cpl_image_delete(contrib) ;
1280 cpl_msg_indent_less() ;
1281
1282 /* Add The remaining Columns to the trace table */
1283 cr2res_trace_add_extra_columns(computed_traces, first_file, reduce_det) ;
1284
1285 /* Filter out traces */
1286 if (filter_traces) {
1287 char *setting_id;
1288 int zp_order;
1289 cpl_msg_info(__func__, "Filter out the traces") ;
1290 cpl_msg_indent_more() ;
1291
1292 /* Get the setting and the zp_order */
1293 plist = cpl_propertylist_load(first_file, 0) ;
1294 setting_id = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
1295 zp_order = cr2res_pfits_get_order_zp(plist) ;
1296 cpl_propertylist_delete(plist) ;
1297 filtered_traces = cr2res_trace_filter(computed_traces,
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") ;
1305 hdrl_image_delete(collapsed) ;
1306 cpl_table_delete(computed_traces) ;
1307 cpl_msg_indent_less() ;
1308 return -1 ;
1309 }
1310 }
1311
1312 /* Use the input traces for extraction if they are provided */
1313 if (tw_frame) {
1314 traces = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(tw_frame),
1315 reduce_det) ;
1316 if (traces == NULL) {
1317 cpl_msg_error(__func__, "Cannot Load the provided TW file") ;
1318 hdrl_image_delete(collapsed) ;
1319 cpl_table_delete(computed_traces) ;
1320 return -1 ;
1321 }
1322 } else {
1323 traces = cpl_table_duplicate(computed_traces) ;
1324 }
1325 cpl_table_delete(computed_traces) ;
1326
1327 /* Extract */
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) ;
1332 hdrl_image_mul_scalar(model_master, (hdrl_value){0.0, 0.0}) ;
1333
1334 /* Loop over the traces and extract them */
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;
1339 /* Initialise */
1340 slit_func_vec[i] = NULL ;
1341 spectrum[i] = NULL ;
1342 model_tmp = NULL ;
1343
1344 /* Get Order and trace id */
1345 order = cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL) ;
1346 trace_id = cpl_table_get(traces, CR2RES_COL_TRACENB, i, NULL) ;
1347
1348 /* Check if this order needs to be skipped */
1349 if (reduce_order > -1 && order != reduce_order) continue ;
1350
1351 /* Check if this trace needs to be skipped */
1352 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1353
1354 cpl_msg_info(__func__, "Process Order %d/Trace %d", order, trace_id) ;
1355 cpl_msg_indent_more() ;
1356
1357 /* Call the Extraction */
1358 if (extr_method == CR2RES_EXTR_SUM) {
1359 if (cr2res_extract_sum_vert(collapsed, traces, order, trace_id,
1360 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1361 &model_tmp) != 0) {
1362 cpl_msg_error(__func__, "Cannot (sum-)extract the trace") ;
1363 slit_func_vec[i] = NULL ;
1364 spectrum[i] = NULL ;
1365 model_tmp = NULL ;
1366 cpl_error_reset() ;
1367 cpl_msg_indent_less() ;
1368 continue ;
1369 }
1370 } else if (extr_method == CR2RES_EXTR_MEDIAN) {
1371 if (cr2res_extract_median(collapsed, traces, order, trace_id,
1372 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1373 &model_tmp) != 0) {
1374 cpl_msg_error(__func__, "Cannot (median-)extract the trace") ;
1375 slit_func_vec[i] = NULL ;
1376 spectrum[i] = NULL ;
1377 model_tmp = NULL ;
1378 cpl_error_reset() ;
1379 cpl_msg_indent_less() ;
1380 continue ;
1381 }
1382 } else if (extr_method == CR2RES_EXTR_TILTSUM) {
1383 if (cr2res_extract_sum_tilt(collapsed, traces, order, trace_id,
1384 extract_height, &(slit_func_vec[i]), &(spectrum[i]),
1385 &model_tmp) != 0) {
1386 cpl_msg_error(__func__, "Cannot (tiltsum-)extract the trace") ;
1387 slit_func_vec[i] = NULL ;
1388 spectrum[i] = NULL ;
1389 model_tmp = NULL ;
1390 cpl_error_reset() ;
1391 cpl_msg_indent_less() ;
1392 continue ;
1393 }
1394 } else if (extr_method == CR2RES_EXTR_OPT_CURV) {
1395 if (cr2res_extract_slitdec_curved(collapsed, traces, NULL,order,
1396 trace_id, extract_height, extract_swath_width,
1397 extract_oversample, extract_smooth_slit,
1398 extract_smooth_spec, extract_niter, extract_kappa,
1399 error_factor,
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 ;
1404 model_tmp = NULL ;
1405 cpl_error_reset() ;
1406 cpl_msg_indent_less() ;
1407 continue ;
1408 }
1409 }
1410
1411 /* Update the model global image */
1412 if (model_tmp != NULL) {
1413 hdrl_image_add_image(model_master, model_tmp) ;
1414 hdrl_image_delete(model_tmp) ;
1415 }
1416 cpl_msg_indent_less() ;
1417 }
1418 cpl_msg_indent_less() ;
1419
1420 /* Create the slit_func_tab for the current detector */
1421 slit_func_tab = cr2res_extract_SLITFUNC_create(slit_func_vec, traces) ;
1422
1423 /* Create the extracted_tab for the current detector */
1424 extract_tab = cr2res_extract_EXTRACT1D_create(spectrum, traces) ;
1425
1426 /* Deallocate Vectors */
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]) ;
1430 }
1431 cpl_free(spectrum) ;
1432 cpl_free(slit_func_vec) ;
1433
1434 /* Compute the Master flat */
1435 cpl_msg_info(__func__, "Compute the master flat") ;
1436 cpl_msg_indent_more() ;
1437 if ((master_flat_loc = cr2res_master_flat(collapsed,
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) ;
1444 hdrl_image_delete(model_master) ;
1445 hdrl_image_delete(collapsed) ;
1446 cpl_msg_indent_less() ;
1447 return -1 ;
1448 }
1449 cpl_msg_indent_less() ;
1450 hdrl_image_delete(collapsed) ;
1451
1452 /* Create BPM image */
1453 bpm_im = NULL ;
1454 if (bpm_frame != NULL) {
1455 if ((bpm_im = cr2res_io_load_BPM(
1456 cpl_frame_get_filename(bpm_frame),
1457 reduce_det, 1)) == NULL) {
1458 cpl_msg_warning(__func__, "Failed to Load the Master BPM") ;
1459 }
1460 }
1461 if (bpm_im == NULL) {
1462 bpm_im = cpl_image_duplicate(bpm_flat) ;
1463 } else {
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) ;
1469 hdrl_image_delete(model_master) ;
1470 hdrl_image_delete(master_flat_loc) ;
1471 cpl_image_delete(bpm_im) ;
1472 cpl_image_delete(bpm_flat) ;
1473 cpl_msg_indent_less() ;
1474 return -1 ;
1475 }
1476 }
1477 cpl_image_delete(bpm_flat) ;
1478
1479 /* Compute the QC parameters */
1480
1481 /* Load the first RAW image */
1482 first_image = cr2res_io_load_image(first_file, reduce_det) ;
1483
1484 /* Set the BPM */
1485 bpm_mask = cr2res_bpm_extract_mask(bpm_im, CR2RES_BPM_ALL) ;
1486
1487 cpl_image_reject_from_mask(hdrl_image_get_image(first_image), bpm_mask) ;
1488 qc_mean = cpl_image_get_mean(hdrl_image_get_image(first_image)) ;
1489 qc_median = cpl_image_get_median(hdrl_image_get_image(first_image)) ;
1490 plist = cpl_propertylist_load(first_file, 0) ;
1491 dit = cr2res_pfits_get_dit(plist) ;
1492 cpl_propertylist_delete(plist) ;
1493 qc_flux = qc_mean / dit ;
1494
1495 my_master_flat = cpl_image_duplicate(hdrl_image_get_image(master_flat_loc));
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) ;
1502
1503 qc_s2n = cr2res_qc_flat_s2n(extract_tab) ;
1504
1505 cr2res_util_blaze_stat(extract_tab, &bl_good, &bl_tot);
1506
1507 qc_trace_centery = cr2res_qc_flat_trace_center_y(traces) ;
1508 qc_nbbad = cr2res_bpm_count(bpm_im, CR2RES_BPM_FLAT) ;
1509 cr2res_qc_flat_order_positions(traces, &qc_order_nb, &qc_order_pos,&nbvals);
1510
1511 /* Load the extension header for saving */
1512 ext_nr = cr2res_io_get_ext_idx(first_file, reduce_det, 1) ;
1513 plist = cpl_propertylist_load(first_file, ext_nr) ;
1514 if (plist == NULL) {
1515 hdrl_image_delete(first_image) ;
1516 cpl_table_delete(traces) ;
1517 cpl_table_delete(slit_func_tab) ;
1518 cpl_table_delete(extract_tab) ;
1519 hdrl_image_delete(model_master) ;
1520 hdrl_image_delete(master_flat_loc) ;
1521 cpl_image_delete(bpm_im) ;
1522 cpl_msg_error(__func__, "Failed to load the plist") ;
1523 return -1 ;
1524 }
1525
1526 /* QC.OVEREXPOSED */
1527
1528 /* Get all orders */
1529 orders = cr2res_trace_get_order_idx_values(traces, &nb_orders) ;
1530 /* Loop on the orders */
1531 for (i=0 ; i<nb_orders ; i++) {
1532 double qc_overexposed;
1533 qc_overexposed = cr2res_qc_overexposed(
1534 hdrl_image_get_image(first_image), traces, orders[i]) ;
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);
1538 cpl_free(qc_name) ;
1539 }
1540 cpl_free(orders) ;
1541 hdrl_image_delete(first_image) ;
1542
1543 /* Store the QC parameters in the plist */
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]);
1549 cpl_free(qc_name) ;
1550 }
1551 }
1552 if (qc_order_nb != NULL) cpl_free(qc_order_nb) ;
1553 if (qc_order_pos != NULL) cpl_free(qc_order_pos) ;
1554
1555 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEAN,
1556 qc_mean) ;
1557 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_MEDIAN,
1558 qc_median);
1559 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_FLUX,
1560 qc_flux) ;
1561 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_RMS,
1562 qc_rms) ;
1563 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_S2N,
1564 qc_s2n) ;
1565 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FLAT_CENTERY,
1566 qc_trace_centery) ;
1567 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_FLAT_NBBAD,
1568 qc_nbbad) ;
1569 cpl_propertylist_append_int(plist, CR2RES_HEADER_QC_BLAZE_NGOOD,
1570 bl_good) ;
1571 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_BLAZE_TOT,
1572 bl_tot) ;
1573
1574 /* Return the results */
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 ;
1581 *bpm = bpm_im ;
1582 return 0 ;
1583}
1584
1585/*----------------------------------------------------------------------------*/
1592/*----------------------------------------------------------------------------*/
1593static int cr2res_cal_flat_compare(
1594 const cpl_frame * frame1,
1595 const cpl_frame * frame2)
1596{
1597 int comparison ;
1598 cpl_propertylist * plist1 ;
1599 cpl_propertylist * plist2 ;
1600 const char * sval1 ;
1601 const char * sval2 ;
1602
1603 /* Test entries */
1604 if (frame1==NULL || frame2==NULL) return -1 ;
1605
1606 /* Get property lists */
1607 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1608 cpl_msg_error(__func__, "getting header from reference frame");
1609 return -1 ;
1610 }
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) ;
1614 return -1 ;
1615 }
1616
1617 /* Test status */
1618 if (cpl_error_get_code()) {
1619 cpl_propertylist_delete(plist1) ;
1620 cpl_propertylist_delete(plist2) ;
1621 return -1 ;
1622 }
1623
1624 comparison = 1 ;
1625
1626 /* Compare the SETTING used */
1627 sval1 = cr2res_pfits_get_wlen_id(plist1) ;
1628 sval2 = cr2res_pfits_get_wlen_id(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) ;
1633 return -1 ;
1634 }
1635 if (strcmp(sval1, sval2)) comparison = 0 ;
1636
1637 cpl_propertylist_delete(plist1) ;
1638 cpl_propertylist_delete(plist2) ;
1639 return comparison ;
1640}
1641
1642
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.