CR2RE Pipeline Reference Manual 1.6.10
cr2res_cal_wave.c
1/*
2
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 <locale.h>
29#include <string.h>
30
31#include <cpl.h>
32#include <math.h>
33#include "hdrl.h"
34
35#include "cr2res_utils.h"
36#include "cr2res_calib.h"
37#include "cr2res_pfits.h"
38#include "cr2res_dfs.h"
39#include "cr2res_io.h"
40#include "cr2res_qc.h"
41#include "cr2res_slit_curv.h"
42#include "cr2res_extract.h"
43#include "cr2res_trace.h"
44#include "cr2res_wave.h"
45
46/*-----------------------------------------------------------------------------
47 Define
48 -----------------------------------------------------------------------------*/
49
50#define RECIPE_STRING "cr2res_cal_wave"
51#define CRIRES_PI 3.1415926535897932384626433832795029L
52
53/*-----------------------------------------------------------------------------
54 Plugin registration
55 -----------------------------------------------------------------------------*/
56
57int cpl_plugin_get_info(cpl_pluginlist * list);
58
59/*-----------------------------------------------------------------------------
60 Private function prototypes
61 -----------------------------------------------------------------------------*/
62
63static int cr2res_cal_wave_qc_une_flux(
64 const cpl_table ** extracted,
65 const cpl_propertylist ** ext_plist,
66 double cwlen,
67 cpl_propertylist * plist) ;
68static int cr2res_cal_wave_qc_fpi(
69 const cpl_table ** extracted,
70 const cpl_table ** tw,
71 const cpl_propertylist ** ext_plist,
72 double cwlen,
73 cpl_propertylist * plist) ;
74static int cr2res_cal_wave_qc_tilt(
75 const cpl_table ** tws,
76 double cwlen,
77 cpl_propertylist * plist) ;
78static int cr2res_cal_wave_reduce(
79 const cpl_frameset * rawframes_une,
80 const cpl_frameset * rawframes_fpet,
81 const cpl_frame * detlin_frame,
82 const cpl_frame * master_dark_frame,
83 const cpl_frame * master_flat_frame,
84 const cpl_frame * bpm_frame,
85 const cpl_frame * trace_wave_frame,
86 const cpl_frame * lines_frame,
87 int reduce_det,
88 int reduce_order,
89 int reduce_trace,
90 int slit_degree,
91 int subtract_nolight_rows,
92 int cosmics,
93 cr2res_collapse collapse,
94 int ext_height,
95 int ext_swath_width,
96 int ext_oversample,
97 double ext_smooth_slit,
98 double ext_smooth_spec,
99 cr2res_wavecal_type wavecal_type,
100 int wl_degree,
101 double wl_start,
102 double wl_end,
103 double wl_err,
104 double wl_shift,
105 int log_flag,
106 int fallback_input_wavecal_flag,
107 int keep_higher_degrees_flag,
108 int clean_spectrum,
109 int display,
110 double display_wmin,
111 double display_wmax,
112 cpl_table ** out_trace_wave_une,
113 cpl_table ** lines_diagnostics_une,
114 cpl_table ** out_extracted_une,
115 hdrl_image ** out_wave_map_une,
116 cpl_propertylist ** ext_plist_une,
117 cpl_table ** out_trace_wave_fpet,
118 cpl_table ** lines_diagnostics_fpet,
119 cpl_table ** out_extracted_fpet,
120 hdrl_image ** out_wave_map_fpet,
121 cpl_propertylist ** ext_plist_fpet) ;
122static int cr2res_cal_wave_create(cpl_plugin *);
123static int cr2res_cal_wave_exec(cpl_plugin *);
124static int cr2res_cal_wave_destroy(cpl_plugin *);
125static int cr2res_cal_wave(cpl_frameset *, const cpl_parameterlist *);
126
127/*-----------------------------------------------------------------------------
128 Static variables
129 -----------------------------------------------------------------------------*/
130
131static char cr2res_cal_wave_description[] = "\
132Spectrum Extraction and Wavelength Calibration \n\
133 This recipe performs the extraction of the various orders along \n\
134 the provided traces, and the wavelength calibration of these \n\
135 extracted spectra. \n\
136 It can support different methods (--wl_method parameter): \n\
137 XCORR: Cross Correlation with a emission lines catalog (default) \n\
138 LINE1D: Line identification and fitting for each 1D spectra \n\
139 LINE2D: Line identification and fitting for all 1D spectra at once \n\
140 \n\
141 Inputs \n\
142 raw.fits " CR2RES_WAVE_UNE_RAW " [1 to n] \n\
143 or " CR2RES_WAVE_FPET_RAW " [0 to n] \n\
144 trace.fits " CR2RES_CAL_FLAT_TW_PROCATG " [1] \n\
145 or " CR2RES_CAL_FLAT_TW_MERGED_PROCATG " \n\
146 or " CR2RES_UTIL_TRACE_TW_PROCATG " \n\
147 or " CR2RES_UTIL_WAVE_TW_PROCATG " \n\
148 or " CR2RES_CAL_WAVE_TW_PROCATG " \n\
149 or " CR2RES_UTIL_SLIT_CURV_TW_PROCATG " \n\
150 detlin.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG " [0 to 1] \n\
151 bpm.fits " CR2RES_CAL_DARK_BPM_PROCATG " [0 to 1] \n\
152 or " CR2RES_CAL_FLAT_BPM_PROCATG " \n\
153 or " CR2RES_CAL_DETLIN_BPM_PROCATG " \n\
154 or " CR2RES_UTIL_BPM_MERGE_PROCATG " \n\
155 or " CR2RES_UTIL_BPM_SPLIT_PROCATG " \n\
156 master_dark.fits " CR2RES_CAL_DARK_MASTER_PROCATG " [0 to 1] \n\
157 master_flat.fits " CR2RES_CAL_FLAT_MASTER_PROCATG " [0 to 1] \n\
158 lines.fits " CR2RES_EMISSION_LINES_PROCATG " [0 to 1] \n\
159 \n\
160 Outputs \n\
161 cr2res_cal_wave_tw.fits " CR2RES_CAL_WAVE_TW_PROCATG" \n\
162 cr2res_cal_wave_wave_map.fits " CR2RES_CAL_WAVE_MAP_PROCATG" \n\
163 cr2res_cal_wave_lines_diagnostics.fits "
164 CR2RES_CAL_WAVE_LINES_DIAGNOSTICS_PROCATG"\n\
165 cr2res_cal_wave_extracted.fits " CR2RES_CAL_WAVE_EXTRACT_1D_PROCATG"\n\
166 \n\
167 Algorithm \n\
168 loop on detectors d: \n\
169 Call cr2res_cal_wave_reduce() \n\
170 -> out_trace_wave[une|fpet](d) \n\
171 -> lines_diagnostics[une|fpet](d) \n\
172 -> out_extracted[une|fpet](d) \n\
173 -> out_wave_map[une|fpet](d) \n\
174 Save out_trace_wave[une|fpet] \n\
175 Save lines_diagnostics[une|fpet] \n\
176 Save out_extracted[une|fpet] \n\
177 Save out_wave_map[une|fpet] \n\
178 \n\
179 cr2res_cal_wave_reduce(): \n\
180 If FPET RAW frame is present, compute the slit_curvature from it, \n\
181 use it in the following, and store it in the out_trace_wave_fpet. \n\
182 \n\
183 Successively for UNE and FPET RAW frames: \n\
184 Load the raw image list \n\
185 Apply the calibrations to the image list \n\
186 Collapse the image list \n\
187 Extract along the traces from the collapsed image \n\
188 Compute the Wavelength with cr2res_wave_apply() \n\
189 -> out_trace_wave \n\
190 -> lines_diagnostics \n\
191 -> out_extracted \n\
192 Compute the Wavelength map \n\
193 -> out_wave_map \n\
194 \n\
195 cr2res_wave_apply() \n\
196 loop on the traces t: \n\
197 Get the spectrum \n\
198 Get the Initial guess \n\
199 Switch on the required method: \n\
200 CR2RES_LINE2D: cr2res_wave_2d() \n\
201 CR2RES_LINE1D: cr2res_wave_line_fitting() \n\
202 CR2RES_ETALON: cr2res_wave_etalon() \n\
203 CR2RES_XCORR: cr2res_wave_xcorr() \n\
204 \n\
205 Library Functions used \n\
206 cr2res_io_find_TRACE_WAVE() \n\
207 cr2res_io_find_BPM() \n\
208 cr2res_io_read_dits() \n\
209 cr2res_io_load_image_list_from_set() \n\
210 cr2res_calib_imagelist() \n\
211 cr2res_io_load_TRACE_WAVE() \n\
212 cr2res_extract_traces() \n\
213 cr2res_wave_apply() \n\
214 cr2res_extract_EXTRACT1D_get_spectrum() \n\
215 cr2res_wave_estimate_compute() \n\
216 cr2res_wave_2d() \n\
217 cr2res_wave_line_fitting() \n\
218 cr2res_wave_etalon() \n\
219 cr2res_wave_xcorr() \n\
220 cr2res_wave_gen_wave_map() \n\
221 cr2res_io_save_TRACE_WAVE() \n\
222 cr2res_io_save_WAVE_MAP() \n\
223 cr2res_io_save_LINES_DIAGNOSTICS() \n\
224 cr2res_io_save_EXTRACT_1D() \n\
225" ;
226
227/*-----------------------------------------------------------------------------
228 Function code
229 -----------------------------------------------------------------------------*/
230
231/*----------------------------------------------------------------------------*/
241/*----------------------------------------------------------------------------*/
242int cpl_plugin_get_info(cpl_pluginlist * list)
243{
244 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
245 cpl_plugin * plugin = &recipe->interface;
246
247 if (cpl_plugin_init(plugin,
248 CPL_PLUGIN_API,
249 CR2RES_BINARY_VERSION,
250 CPL_PLUGIN_TYPE_RECIPE,
251 RECIPE_STRING,
252 "Wavelength Calibration",
253 cr2res_cal_wave_description,
254 CR2RES_PIPELINE_AUTHORS,
255 PACKAGE_BUGREPORT,
257 cr2res_cal_wave_create,
258 cr2res_cal_wave_exec,
259 cr2res_cal_wave_destroy)) {
260 cpl_msg_error(cpl_func, "Plugin initialization failed");
261 (void)cpl_error_set_where(cpl_func);
262 return 1;
263 }
264
265 if (cpl_pluginlist_append(list, plugin)) {
266 cpl_msg_error(cpl_func, "Error adding plugin to list");
267 (void)cpl_error_set_where(cpl_func);
268 return 1;
269 }
270
271 return 0;
272}
273
274/*----------------------------------------------------------------------------*/
282/*----------------------------------------------------------------------------*/
283static int cr2res_cal_wave_create(cpl_plugin * plugin)
284{
285 cpl_recipe * recipe;
286 cpl_parameter * p;
287
288 /* Check that the plugin is part of a valid recipe */
289 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
290 recipe = (cpl_recipe *)plugin;
291 else
292 return -1;
293
294 /* Create the parameters list in the cpl_recipe object */
295 recipe->parameters = cpl_parameterlist_new();
296
297 /* Fill the parameters list */
298 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.detector",
299 CPL_TYPE_INT, "Only reduce the specified detector",
300 "cr2res.cr2res_cal_wave", 0);
301 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detector");
302 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
303 cpl_parameterlist_append(recipe->parameters, p);
304
305 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.order",
306 CPL_TYPE_INT, "Only reduce the specified order",
307 "cr2res.cr2res_cal_wave", -1);
308 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order");
309 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
310 cpl_parameterlist_append(recipe->parameters, p);
311
312 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.trace_nb",
313 CPL_TYPE_INT, "Only reduce the specified trace number",
314 "cr2res.cr2res_cal_wave", -1);
315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_nb");
316 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
317 cpl_parameterlist_append(recipe->parameters, p);
318
319 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.slit_degree",
320 CPL_TYPE_INT, "Slit fitting Polynomial degree (1 or 2)",
321 "cr2res.cr2res_cal_wave", 2);
322 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_degree");
323 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
324 cpl_parameterlist_append(recipe->parameters, p);
325
326 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.subtract_nolight_rows",
327 CPL_TYPE_BOOL, "Subtract the no-light rows.",
328 "cr2res.cr2res_cal_wave", FALSE);
329 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "subtract_nolight_rows");
330 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
331 cpl_parameterlist_append(recipe->parameters, p);
332
333 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.cosmics",
334 CPL_TYPE_BOOL, "Find and mark cosmic rays hits as bad",
335 "cr2res.cr2res_cal_wave", FALSE);
336 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics");
337 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
338 cpl_parameterlist_append(recipe->parameters, p);
339
340 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.collapse_method",
341 CPL_TYPE_STRING, "Collapse the input images (MEAN or MEDIAN)",
342 "cr2res.cr2res_cal_wave", "MEDIAN");
343 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "collapse_method");
344 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
345 cpl_parameterlist_append(recipe->parameters, p);
346
347 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.extract_oversample",
348 CPL_TYPE_INT, "factor by which to oversample the extraction",
349 "cr2res.cr2res_cal_wave", 7);
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extract_oversample");
351 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
352 cpl_parameterlist_append(recipe->parameters, p);
353
354 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.extract_swath_width",
355 CPL_TYPE_INT, "The swath width", "cr2res.cr2res_cal_wave", 2048);
356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extract_swath_width");
357 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
358 cpl_parameterlist_append(recipe->parameters, p);
359
360 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.extract_height",
361 CPL_TYPE_INT, "Extraction height",
362 "cr2res.cr2res_cal_wave", 160);
363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extract_height");
364 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
365 cpl_parameterlist_append(recipe->parameters, p);
366
367 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.extract_smooth_slit",
368 CPL_TYPE_DOUBLE, "Smoothing along the slit",
369 "cr2res.cr2res_cal_wave", 15.0);
370 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extract_smooth_slit");
371 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
372 cpl_parameterlist_append(recipe->parameters, p);
373
374 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.extract_smooth_spec",
375 CPL_TYPE_DOUBLE, "Smoothing along the spectrum",
376 "cr2res.cr2res_cal_wave", 2.0E-7);
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extract_smooth_spec");
378 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
379 cpl_parameterlist_append(recipe->parameters, p);
380
381 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.wl_method",
382 CPL_TYPE_STRING,
383 "Wavelength Method (XCORR / LINE1D / LINE2D)",
384 "cr2res.cr2res_cal_wave", "XCORR");
385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wl_method");
386 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
387 cpl_parameterlist_append(recipe->parameters, p);
388
389 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.wl_shift",
390 CPL_TYPE_DOUBLE, "Wavelength shift (nm) to apply to the guess",
391 "cr2res.cr2res_cal_wave", 0.0);
392 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wl_shift");
393 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
394 cpl_parameterlist_append(recipe->parameters, p);
395
396 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.wl_est",
397 CPL_TYPE_STRING, "Estimated wavelength start and end",
398 "cr2res.cr2res_cal_wave", "-1.0, -1.0");
399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wl_est");
400 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
401 cpl_parameterlist_append(recipe->parameters, p);
402
403 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.wl_err",
404 CPL_TYPE_DOUBLE, "Estimated wavelength error (in nm)",
405 "cr2res.cr2res_cal_wave", 0.04);
406 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wl_err");
407 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
408 cpl_parameterlist_append(recipe->parameters, p);
409
410 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.wl_degree",
411 CPL_TYPE_INT, "Wavelength Polynomial degree",
412 "cr2res.cr2res_cal_wave", 0);
413 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wl_degree");
414 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
415 cpl_parameterlist_append(recipe->parameters, p);
416
417 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.log",
418 CPL_TYPE_BOOL, "Flag for taking the Log() value of the lines",
419 "cr2res.cr2res_cal_wave", FALSE);
420 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "log");
421 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
422 cpl_parameterlist_append(recipe->parameters, p);
423
424 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.fallback_input_wavecal",
425 CPL_TYPE_BOOL, "Flag for using the input WL when no computation",
426 "cr2res.cr2res_cal_wave", FALSE);
427 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fallback");
428 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
429 cpl_parameterlist_append(recipe->parameters, p);
430
431 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.keep_higher_degrees",
432 CPL_TYPE_BOOL,
433 "Flag for re-using higher degrees of first guess in Cross-Corr.",
434 "cr2res.cr2res_cal_wave", TRUE);
435 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "keep");
436 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
437 cpl_parameterlist_append(recipe->parameters, p);
438
439 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.save_intermediate",
440 CPL_TYPE_BOOL,
441 "Flag to save UNE results (if UNE and FPET are used as inputs)",
442 "cr2res.cr2res_cal_wave", FALSE);
443 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save");
444 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
445 cpl_parameterlist_append(recipe->parameters, p);
446
447 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.clean_spectrum",
448 CPL_TYPE_BOOL, "Flag to automatically clean the missing lines",
449 "cr2res.cr2res_cal_wave", TRUE);
450 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "clean_spectrum");
451 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
452 cpl_parameterlist_append(recipe->parameters, p);
453
454 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.display",
455 CPL_TYPE_BOOL, "Flag for display",
456 "cr2res.cr2res_cal_wave", FALSE);
457 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "display");
458 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
459 cpl_parameterlist_append(recipe->parameters, p);
460
461 p = cpl_parameter_new_value("cr2res.cr2res_cal_wave.display_range",
462 CPL_TYPE_STRING,
463 "Wavelength range to display [start, end] (in nm)",
464 "cr2res.cr2res_cal_wave", "-1.0, -1.0");
465 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "display_range");
466 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
467 cpl_parameterlist_append(recipe->parameters, p);
468
469 return 0;
470}
471
472/*----------------------------------------------------------------------------*/
478/*----------------------------------------------------------------------------*/
479static int cr2res_cal_wave_exec(cpl_plugin * plugin)
480{
481 cpl_recipe *recipe;
482
483 /* Get the recipe out of the plugin */
484 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
485 recipe = (cpl_recipe *)plugin;
486 else return -1;
487
488 return cr2res_cal_wave(recipe->frames, recipe->parameters);
489}
490
491/*----------------------------------------------------------------------------*/
497/*----------------------------------------------------------------------------*/
498static int cr2res_cal_wave_destroy(cpl_plugin * plugin)
499{
500 cpl_recipe *recipe;
501
502 /* Get the recipe out of the plugin */
503 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
504 recipe = (cpl_recipe *)plugin;
505 else return -1 ;
506
507 cpl_parameterlist_delete(recipe->parameters);
508 return 0 ;
509}
510
511/*----------------------------------------------------------------------------*/
518/*----------------------------------------------------------------------------*/
519static int cr2res_cal_wave(
520 cpl_frameset * frameset,
521 const cpl_parameterlist * parlist)
522{
523 const cpl_parameter * param;
524 int reduce_det, reduce_order, reduce_trace,
525 slit_degree, ext_oversample, ext_swath_width,
526 ext_height, wl_degree, display, log_flag,
527 fallback_input_wavecal_flag,
528 save_intermediate_flag, keep_higher_degrees_flag,
529 clean_spectrum, subtract_nolight_rows,
530 cosmics;
531 double ext_smooth_slit, ext_smooth_spec, wl_start, wl_end,
532 wl_err, wl_shift, display_wmin,
533 display_wmax, central_wlen;
534 cr2res_collapse collapse ;
535 cr2res_wavecal_type wavecal_type ;
536 const char * sval ;
537 cpl_frameset * rawframes_une ;
538 cpl_frameset * rawframes_fpet ;
539 const cpl_frame * detlin_frame ;
540 const cpl_frame * master_dark_frame ;
541 const cpl_frame * master_flat_frame ;
542 const cpl_frame * bpm_frame ;
543 const cpl_frame * trace_wave_frame ;
544 const cpl_frame * lines_frame ;
545 cpl_propertylist * plist ;
546 char * out_file;
547 cpl_table * out_trace_wave_une[CR2RES_NB_DETECTORS] ;
548 cpl_table * lines_diagnostics_une[CR2RES_NB_DETECTORS] ;
549 cpl_table * out_extracted_une[CR2RES_NB_DETECTORS] ;
550 hdrl_image * out_wave_map_une[CR2RES_NB_DETECTORS] ;
551 cpl_propertylist * ext_plist_une[CR2RES_NB_DETECTORS] ;
552 cpl_table * out_trace_wave_fpet[CR2RES_NB_DETECTORS] ;
553 cpl_table * lines_diagnostics_fpet[CR2RES_NB_DETECTORS] ;
554 cpl_table * out_extracted_fpet[CR2RES_NB_DETECTORS] ;
555 hdrl_image * out_wave_map_fpet[CR2RES_NB_DETECTORS] ;
556 cpl_propertylist * ext_plist_fpet[CR2RES_NB_DETECTORS] ;
557 cpl_propertylist * qc_main ;
558 int det_nr, i;
559
560 /* Needed for sscanf() */
561 setlocale(LC_NUMERIC, "C");
562
563 /* Initialise */
564 wl_start = wl_end = -1.0 ;
565
566 collapse = CR2RES_COLLAPSE_UNSPECIFIED ;
567 display_wmin = display_wmax = -1.0 ;
568
569 int qc_sizes[] = {CR2RES_NB_DETECTORS,CR2RES_NB_DETECTORS};
570 cpl_propertylist** qc_plists[] = {ext_plist_une, ext_plist_fpet} ;
571 cpl_propertylist** qc_plists_une[] = {ext_plist_une} ;
572
573 /* RETRIEVE INPUT PARAMETERS */
574 param = cpl_parameterlist_find_const(parlist,
575 "cr2res.cr2res_cal_wave.detector");
576 reduce_det = cpl_parameter_get_int(param);
577 param = cpl_parameterlist_find_const(parlist,
578 "cr2res.cr2res_cal_wave.order");
579 reduce_order = cpl_parameter_get_int(param);
580 param = cpl_parameterlist_find_const(parlist,
581 "cr2res.cr2res_cal_wave.trace_nb");
582 reduce_trace = cpl_parameter_get_int(param);
583 param = cpl_parameterlist_find_const(parlist,
584 "cr2res.cr2res_cal_wave.slit_degree");
585 slit_degree = cpl_parameter_get_int(param);
586 param = cpl_parameterlist_find_const(parlist,
587 "cr2res.cr2res_cal_wave.subtract_nolight_rows");
588 subtract_nolight_rows = cpl_parameter_get_bool(param) ;
589 param = cpl_parameterlist_find_const(parlist,
590 "cr2res.cr2res_cal_wave.cosmics");
591 cosmics = cpl_parameter_get_bool(param);
592 param = cpl_parameterlist_find_const(parlist,
593 "cr2res.cr2res_cal_wave.collapse_method");
594 sval = cpl_parameter_get_string(param);
595 if (!strcmp(sval, "MEAN")) collapse = CR2RES_COLLAPSE_MEAN ;
596 else if (!strcmp(sval, "MEDIAN")) collapse = CR2RES_COLLAPSE_MEDIAN ;
597 if (collapse!=CR2RES_COLLAPSE_MEAN && collapse!=CR2RES_COLLAPSE_MEDIAN) {
598 cpl_msg_error(__func__, "Unsupported collapse method") ;
599 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
600 return -1 ;
601 }
602 param = cpl_parameterlist_find_const(parlist,
603 "cr2res.cr2res_cal_wave.extract_oversample");
604 ext_oversample = cpl_parameter_get_int(param);
605 param = cpl_parameterlist_find_const(parlist,
606 "cr2res.cr2res_cal_wave.extract_swath_width");
607 ext_swath_width = cpl_parameter_get_int(param);
608 param = cpl_parameterlist_find_const(parlist,
609 "cr2res.cr2res_cal_wave.extract_height");
610 ext_height = cpl_parameter_get_int(param);
611 param = cpl_parameterlist_find_const(parlist,
612 "cr2res.cr2res_cal_wave.extract_smooth_slit");
613 ext_smooth_slit = cpl_parameter_get_double(param);
614 param = cpl_parameterlist_find_const(parlist,
615 "cr2res.cr2res_cal_wave.extract_smooth_spec");
616 ext_smooth_spec = cpl_parameter_get_double(param);
617 param = cpl_parameterlist_find_const(parlist,
618 "cr2res.cr2res_cal_wave.wl_method");
619 sval = cpl_parameter_get_string(param) ;
620 if (!strcmp(sval, "XCORR")) wavecal_type = CR2RES_XCORR ;
621 else if (!strcmp(sval, "LINE1D")) wavecal_type = CR2RES_LINE1D ;
622 else if (!strcmp(sval, "LINE2D")) wavecal_type = CR2RES_LINE2D ;
623 else {
624 cpl_msg_error(__func__, "Invalid Method specified");
625 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
626 return -1;
627 }
628 param = cpl_parameterlist_find_const(parlist,
629 "cr2res.cr2res_cal_wave.wl_shift");
630 wl_shift = cpl_parameter_get_double(param) ;
631 param = cpl_parameterlist_find_const(parlist,
632 "cr2res.cr2res_cal_wave.wl_est");
633 sval = cpl_parameter_get_string(param) ;
634 if (sscanf(sval, "%lg,%lg", &wl_start, &wl_end) != 2) {
635 return -1 ;
636 }
637 param = cpl_parameterlist_find_const(parlist,
638 "cr2res.cr2res_cal_wave.wl_err");
639 wl_err = cpl_parameter_get_double(param) ;
640 param = cpl_parameterlist_find_const(parlist,
641 "cr2res.cr2res_cal_wave.wl_degree");
642 wl_degree = cpl_parameter_get_int(param);
643 param = cpl_parameterlist_find_const(parlist,
644 "cr2res.cr2res_cal_wave.log");
645 log_flag = cpl_parameter_get_bool(param) ;
646 param = cpl_parameterlist_find_const(parlist,
647 "cr2res.cr2res_cal_wave.fallback_input_wavecal");
648 fallback_input_wavecal_flag = cpl_parameter_get_bool(param) ;
649 param = cpl_parameterlist_find_const(parlist,
650 "cr2res.cr2res_cal_wave.keep_higher_degrees");
651 keep_higher_degrees_flag = cpl_parameter_get_bool(param) ;
652 param = cpl_parameterlist_find_const(parlist,
653 "cr2res.cr2res_cal_wave.save_intermediate");
654 save_intermediate_flag = cpl_parameter_get_bool(param) ;
655 param = cpl_parameterlist_find_const(parlist,
656 "cr2res.cr2res_cal_wave.clean_spectrum");
657 clean_spectrum = cpl_parameter_get_bool(param) ;
658 param = cpl_parameterlist_find_const(parlist,
659 "cr2res.cr2res_cal_wave.display");
660 display = cpl_parameter_get_bool(param) ;
661 param = cpl_parameterlist_find_const(parlist,
662 "cr2res.cr2res_cal_wave.display_range");
663 sval = cpl_parameter_get_string(param) ;
664 if (sscanf(sval, "%lg,%lg", &display_wmin, &display_wmax) != 2) {
665 return -1 ;
666 }
667
668 /* Check Parameters */
669 if (display==TRUE && (reduce_order==-1 || reduce_det==0)){
670 cpl_msg_warning(__func__,
671 "Option --display can only be used with --order"
672 " and --detector");
673 display=FALSE;
674 }
675 if (wl_degree < 0) {
676 cpl_msg_error(__func__, "The degree needs to be >= 0");
677 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
678 return -1 ;
679 }
680 if (wl_degree == 0 && !keep_higher_degrees_flag) {
681 cpl_msg_error(__func__, "The degree 0 can only be used with --keep");
682 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
683 return -1 ;
684 }
685 if (slit_degree != 1 && slit_degree != 2) {
686 cpl_msg_error(__func__, "The slit fit degree must be 1 or 2");
687 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
688 return -1 ;
689 }
690
691 /* Identify the RAW and CALIB frames in the input frameset */
692 if (cr2res_dfs_set_groups(frameset) != CPL_ERROR_NONE) {
693 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
694 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
695 return -1 ;
696 }
697
698 /* Retrieve calibration data */
699 trace_wave_frame = cr2res_io_find_TRACE_WAVE(frameset) ;
700 if (trace_wave_frame == NULL) {
701 cpl_msg_error(__func__, "Could not find TRACE_WAVE frame") ;
702 return -1 ;
703 }
704 detlin_frame = cpl_frameset_find_const(frameset,
705 CR2RES_CAL_DETLIN_COEFFS_PROCATG);
706 master_dark_frame = cpl_frameset_find_const(frameset,
707 CR2RES_CAL_DARK_MASTER_PROCATG) ;
708 master_flat_frame = cpl_frameset_find_const(frameset,
709 CR2RES_CAL_FLAT_MASTER_PROCATG) ;
710 bpm_frame = cr2res_io_find_BPM(frameset) ;
711 lines_frame = cpl_frameset_find_const(frameset,
712 CR2RES_EMISSION_LINES_PROCATG) ;
713
714 /* Get the RAW Frames */
715 rawframes_une = cr2res_extract_frameset(frameset, CR2RES_WAVE_UNE_RAW) ;
716 rawframes_fpet = cr2res_extract_frameset(frameset, CR2RES_WAVE_FPET_RAW) ;
717 if (rawframes_une == NULL && rawframes_fpet == NULL) {
718 cpl_msg_error(__func__, "Could not find RAW frames") ;
719 return -1 ;
720 }
721 if (lines_frame == NULL && rawframes_une != NULL) {
722 cpl_frameset_delete(rawframes_une) ;
723 if (rawframes_fpet!=NULL) cpl_frameset_delete(rawframes_fpet) ;
724 cpl_msg_error(__func__, "The emission lines catalog is needed");
725 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
726 return -1 ;
727 }
728 if (reduce_order > -1 && wavecal_type == CR2RES_LINE2D) {
729 if (rawframes_une !=NULL) cpl_frameset_delete(rawframes_une) ;
730 if (rawframes_fpet!=NULL) cpl_frameset_delete(rawframes_fpet) ;
731 cpl_msg_error(__func__, "Limiting to one order with LINE2D impossible");
732 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
733 return -1 ;
734 }
735 if (reduce_order > -1 && wavecal_type == CR2RES_ETALON) {
736 if (rawframes_une !=NULL) cpl_frameset_delete(rawframes_une) ;
737 if (rawframes_fpet!=NULL) cpl_frameset_delete(rawframes_fpet) ;
738 cpl_msg_error(__func__, "Limiting to one order with ETALON impossible");
739 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
740 return -1 ;
741 }
742
743 /* Loop over the detectors */
744 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
745
746 /* Initialise */
747 out_trace_wave_une[det_nr-1] = NULL ;
748 lines_diagnostics_une[det_nr-1] = NULL ;
749 out_extracted_une[det_nr-1] = NULL ;
750 out_wave_map_une[det_nr-1] = NULL ;
751 ext_plist_une[det_nr-1] = NULL ;
752
753 out_trace_wave_fpet[det_nr-1] = NULL ;
754 lines_diagnostics_fpet[det_nr-1] = NULL ;
755 out_extracted_fpet[det_nr-1] = NULL ;
756 out_wave_map_fpet[det_nr-1] = NULL ;
757 ext_plist_fpet[det_nr-1] = NULL ;
758
759 /* Compute only one detector but not this one */
760 if (reduce_det != 0 && det_nr != reduce_det) {
761 /* This Detector will not be processed here */
762 /* The output trace wave contains the input one ... */
763 if (rawframes_une != NULL)
764 out_trace_wave_une[det_nr-1] = cr2res_io_load_TRACE_WAVE(
765 cpl_frame_get_filename(trace_wave_frame), det_nr) ;
766 if (rawframes_fpet != NULL)
767 out_trace_wave_fpet[det_nr-1] = cr2res_io_load_TRACE_WAVE(
768 cpl_frame_get_filename(trace_wave_frame), det_nr) ;
769 /* ... without the WL / WL_ERR */
770 /* ... unless fallback_input_wavecal_flag is set */
771
772 if (!fallback_input_wavecal_flag) {
773 /* Reset WL / WL_ERR */
774 if (rawframes_une != NULL) {
775 cpl_table_erase_column(out_trace_wave_une[det_nr-1],
776 CR2RES_COL_WAVELENGTH) ;
777 cpl_table_new_column_array(out_trace_wave_une[det_nr-1],
778 CR2RES_COL_WAVELENGTH, CPL_TYPE_DOUBLE, 2) ;
779 cpl_table_erase_column(out_trace_wave_une[det_nr-1],
780 CR2RES_COL_WAVELENGTH_ERROR) ;
781 cpl_table_new_column_array(out_trace_wave_une[det_nr-1],
782 CR2RES_COL_WAVELENGTH_ERROR, CPL_TYPE_DOUBLE, 2) ;
783 }
784 if (rawframes_fpet != NULL) {
785 cpl_table_erase_column(out_trace_wave_fpet[det_nr-1],
786 CR2RES_COL_WAVELENGTH) ;
787 cpl_table_new_column_array(out_trace_wave_fpet[det_nr-1],
788 CR2RES_COL_WAVELENGTH, CPL_TYPE_DOUBLE, 2) ;
789 cpl_table_erase_column(out_trace_wave_fpet[det_nr-1],
790 CR2RES_COL_WAVELENGTH_ERROR) ;
791 cpl_table_new_column_array(out_trace_wave_fpet[det_nr-1],
792 CR2RES_COL_WAVELENGTH_ERROR, CPL_TYPE_DOUBLE, 2) ;
793 }
794 }
795 continue ;
796 }
797
798 cpl_msg_info(__func__, "Process detector number %d", det_nr) ;
799 cpl_msg_indent_more() ;
800
801 /* For Testing the QCs without re-running all the time */
802 if (0) {
803 out_trace_wave_une[det_nr-1] =
805"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_tw_une.fits",
806 det_nr) ;
807 out_extracted_une[det_nr-1] = cr2res_io_load_EXTRACT_1D(
808"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_extracted_une.fits",
809 det_nr) ;
810 ext_plist_une[det_nr-1] = cpl_propertylist_load(
811"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_extracted_une.fits",
812 det_nr) ;
813 out_trace_wave_fpet[det_nr-1] =
815"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_tw_fpet.fits",
816 det_nr) ;
817 out_extracted_fpet[det_nr-1] =
819"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_extracted_fpet.fits",
820 det_nr) ;
821 ext_plist_fpet[det_nr-1] =
822 cpl_propertylist_load(
823"/home/yjung/P_cr2res/test_cr2res_cal_wave/res/cr2res_cal_wave_extracted_fpet.fits",
824 det_nr) ;
825 lines_diagnostics_une[det_nr-1] = NULL ;
826 out_wave_map_une[det_nr-1] = NULL ;
827 out_wave_map_fpet[det_nr-1] = NULL ;
828 lines_diagnostics_fpet[det_nr-1] = NULL ;
829 } else {
830
831 /* Call the reduction function */
832 if (cr2res_cal_wave_reduce(rawframes_une, rawframes_fpet, detlin_frame,
833 master_dark_frame, master_flat_frame, bpm_frame,
834 trace_wave_frame, lines_frame, det_nr, reduce_order,
835 reduce_trace, slit_degree, subtract_nolight_rows, cosmics,
836 collapse, ext_height, ext_swath_width, ext_oversample,
837 ext_smooth_slit, ext_smooth_spec, wavecal_type, wl_degree,
838 wl_start, wl_end, wl_err, wl_shift, log_flag,
839 fallback_input_wavecal_flag, keep_higher_degrees_flag,
840 clean_spectrum, display, display_wmin,
841 display_wmax,
842 &(out_trace_wave_une[det_nr-1]),
843 &(lines_diagnostics_une[det_nr-1]),
844 &(out_extracted_une[det_nr-1]),
845 &(out_wave_map_une[det_nr-1]),
846 &(ext_plist_une[det_nr-1]),
847 &(out_trace_wave_fpet[det_nr-1]),
848 &(lines_diagnostics_fpet[det_nr-1]),
849 &(out_extracted_fpet[det_nr-1]),
850 &(out_wave_map_fpet[det_nr-1]),
851 &(ext_plist_fpet[det_nr-1])) == -1) {
852 cpl_msg_warning(__func__, "Failed to reduce detector %d", det_nr);
853 cpl_error_reset() ;
854 }
855 }
856
857 cpl_msg_indent_less() ;
858 }
859
860 /* QC Computation */
861 qc_main = cpl_propertylist_new() ;
862
863 cr2res_qc_calculate_mean_and_rmsd(qc_plists, 2, qc_sizes,
864 CR2RES_HEADER_QC_WAVE_CENTWL, qc_main,
865 CR2RES_HEADER_QC_WAVE_CENTWL_AVG, CR2RES_HEADER_QC_WAVE_CENTWL_RMS);
866
867 cr2res_qc_calculate_mean_and_rmsd(qc_plists, 2, qc_sizes,
868 CR2RES_HEADER_QC_WAVE_DISPWL, qc_main,
869 CR2RES_HEADER_QC_WAVE_DISPWL_AVG, CR2RES_HEADER_QC_WAVE_DISPWL_RMS);
870
871 char* qc_une_keywords[] = {
872 CR2RES_HEADER_QC_WAVE_LAMP_EFFIC,
873 CR2RES_HEADER_QC_WAVE_RESOL,
874 CR2RES_HEADER_QC_WAVE_RESOL_FWHM,
875 CR2RES_HEADER_QC_WAVE_POS,
876 CR2RES_HEADER_QC_WAVE_BESTXCORR,
877 CR2RES_HEADER_QC_OVEREXPOSED
878};
879
880
881 int qc_une_keywords_size = sizeof(qc_une_keywords) / sizeof(qc_une_keywords[0]);
882
883 if (rawframes_une != NULL) {
884 plist = cpl_propertylist_load(cpl_frame_get_filename(
885 cpl_frameset_get_position_const(rawframes_une, 0)), 0) ;
886 central_wlen = cr2res_pfits_get_cwlen(plist) ;
887 cpl_propertylist_delete(plist);
888
889 /* QC.UNE.FLUX Computation */
890 if (cr2res_cal_wave_qc_une_flux(
891 (const cpl_table **)out_extracted_une,
892 (const cpl_propertylist **)ext_plist_une,
893 central_wlen, qc_main)) {
894 cpl_msg_warning(__func__, "QC.UNE.FLUX Computation failed") ;
895 }
896
897 /* Should get min and max order_id's from column of all detectors here*/
898 /*int nb_traces = cpl_table_get_nrow(out_trace_wave_une[0]);*/
899
900 int min_order = INT_MAX;
901 int max_order = INT_MIN;
902 int current_min, current_max;
903
904 for (int qc_i = 0; qc_i < CR2RES_NB_DETECTORS; qc_i++) {
905 if (out_trace_wave_une[qc_i] == NULL) {
906 continue;
907 }
908 current_min = cpl_table_get_column_min(out_trace_wave_une[qc_i], "Order");
909 if (cpl_error_get_code() != CPL_ERROR_NONE) {
910 continue;
911 }
912 if (current_min < min_order) {
913 min_order = current_min;
914 }
915
916 current_max = cpl_table_get_column_max(out_trace_wave_une[qc_i], "Order");
917 if (cpl_error_get_code() != CPL_ERROR_NONE) {
918 continue;
919 }
920 if (current_max > max_order) {
921 max_order = current_max;
922 }
923 }
924
925 int qc_j;
926 for (qc_j=0; qc_j<qc_une_keywords_size ; qc_j++) {
927 for (int order_id=min_order ; order_id<=max_order ; order_id++) {
928
929 int qc_sizes_une[] = {CR2RES_NB_DETECTORS};
930 char * qc_ref, * qc_res_avg, * qc_res_rmsd ;
931
932 if(strcmp(qc_une_keywords[qc_j], CR2RES_HEADER_QC_OVEREXPOSED)==0) {
933 qc_ref = cpl_sprintf("%s%02d",
934 qc_une_keywords[qc_j], order_id);
935 qc_res_avg = cpl_sprintf("%s%02d %s",
936 qc_une_keywords[qc_j], order_id, "AVG");
937 qc_res_rmsd = cpl_sprintf("%s%02d %s",
938 qc_une_keywords[qc_j], order_id, "RMS");;
939 }
940 else {
941 qc_ref = cpl_sprintf("%s-%02d-%02d",
942 qc_une_keywords[qc_j], order_id, 1);
943 qc_res_avg = cpl_sprintf("%s-%02d-%02d %s",
944 qc_une_keywords[qc_j], order_id, 1, "AVG");
945 qc_res_rmsd = cpl_sprintf("%s-%02d-%02d %s",
946 qc_une_keywords[qc_j], order_id, 1, "RMS");
947 }
948
949 cr2res_qc_calculate_mean_and_rmsd(qc_plists_une, 1, qc_sizes_une,
950 qc_ref, qc_main,
951 qc_res_avg, qc_res_rmsd);
952
953 cpl_free(qc_ref);
954 cpl_free(qc_res_avg);
955 cpl_free(qc_res_rmsd);
956 }
957 }
958
959 if (cpl_error_get_code() != CPL_ERROR_NONE) {
960 cpl_msg_error(__func__, "Failed to set QC params for UNE: %s",
961 cpl_error_get_message_default ( cpl_error_get_code())) ;
962 return -1 ;
963 }
964
965 }
966
967 if (rawframes_fpet != NULL) {
968 plist = cpl_propertylist_load(cpl_frame_get_filename(
969 cpl_frameset_get_position_const(rawframes_fpet, 0)), 0) ;
970 central_wlen = cr2res_pfits_get_cwlen(plist) ;
971 cpl_propertylist_delete(plist);
972
973 /* QC.TILT Computation */
974 if (cr2res_cal_wave_qc_tilt((const cpl_table **)out_trace_wave_fpet,
975 central_wlen, qc_main)) {
976 cpl_msg_warning(__func__, "QC.TILT Computation failed") ;
977 }
978 /* QC.FPI Computation */
979 if (cr2res_cal_wave_qc_fpi(
980 (const cpl_table **)out_extracted_fpet,
981 (const cpl_table **)out_trace_wave_fpet,
982 (const cpl_propertylist **)ext_plist_fpet,
983 central_wlen, qc_main)) {
984 cpl_msg_warning(__func__, "QC.FPI Computation failed") ;
985 }
986 }
987
988 /* Save only the used RAW ? : rawframes_xxx instead of 2nd frameset */
989 /* Beware that the calibration PRO RECi CAL will be missing */
990
991 /* Save Products UNE */
992 if (rawframes_une != NULL &&
993 (rawframes_fpet == NULL || // UNE is the main product
994 save_intermediate_flag)) {
995 out_file = cpl_sprintf("%s_tw_une.fits", RECIPE_STRING) ;
996 cr2res_io_save_TRACE_WAVE(out_file, frameset, frameset, parlist,
997 out_trace_wave_une, qc_main, ext_plist_une,
998 CR2RES_CAL_WAVE_TW_PROCATG, RECIPE_STRING) ;
999 cpl_free(out_file);
1000
1001 out_file = cpl_sprintf("%s_wave_map_une.fits", RECIPE_STRING) ;
1002 cr2res_io_save_WAVE_MAP(out_file, frameset, frameset, parlist,
1003 out_wave_map_une, qc_main, ext_plist_une,
1004 CR2RES_CAL_WAVE_MAP_PROCATG, RECIPE_STRING) ;
1005 cpl_free(out_file);
1006
1007 out_file = cpl_sprintf("%s_extracted_une.fits", RECIPE_STRING) ;
1008 cr2res_io_save_EXTRACT_1D(out_file, frameset, frameset, parlist,
1009 out_extracted_une, qc_main, ext_plist_une,
1010 CR2RES_CAL_WAVE_EXTRACT_1D_PROCATG, RECIPE_STRING) ;
1011 cpl_free(out_file);
1012
1013 out_file = cpl_sprintf("%s_lines_diagnostics_une.fits",
1014 RECIPE_STRING);
1015 cr2res_io_save_LINES_DIAGNOSTICS(out_file, frameset, frameset,
1016 parlist, lines_diagnostics_une, qc_main, ext_plist_une,
1017 CR2RES_CAL_WAVE_LINES_DIAGNOSTICS_PROCATG, RECIPE_STRING) ;
1018 cpl_free(out_file);
1019 }
1020
1021 if (rawframes_fpet != NULL) {
1022 /* Save Products FPET */
1023 out_file = cpl_sprintf("%s_tw_fpet.fits", RECIPE_STRING) ;
1024 cr2res_io_save_TRACE_WAVE(out_file, frameset, frameset, parlist,
1025 out_trace_wave_fpet, qc_main, ext_plist_fpet,
1026 CR2RES_CAL_WAVE_TW_PROCATG, RECIPE_STRING) ;
1027 cpl_free(out_file);
1028
1029 out_file = cpl_sprintf("%s_wave_map_fpet.fits", RECIPE_STRING) ;
1030 cr2res_io_save_WAVE_MAP(out_file, frameset, frameset, parlist,
1031 out_wave_map_fpet, qc_main, ext_plist_fpet,
1032 CR2RES_CAL_WAVE_MAP_PROCATG, RECIPE_STRING) ;
1033 cpl_free(out_file);
1034
1035 out_file = cpl_sprintf("%s_extracted_fpet.fits", RECIPE_STRING) ;
1036 cr2res_io_save_EXTRACT_1D(out_file, frameset, frameset, parlist,
1037 out_extracted_fpet, qc_main, ext_plist_fpet,
1038 CR2RES_CAL_WAVE_EXTRACT_1D_PROCATG, RECIPE_STRING) ;
1039 cpl_free(out_file);
1040
1041 out_file = cpl_sprintf("%s_lines_diagnostics_fpet.fits",
1042 RECIPE_STRING);
1043 cr2res_io_save_LINES_DIAGNOSTICS(out_file, frameset, frameset, parlist,
1044 lines_diagnostics_fpet, qc_main, ext_plist_fpet,
1045 CR2RES_CAL_WAVE_LINES_DIAGNOSTICS_PROCATG, RECIPE_STRING) ;
1046 cpl_free(out_file);
1047 }
1048
1049 /* Free and return */
1050 cpl_propertylist_delete(qc_main) ;
1051 cpl_frameset_delete(rawframes_une) ;
1052 if (rawframes_fpet!=NULL) cpl_frameset_delete(rawframes_fpet) ;
1053 for (i=0 ; i<CR2RES_NB_DETECTORS ; i++) {
1054 if (ext_plist_une[i] != NULL)
1055 cpl_propertylist_delete(ext_plist_une[i]) ;
1056 if (out_trace_wave_une[i] != NULL)
1057 cpl_table_delete(out_trace_wave_une[i]) ;
1058 if (lines_diagnostics_une[i] != NULL)
1059 cpl_table_delete(lines_diagnostics_une[i]) ;
1060 if (out_extracted_une[i] != NULL)
1061 cpl_table_delete(out_extracted_une[i]) ;
1062 if (out_wave_map_une[i] != NULL)
1063 hdrl_image_delete(out_wave_map_une[i]) ;
1064 if (ext_plist_fpet[i] != NULL)
1065 cpl_propertylist_delete(ext_plist_fpet[i]) ;
1066 if (out_trace_wave_fpet[i] != NULL)
1067 cpl_table_delete(out_trace_wave_fpet[i]) ;
1068 if (lines_diagnostics_fpet[i] != NULL)
1069 cpl_table_delete(lines_diagnostics_fpet[i]) ;
1070 if (out_extracted_fpet[i] != NULL)
1071 cpl_table_delete(out_extracted_fpet[i]) ;
1072 if (out_wave_map_fpet[i] != NULL)
1073 hdrl_image_delete(out_wave_map_fpet[i]) ;
1074 }
1075 return (int)cpl_error_get_code();
1076}
1077
1078/*----------------------------------------------------------------------------*/
1127/*----------------------------------------------------------------------------*/
1128static int cr2res_cal_wave_reduce(
1129 const cpl_frameset * rawframes_une,
1130 const cpl_frameset * rawframes_fpet,
1131 const cpl_frame * detlin_frame,
1132 const cpl_frame * master_dark_frame,
1133 const cpl_frame * master_flat_frame,
1134 const cpl_frame * bpm_frame,
1135 const cpl_frame * trace_wave_frame,
1136 const cpl_frame * lines_frame,
1137 int reduce_det,
1138 int reduce_order,
1139 int reduce_trace,
1140 int slit_degree,
1141 int subtract_nolight_rows,
1142 int cosmics,
1143 cr2res_collapse collapse,
1144 int ext_height,
1145 int ext_swath_width,
1146 int ext_oversample,
1147 double ext_smooth_slit,
1148 double ext_smooth_spec,
1149 cr2res_wavecal_type wavecal_type,
1150 int wl_degree,
1151 double wl_start,
1152 double wl_end,
1153 double wl_err,
1154 double wl_shift,
1155 int log_flag,
1156 int fallback_input_wavecal_flag,
1157 int keep_higher_degrees_flag,
1158 int clean_spectrum,
1159 int display,
1160 double display_wmin,
1161 double display_wmax,
1162 cpl_table ** out_trace_wave_une,
1163 cpl_table ** lines_diagnostics_une,
1164 cpl_table ** out_extracted_une,
1165 hdrl_image ** out_wave_map_une,
1166 cpl_propertylist ** ext_plist_une,
1167 cpl_table ** out_trace_wave_fpet,
1168 cpl_table ** lines_diagnostics_fpet,
1169 cpl_table ** out_extracted_fpet,
1170 hdrl_image ** out_wave_map_fpet,
1171 cpl_propertylist ** ext_plist_fpet)
1172{
1173 cpl_vector * ndits_fpet ;
1174 hdrl_imagelist * in_fpet ;
1175 hdrl_imagelist * in_fpet_calib ;
1176 hdrl_image * collapsed_une ;
1177 hdrl_image * collapsed_fpet ;
1178 cpl_image * contrib ;
1179 cpl_table * tw_in ;
1180 cpl_table * extracted_une ;
1181 cpl_table * slit_func_une ;
1182 hdrl_image * model_master_une ;
1183 cpl_table * extracted_fpet ;
1184 cpl_table * slit_func_fpet ;
1185 hdrl_image * model_master_fpet ;
1186 hdrl_image * wl_map_une_out ;
1187 cpl_table * tw_une_out ;
1188 cpl_table * lines_diagnostics_une_out ;
1189 cpl_table * extracted_une_out ;
1190 cpl_propertylist * qcs_une_out ;
1191 cpl_propertylist * plist_une_out ;
1192 hdrl_image * wl_map_fpet_out ;
1193 cpl_table * tw_fpet_out ;
1194 cpl_table * lines_diagnostics_fpet_out ;
1195 cpl_table * extracted_fpet_out ;
1196 cpl_propertylist * qcs_fpet_out ;
1197 cpl_propertylist * plist_fpet_out ;
1198 cpl_propertylist * plist ;
1199 const char * first_file ;
1200 cpl_polynomial * slit_polya ;
1201 cpl_polynomial * slit_polyb ;
1202 cpl_polynomial * slit_polyc ;
1203 double gain, error_factor ;
1204 int i, order, trace_id, ext_nr,
1205 zp_order_fpet, nb_traces,
1206 grat1_order_fpet ;
1207
1208 /* TODO, make parameters */
1209 int extract_niter = 10;
1210 double extract_kappa = 10;
1211
1212 /* Check Inputs */
1213 if (rawframes_fpet==NULL && rawframes_une==NULL) return -1 ;
1214 if (trace_wave_frame==NULL || out_trace_wave_une==NULL ||
1215 out_trace_wave_fpet==NULL || lines_diagnostics_une == NULL ||
1216 lines_diagnostics_fpet == NULL || out_extracted_une == NULL ||
1217 out_extracted_fpet == NULL || out_wave_map_une == NULL ||
1218 out_wave_map_fpet == NULL || ext_plist_une == NULL ||
1219 ext_plist_fpet == NULL) return -1 ;
1220 if (collapse!=CR2RES_COLLAPSE_MEAN && collapse!=CR2RES_COLLAPSE_MEDIAN)
1221 return -1 ;
1222
1223 /* Get the Gain */
1224 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
1225 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
1226 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
1227 else {
1228 cpl_msg_error(__func__, "Failed to get the Gain value") ;
1229 return -1 ;
1230 }
1231
1232
1233 /* Compute the Slit Curvature using the first passed FPET frame */
1234 tw_in = NULL ;
1235 if (rawframes_fpet != NULL) {
1236
1237 const cpl_frame * fpet_frame ;
1238 const char * fpet_fname ;
1239 hdrl_image * fpet_image ;
1240
1241 fpet_frame = cpl_frameset_get_position_const(rawframes_fpet, 0) ;
1242 fpet_fname = cpl_frame_get_filename(fpet_frame) ;
1243 cpl_msg_info(__func__,
1244 "Compute the Slit Curvature from the first FPET frame %s",
1245 fpet_fname) ;
1246 cpl_msg_indent_more() ;
1247
1248 /* Load the trace wave */
1249 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
1250 if ((tw_in = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(
1251 trace_wave_frame), reduce_det)) == NULL) {
1252 cpl_msg_error(__func__, "Failed to Load the traces file") ;
1253 cpl_msg_indent_less() ;
1254 return -1 ;
1255 }
1256
1257 /* Load the FPET image of this detector */
1258 cpl_msg_info(__func__, "Load the FPET image") ;
1259 if ((fpet_image = cr2res_io_load_image(fpet_fname, reduce_det))==NULL) {
1260 cpl_msg_error(__func__, "Failed to load image") ;
1261 cpl_table_delete(tw_in) ;
1262 cpl_msg_indent_less() ;
1263 return -1 ;
1264 }
1265
1266 /* Loop over the traces and get the slit curvature */
1267 nb_traces = cpl_table_get_nrow(tw_in) ;
1268 for (i=0 ; i<nb_traces ; i++) {
1269 /* Get Order and trace id */
1270 order = cpl_table_get(tw_in, CR2RES_COL_ORDER, i, NULL) ;
1271 trace_id = cpl_table_get(tw_in, CR2RES_COL_TRACENB, i, NULL) ;
1272
1273 /* Check if this order needs to be skipped */
1274 if (reduce_order > -1 && order != reduce_order) continue ;
1275
1276 /* Check if this trace needs to be skipped */
1277 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1278
1279 cpl_msg_info(__func__, "Process Order %d/Trace %d",order,trace_id) ;
1280 cpl_msg_indent_more() ;
1281
1282 /* Call the Slit Curvature Computation */
1283 /* TODO : Should those become parameters ? */
1284 int height = 100 ;
1285 int window = 15 ;
1286 int change_degree = 1;
1287 if (cr2res_slit_curv_compute_order_trace(fpet_image, tw_in, order,
1288 trace_id, height, window, change_degree, slit_degree,
1289 &slit_polya, &slit_polyb, &slit_polyc)) {
1290 cpl_msg_error(__func__, "Failed to compute slit curvature") ;
1291 cpl_table_delete(tw_in) ;
1292 hdrl_image_delete(fpet_image) ;
1293 cpl_msg_indent_less() ;
1294 return -1 ;
1295 }
1296
1297 cpl_array * slit_array ;
1298 /* Fill the SLIT_CURVE_A/B/C for the current trace */
1299 slit_array = cr2res_convert_poly_to_array(slit_polya, 3) ;
1300 cpl_polynomial_delete(slit_polya) ;
1301 cpl_table_set_array(tw_in, CR2RES_COL_SLIT_CURV_A, i, slit_array) ;
1302 cpl_array_delete(slit_array) ;
1303 slit_array = cr2res_convert_poly_to_array(slit_polyb, 3) ;
1304 cpl_polynomial_delete(slit_polyb) ;
1305 cpl_table_set_array(tw_in, CR2RES_COL_SLIT_CURV_B, i, slit_array) ;
1306 cpl_array_delete(slit_array) ;
1307 slit_array = cr2res_convert_poly_to_array(slit_polyc, 3) ;
1308 cpl_polynomial_delete(slit_polyc) ;
1309 cpl_table_set_array(tw_in, CR2RES_COL_SLIT_CURV_C, i, slit_array) ;
1310 cpl_array_delete(slit_array) ;
1311
1312 cpl_msg_indent_less() ;
1313 }
1314 hdrl_image_delete(fpet_image) ;
1315 cpl_msg_indent_less() ;
1316 }
1317
1318 /*
1319 At this point : tw_in is NULL or it is the input TW with the
1320 newly computed slit curvature
1321 */
1322
1323 /* Reduce the UNE */
1324 if (rawframes_une != NULL) {
1325
1326 cpl_vector * dits_une ;
1327 cpl_vector * ndits_une ;
1328 hdrl_imagelist * in_une ;
1329 hdrl_imagelist * in_une_calib ;
1330 hdrl_image * first_image ;
1331 int zp_order_une, grat1_order_une ;
1332
1333 cpl_msg_info(__func__, "Reduce %"CPL_SIZE_FORMAT" UNE Frames",
1334 cpl_frameset_get_size(rawframes_une)) ;
1335 cpl_msg_indent_more() ;
1336
1337 /* Load the UNE DITs if necessary */
1338 if (master_dark_frame != NULL)
1339 dits_une = cr2res_io_read_dits(rawframes_une) ;
1340 else
1341 dits_une = NULL ;
1342 if (cpl_msg_get_level() == CPL_MSG_DEBUG && dits_une != NULL)
1343 cpl_vector_dump(dits_une, stdout) ;
1344
1345 /*Load the NDITs */
1346 ndits_une = cr2res_io_read_ndits(rawframes_une);
1347
1348 /* Set the error factor. */
1349 error_factor = gain * cpl_vector_get(ndits_une, 0) *
1350 cpl_frameset_get_size(rawframes_une) ;
1351
1352 for (i=0; i<cpl_vector_get_size(ndits_une); i++){
1353 if (cpl_vector_get(ndits_une,i) != cpl_vector_get(ndits_une, 0))
1354 cpl_msg_warning(__func__, "UNE raw frames have different NDIT! "
1355 "Error spectrum will likely be scaled incorrectly.");
1356 }
1357
1358 /* Load UNE image list */
1359 if ((in_une = cr2res_io_load_image_list_from_set(rawframes_une,
1360 reduce_det)) == NULL) {
1361 cpl_msg_error(__func__, "Cannot load images") ;
1362 if (dits_une != NULL) cpl_vector_delete(dits_une) ;
1363 if (tw_in != NULL) cpl_table_delete(tw_in);
1364 cpl_msg_indent_less() ;
1365 return -1 ;
1366 }
1367 if (hdrl_imagelist_get_size(in_une) !=
1368 cpl_frameset_get_size(rawframes_une)) {
1369 cpl_msg_error(__func__, "Inconsistent number of loaded images") ;
1370 if (dits_une != NULL) cpl_vector_delete(dits_une) ;
1371 hdrl_imagelist_delete(in_une) ;
1372 if (tw_in != NULL) cpl_table_delete(tw_in);
1373 cpl_msg_indent_less() ;
1374 return -1 ;
1375 }
1376 /* Calibrate the UNE images */
1377 if ((in_une_calib = cr2res_calib_imagelist(in_une, reduce_det, 0,
1378 subtract_nolight_rows, 1, cosmics, master_flat_frame,
1379 master_dark_frame, bpm_frame, detlin_frame,
1380 dits_une, ndits_une)) == NULL) {
1381 cpl_msg_error(__func__, "Failed to apply the calibrations") ;
1382 if (dits_une != NULL) cpl_vector_delete(dits_une) ;
1383 if (ndits_une != NULL) cpl_vector_delete(ndits_une) ;
1384 hdrl_imagelist_delete(in_une) ;
1385 if (tw_in != NULL) cpl_table_delete(tw_in);
1386 cpl_msg_indent_less() ;
1387 return -1 ;
1388 }
1389 hdrl_imagelist_delete(in_une) ;
1390 if (dits_une != NULL) cpl_vector_delete(dits_une) ;
1391 if (ndits_une != NULL) cpl_vector_delete(ndits_une) ;
1392
1393 /* Collapse UNE */
1394 contrib = NULL ;
1395 if (collapse == CR2RES_COLLAPSE_MEAN) {
1396 cpl_msg_info(__func__, "Collapse (Mean) the input UNE frames") ;
1397 cpl_msg_indent_more() ;
1398 hdrl_imagelist_collapse_mean(in_une_calib, &collapsed_une,
1399 &contrib) ;
1400 cpl_msg_indent_less() ;
1401 } else if (collapse == CR2RES_COLLAPSE_MEDIAN) {
1402 cpl_msg_info(__func__, "Collapse (Median) the input UNE frames") ;
1403 cpl_msg_indent_more() ;
1404 hdrl_imagelist_collapse_median(in_une_calib, &collapsed_une,
1405 &contrib) ;
1406 cpl_msg_indent_less() ;
1407 } else {
1408 /* Should never happen */
1409 collapsed_une = NULL ;
1410 contrib = NULL ;
1411 }
1412 hdrl_imagelist_delete(in_une_calib) ;
1413 if (contrib != NULL) cpl_image_delete(contrib) ;
1414 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1415 cpl_msg_error(__func__, "Failed Collapse: %d",
1416 cpl_error_get_code());
1417 cpl_msg_indent_less() ;
1418 if (tw_in != NULL) cpl_table_delete(tw_in);
1419 return -1 ;
1420 }
1421
1422 /* Load the trace wave */
1423 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
1424 if (tw_in == NULL)
1425 if ((tw_in = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(
1426 trace_wave_frame), reduce_det)) == NULL) {
1427 cpl_msg_error(__func__, "Failed to Load the traces file") ;
1428 hdrl_image_delete(collapsed_une) ;
1429 cpl_msg_indent_less() ;
1430 return -1 ;
1431 }
1432
1433 /* Execute the extraction for UNE */
1434 cpl_msg_info(__func__, "Spectra Extraction UNE") ;
1435 cpl_msg_indent_more() ;
1436 if (cr2res_extract_traces(collapsed_une, tw_in, NULL, NULL, 0,
1437 reduce_order, reduce_trace, CR2RES_EXTR_OPT_CURV,
1438 ext_height, ext_swath_width, ext_oversample,
1439 ext_smooth_slit, ext_smooth_spec,
1440 extract_niter, extract_kappa, error_factor, 0, 0, 0,
1441 &extracted_une, &slit_func_une, &model_master_une) == -1) {
1442 cpl_msg_error(__func__, "Failed to extract");
1443 hdrl_image_delete(collapsed_une) ;
1444 cpl_table_delete(tw_in) ;
1445 cpl_msg_indent_less() ;
1446 cpl_msg_indent_less() ;
1447 return -1 ;
1448 }
1449 cpl_msg_indent_less() ;
1450 cpl_table_delete(slit_func_une) ;
1451 hdrl_image_delete(model_master_une) ;
1452 hdrl_image_delete(collapsed_une);
1453
1454 /* Compute the Wavelength Calibration for UNE */
1455 first_file = cpl_frame_get_filename(
1456 cpl_frameset_get_position_const(rawframes_une, 0)) ;
1457 plist = cpl_propertylist_load(first_file, 0) ;
1458 zp_order_une = cr2res_pfits_get_order_zp(plist) ;
1459 grat1_order_une = cr2res_pfits_get_order(plist) ;
1460 cpl_propertylist_delete(plist);
1461
1462 cpl_msg_info(__func__, "Compute the Wavelength for UNE") ;
1463 cpl_msg_indent_more() ;
1464 if (cr2res_wave_apply(tw_in, extracted_une, lines_frame, reduce_order,
1465 reduce_trace, wavecal_type, wl_degree, -1, // xdegree
1466 wl_start, wl_end,
1467 wl_err, wl_shift, log_flag, fallback_input_wavecal_flag,
1468 keep_higher_degrees_flag, clean_spectrum,
1469 display, display_wmin, display_wmax, zp_order_une,
1470 grat1_order_une,
1471 &qcs_une_out,
1472 &lines_diagnostics_une_out,
1473 &extracted_une_out,
1474 &tw_une_out) || cpl_error_get_code()) {
1475 cpl_msg_error(__func__, "Failed to calibrate");
1476 cpl_table_delete(tw_in) ;
1477 cpl_table_delete(extracted_une) ;
1478 cpl_msg_indent_less() ;
1479 cpl_msg_indent_less() ;
1480 return -1 ;
1481 }
1482 cpl_msg_indent_less() ;
1483 cpl_table_delete(extracted_une) ;
1484
1485 /* Generate the Wave Map */
1486 wl_map_une_out = cr2res_wave_gen_wave_map(tw_une_out) ;
1487
1488 /* Load the extension header for saving UNE*/
1489 first_file = cpl_frame_get_filename(
1490 cpl_frameset_get_position_const(rawframes_une, 0)) ;
1491 ext_nr = cr2res_io_get_ext_idx(first_file, reduce_det, 1) ;
1492 plist_une_out = cpl_propertylist_load(first_file, ext_nr) ;
1493 if (plist_une_out == NULL) {
1494 cpl_propertylist_delete(qcs_une_out) ;
1495 cpl_table_delete(tw_in) ;
1496 cpl_table_delete(tw_une_out) ;
1497 cpl_table_delete(lines_diagnostics_une_out) ;
1498 cpl_table_delete(extracted_une_out) ;
1499 hdrl_image_delete(wl_map_une_out) ;
1500 cpl_msg_error(__func__, "Failed to load the plist") ;
1501 cpl_msg_indent_less() ;
1502 return -1 ;
1503 }
1504
1505 /* Load the first RAW image and compute QC OVEREXPOSED */
1506 first_image = cr2res_io_load_image(first_file,reduce_det) ;
1507
1508 /* QC.OVEREXPOSED */
1509 /* Loop on the traces */
1510 nb_traces = cpl_table_get_nrow(tw_in) ;
1511 for (i=0 ; i<nb_traces ; i++) {
1512 /* Get Order and trace id */
1513 order = cpl_table_get(tw_in, CR2RES_COL_ORDER, i, NULL) ;
1514 trace_id = cpl_table_get(tw_in, CR2RES_COL_TRACENB, i, NULL) ;
1515
1516 /* Check if this order needs to be skipped */
1517 if (reduce_order > -1 && order != reduce_order) continue ;
1518
1519 /* Check if this trace needs to be skipped */
1520 if (reduce_trace > -1 && trace_id != reduce_trace) continue ;
1521
1522 double qc_overexposed;
1523 qc_overexposed = cr2res_qc_overexposed(
1524 hdrl_image_get_image(first_image), tw_in, order) ;
1525 char * qc_name = cpl_sprintf("%s%02d",
1526 CR2RES_HEADER_QC_OVEREXPOSED, order) ;
1527 if (qcs_une_out == NULL) qcs_une_out = cpl_propertylist_new() ;
1528 cpl_propertylist_append_double(qcs_une_out, qc_name,qc_overexposed);
1529 cpl_free(qc_name) ;
1530 }
1531 hdrl_image_delete(first_image) ;
1532
1533 if (qcs_une_out != NULL) {
1534 cpl_propertylist_append(plist_une_out, qcs_une_out) ;
1535 cpl_propertylist_delete(qcs_une_out) ;
1536 }
1537 cpl_msg_indent_less() ;
1538 } else {
1539 tw_une_out = NULL ;
1540 lines_diagnostics_une_out = NULL ;
1541 extracted_une_out = NULL ;
1542 wl_map_une_out = NULL ;
1543 plist_une_out = NULL ;
1544 }
1545
1546 /*
1547 At this point : tw_in is NULL or it is the input TW with the
1548 newly computed slit curvature
1549 */
1550
1551 /* Reduce the FPET */
1552 if (rawframes_fpet != NULL && reduce_order != -1){
1553 cpl_msg_warning(__func__,
1554 "Etalon wavecal requires all orders to be used, skipping it.");
1555 if (tw_in != NULL) cpl_table_delete(tw_in);
1556 tw_fpet_out = NULL ;
1557 lines_diagnostics_fpet_out = NULL ;
1558 extracted_fpet_out = NULL ;
1559 wl_map_fpet_out = NULL ;
1560 plist_fpet_out = NULL ;
1561 } else if (rawframes_fpet != NULL) {
1562 cpl_msg_info(__func__, "Reduce %"CPL_SIZE_FORMAT" FPET Frames",
1563 cpl_frameset_get_size(rawframes_fpet)) ;
1564 cpl_msg_indent_more() ;
1565
1566 /* Load FPET image list */
1567 if ((in_fpet = cr2res_io_load_image_list_from_set(rawframes_fpet,
1568 reduce_det)) == NULL) {
1569 cpl_msg_error(__func__, "Cannot load images") ;
1570 cpl_msg_indent_less() ;
1571 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1572 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1573 if (lines_diagnostics_une_out != NULL)
1574 cpl_table_delete(lines_diagnostics_une_out) ;
1575 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1576 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1577 return -1 ;
1578 }
1579 if (hdrl_imagelist_get_size(in_fpet) !=
1580 cpl_frameset_get_size(rawframes_fpet)) {
1581 cpl_msg_error(__func__, "Inconsistent number of loaded images") ;
1582 cpl_msg_indent_less() ;
1583 hdrl_imagelist_delete(in_fpet) ;
1584 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1585 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1586 if (lines_diagnostics_une_out != NULL)
1587 cpl_table_delete(lines_diagnostics_une_out) ;
1588 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1589 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1590 return -1 ;
1591 }
1592
1593 /* Load FPET NDITs*/
1594 ndits_fpet = cr2res_io_read_ndits(rawframes_fpet);
1595
1596 /* Set the error factor. */
1597 error_factor = gain * cpl_vector_get(ndits_fpet, 0) *
1598 cpl_frameset_get_size(rawframes_une) ;
1599
1600 for (i=0; i<cpl_vector_get_size(ndits_fpet); i++){
1601 if (cpl_vector_get(ndits_fpet,i) != cpl_vector_get(ndits_fpet, 0))
1602 cpl_msg_warning(__func__, "FPET raw frames have different NDIT! "
1603 "Error spectrum will likely be scaled incorrectly.");
1604 }
1605
1606 /* Calibrate the FPET images */
1607 if ((in_fpet_calib = cr2res_calib_imagelist(in_fpet, reduce_det, 0,
1608 subtract_nolight_rows, 0, cosmics, master_flat_frame,
1609 NULL, bpm_frame, detlin_frame, NULL,
1610 ndits_fpet)) == NULL) {
1611 cpl_msg_error(__func__, "Failed to apply the calibrations") ;
1612 cpl_msg_indent_less() ;
1613 if (in_fpet != NULL) hdrl_imagelist_delete(in_fpet) ;
1614 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1615 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1616 if (lines_diagnostics_une_out != NULL)
1617 cpl_table_delete(lines_diagnostics_une_out) ;
1618 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1619 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1620 if (ndits_fpet != NULL) cpl_vector_delete(ndits_fpet) ;
1621 return -1 ;
1622 }
1623 hdrl_imagelist_delete(in_fpet) ;
1624 if (ndits_fpet != NULL) cpl_vector_delete(ndits_fpet) ;
1625
1626 /* Collapse FPET */
1627 contrib = NULL ;
1628 if (collapse == CR2RES_COLLAPSE_MEAN) {
1629 cpl_msg_info(__func__, "Collapse (Mean) the input FPET frames") ;
1630 cpl_msg_indent_more() ;
1631 hdrl_imagelist_collapse_mean(in_fpet_calib, &collapsed_fpet,
1632 &contrib) ;
1633 cpl_msg_indent_less() ;
1634 } else if (collapse == CR2RES_COLLAPSE_MEDIAN) {
1635 cpl_msg_info(__func__, "Collapse (Median) the input FPET frames") ;
1636 cpl_msg_indent_more() ;
1637 hdrl_imagelist_collapse_median(in_fpet_calib, &collapsed_fpet,
1638 &contrib) ;
1639 cpl_msg_indent_less() ;
1640 } else {
1641 /* Should never happen */
1642 collapsed_fpet = NULL ;
1643 contrib = NULL ;
1644 }
1645 hdrl_imagelist_delete(in_fpet_calib) ;
1646 if (contrib != NULL) cpl_image_delete(contrib) ;
1647 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1648 cpl_msg_error(__func__,
1649 "Failed Collapse: %d", cpl_error_get_code()) ;
1650 if (collapsed_fpet != NULL) hdrl_image_delete(collapsed_fpet) ;
1651 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1652 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1653 if (lines_diagnostics_une_out != NULL)
1654 cpl_table_delete(lines_diagnostics_une_out) ;
1655 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1656 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1657 cpl_msg_indent_less() ;
1658 return -1 ;
1659 }
1660
1661 /* Get the trace wave */
1662 if (tw_une_out != NULL) {
1663 cpl_msg_info(__func__, "Use the UNE output TRACE WAVE") ;
1664 if (tw_in != NULL) cpl_table_delete(tw_in);
1665 tw_in = cpl_table_duplicate(tw_une_out) ;
1666 } else {
1667 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
1668 if (tw_in == NULL)
1669 if ((tw_in = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(
1670 trace_wave_frame), reduce_det)) == NULL) {
1671 cpl_msg_error(__func__, "Failed to Load the traces file") ;
1672 if (collapsed_fpet != NULL)
1673 hdrl_image_delete(collapsed_fpet) ;
1674 if (plist_une_out != NULL)
1675 cpl_propertylist_delete(plist_une_out) ;
1676 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1677 if (lines_diagnostics_une_out != NULL)
1678 cpl_table_delete(lines_diagnostics_une_out) ;
1679 if (extracted_une_out != NULL)
1680 cpl_table_delete(extracted_une_out) ;
1681 if (wl_map_une_out != NULL)
1682 hdrl_image_delete(wl_map_une_out) ;
1683 cpl_msg_indent_less() ;
1684 return -1 ;
1685 }
1686 }
1687
1688 /* Execute the extraction for FPET */
1689 cpl_msg_info(__func__, "Spectra Extraction FPET") ;
1690 cpl_msg_indent_more() ;
1691 if (cr2res_extract_traces(collapsed_fpet, tw_in, NULL, NULL, 0,
1692 reduce_order, reduce_trace, CR2RES_EXTR_OPT_CURV,
1693 ext_height, ext_swath_width, ext_oversample,
1694 ext_smooth_slit, ext_smooth_spec,
1695 extract_niter, extract_kappa, error_factor, 0, 0, 0,
1696 &extracted_fpet, &slit_func_fpet, &model_master_fpet)==-1) {
1697 cpl_msg_error(__func__, "Failed to extract");
1698 cpl_table_delete(tw_in) ;
1699 if (collapsed_fpet != NULL) hdrl_image_delete(collapsed_fpet) ;
1700 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1701 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1702 if (lines_diagnostics_une_out != NULL)
1703 cpl_table_delete(lines_diagnostics_une_out) ;
1704 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1705 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1706 cpl_msg_indent_less() ;
1707 cpl_msg_indent_less() ;
1708 return -1 ;
1709 }
1710 cpl_msg_indent_less() ;
1711 cpl_table_delete(slit_func_fpet) ;
1712 hdrl_image_delete(model_master_fpet) ;
1713 hdrl_image_delete(collapsed_fpet);
1714
1715 /* Compute the Wavelength Calibration for FPET */
1716 first_file = cpl_frame_get_filename(
1717 cpl_frameset_get_position_const(rawframes_fpet, 0)) ;
1718 plist = cpl_propertylist_load(first_file, 0) ;
1719 zp_order_fpet = cr2res_pfits_get_order_zp(plist) ;
1720 grat1_order_fpet = cr2res_pfits_get_order(plist) ;
1721 cpl_propertylist_delete(plist);
1722
1723 cpl_msg_info(__func__, "Compute the Wavelength for FPET") ;
1724 cpl_msg_indent_more() ;
1725 cpl_msg_info(__func__, "Running FPET with degrees=4,6") ;
1726
1727 if (cr2res_wave_apply(tw_in, extracted_fpet, NULL, reduce_order,
1728 reduce_trace, CR2RES_ETALON, 4, 6, wl_start, wl_end,
1729 wl_err, wl_shift, log_flag, fallback_input_wavecal_flag,
1730 FALSE, // --keep=FALSE
1731 clean_spectrum,
1732 display, display_wmin, display_wmax, zp_order_fpet,
1733 grat1_order_fpet,
1734 &qcs_fpet_out,
1735 &lines_diagnostics_fpet_out,
1736 &extracted_fpet_out,
1737 &tw_fpet_out) || cpl_error_get_code()) {
1738 cpl_msg_error(__func__, "Failed to calibrate");
1739 cpl_table_delete(extracted_fpet) ;
1740 cpl_table_delete(tw_in) ;
1741 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1742 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1743 if (lines_diagnostics_une_out != NULL)
1744 cpl_table_delete(lines_diagnostics_une_out) ;
1745 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1746 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1747 cpl_msg_indent_less() ;
1748 cpl_msg_indent_less() ;
1749 return -1 ;
1750 }
1751 cpl_msg_indent_less() ;
1752 cpl_table_delete(tw_in) ;
1753 cpl_table_delete(extracted_fpet) ;
1754
1755 /* Generate the Wave Map */
1756 wl_map_fpet_out = cr2res_wave_gen_wave_map(tw_fpet_out) ;
1757
1758 /* Load the extension header for saving FPET */
1759 first_file = cpl_frame_get_filename(
1760 cpl_frameset_get_position_const(rawframes_fpet, 0)) ;
1761 ext_nr = cr2res_io_get_ext_idx(first_file, reduce_det, 1) ;
1762 plist_fpet_out = cpl_propertylist_load(first_file, ext_nr) ;
1763 if (plist_fpet_out == NULL) {
1764 cpl_propertylist_delete(qcs_fpet_out) ;
1765 cpl_table_delete(tw_fpet_out) ;
1766 cpl_table_delete(lines_diagnostics_fpet_out) ;
1767 cpl_table_delete(extracted_fpet_out) ;
1768 hdrl_image_delete(wl_map_fpet_out) ;
1769 if (plist_une_out != NULL) cpl_propertylist_delete(plist_une_out) ;
1770 if (tw_une_out != NULL) cpl_table_delete(tw_une_out) ;
1771 if (lines_diagnostics_une_out != NULL)
1772 cpl_table_delete(lines_diagnostics_une_out) ;
1773 if (extracted_une_out != NULL) cpl_table_delete(extracted_une_out) ;
1774 if (wl_map_une_out != NULL) hdrl_image_delete(wl_map_une_out) ;
1775 cpl_msg_indent_less() ;
1776 cpl_msg_error(__func__, "Failed to load the plist") ;
1777 return -1 ;
1778 }
1779 if (qcs_fpet_out != NULL) {
1780 cpl_propertylist_append(plist_fpet_out, qcs_fpet_out) ;
1781 cpl_propertylist_delete(qcs_fpet_out) ;
1782 }
1783 cpl_msg_indent_less() ;
1784 } else {
1785 if (tw_in != NULL) cpl_table_delete(tw_in);
1786 tw_fpet_out = NULL ;
1787 lines_diagnostics_fpet_out = NULL ;
1788 extracted_fpet_out = NULL ;
1789 wl_map_fpet_out = NULL ;
1790 plist_fpet_out = NULL ;
1791 }
1792
1793 /* Return */
1794 *out_trace_wave_une = tw_une_out ;
1795 *lines_diagnostics_une = lines_diagnostics_une_out ;
1796 *out_extracted_une = extracted_une_out ;
1797 *out_wave_map_une = wl_map_une_out ;
1798 *ext_plist_une = plist_une_out ;
1799
1800 *out_trace_wave_fpet = tw_fpet_out ;
1801 *lines_diagnostics_fpet = lines_diagnostics_fpet_out ;
1802 *out_extracted_fpet = extracted_fpet_out ;
1803 *out_wave_map_fpet = wl_map_fpet_out ;
1804 *ext_plist_fpet = plist_fpet_out ;
1805 return 0 ;
1806}
1807
1808/*----------------------------------------------------------------------------*/
1824/*----------------------------------------------------------------------------*/
1825static int cr2res_cal_wave_qc_une_flux(
1826 const cpl_table ** extracted,
1827 const cpl_propertylist ** ext_plist,
1828 double cwlen,
1829 cpl_propertylist * plist)
1830{
1831 const cpl_table * ref_extr ;
1832 const cpl_propertylist * ref_plist ;
1833 cpl_bivector * spec ;
1834 cpl_bivector * spec_err ;
1835 cpl_bivector * intensities ;
1836 double * pintens;
1837 double qc_flux, min_intens, max_intens;
1838 int ref_det, corder_idx ;
1839 cpl_size k;
1840
1841 /* Check Inputs */
1842 if (extracted==NULL || ext_plist == NULL) return -1 ;
1843 for (k=0 ; k< CR2RES_NB_DETECTORS ; k++) {
1844 if (extracted[k] == NULL) return -1 ;
1845 if (ext_plist[k] == NULL) return -1 ;
1846 }
1847
1848 /* Initialize */
1849 qc_flux = -1.0 ;
1850 min_intens = 1000.0 ;
1851 max_intens = 37000.0 ;
1852
1853 /* Detector used depends on the cwlen */
1854 if (cwlen <= 1100.0) ref_det = 0 ;
1855 else ref_det = 1 ;
1856 ref_extr = extracted[ref_det] ;
1857
1858 ref_plist = ext_plist[ref_det] ;
1859
1860 /* Get central order index */
1861 corder_idx = cr2res_pfits_get_order_idx(ref_plist,
1862 CR2RES_DETECTOR_SIZE/2.0) ;
1863
1864 cpl_msg_debug(__func__, "Central wl: %g / Cent. Order IDX: %d",
1865 cwlen, corder_idx) ;
1866
1867 /* Load the spectrum */
1868 cr2res_extract_EXTRACT1D_get_spectrum(ref_extr, corder_idx, 1, &spec,
1869 &spec_err) ;
1870 cpl_bivector_delete(spec_err) ;
1871
1872 /* Plot the spectrum */
1873 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
1874 cpl_errorstate status;
1875 status = cpl_errorstate_get();
1876 cpl_plot_bivector(
1877 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Intensity';",
1878 "t 'UNE Spectrum' w lines", "",
1879 spec);
1880 cpl_error_reset();
1881 cpl_errorstate_set(status);
1882 }
1883
1884 /* Compute the lines statistics */
1885 if ((intensities = cr2res_qc_lines_intens_bgd(spec)) == NULL) {
1886 cpl_msg_warning(__func__, "Cannot get the lines statistics") ;
1887 }
1888 else {
1889 cpl_size nintensities, nval;
1890 double * pbgs ;
1891 nintensities = cpl_bivector_get_size(intensities) ;
1892 pintens = cpl_bivector_get_x_data(intensities) ;
1893 pbgs = cpl_bivector_get_y_data(intensities) ;
1894 /* Compute qc_flux of lines in [min_intens,max_intens] */
1895 nval = 0 ;
1896 for (k=0 ; k<nintensities ; k++) {
1897 double val;
1898 val = pintens[k] - pbgs[k] ;
1899 if (val < max_intens && val > min_intens) {
1900 qc_flux += val ;
1901 nval++;
1902 }
1903 }
1904 if (nval > 0) qc_flux /= nval ;
1905 cpl_bivector_delete(intensities) ;
1906 }
1907 cpl_bivector_delete(spec) ;
1908
1909 /* Store the QCs */
1910 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_UNE_FLUX,
1911 qc_flux) ;
1912
1913 return 0 ;
1914}
1915/*----------------------------------------------------------------------------*/
1938/*----------------------------------------------------------------------------*/
1939static int cr2res_cal_wave_qc_fpi(
1940 const cpl_table ** extracted,
1941 const cpl_table ** tw,
1942 const cpl_propertylist ** ext_plist,
1943 double cwlen,
1944 cpl_propertylist * plist)
1945{
1946 const cpl_table * ref_extr ;
1947 const cpl_table * ref_tw ;
1948 const cpl_propertylist * ref_plist ;
1949 double qc_contrast, qc_flux, qc_separation;
1950 int corder_idx, ref_det, first_fringe_idx,
1951 last_fringe_idx, nb_fringes_between ;
1952 cpl_bivector * spec ;
1953 cpl_bivector * spec_err ;
1954 cpl_vector * xpeaks ;
1955 cpl_vector * lpeaks ;
1956 cpl_vector * fpeaks ;
1957 cpl_vector * xmins ;
1958 cpl_vector * fmins ;
1959 cpl_vector * lmins ;
1960 cpl_vector * tmp_vec ;
1961 cpl_vector * flux_vec ;
1962 cpl_polynomial * wlpoly ;
1963 cpl_size k, npeaks, end_val_search;
1964
1965
1966
1967 /* Check Inputs */
1968 if (extracted==NULL || ext_plist == NULL) return -1 ;
1969 for (k=0 ; k< CR2RES_NB_DETECTORS ; k++) {
1970 if (extracted[k] == NULL) return -1 ;
1971 if (ext_plist[k] == NULL) return -1 ;
1972 }
1973
1974 /* Detector used depends on the cwlen */
1975 if (cwlen <= 1100.0) ref_det = 0 ;
1976 else ref_det = 1 ;
1977 ref_extr = extracted[ref_det] ;
1978 ref_tw = tw[ref_det] ;
1979 ref_plist = ext_plist[ref_det] ;
1980
1981 /* Get central order index */
1982 corder_idx = cr2res_pfits_get_order_idx(ref_plist,
1983 CR2RES_DETECTOR_SIZE/2.0) ;
1984
1985 cpl_msg_debug(__func__, "Central wl: %g / Cent. Order IDX: %d",
1986 cwlen, corder_idx) ;
1987
1988 /* Load the spectrum */
1989 cr2res_extract_EXTRACT1D_get_spectrum(ref_extr, corder_idx, 1, &spec,
1990 &spec_err) ;
1991 cpl_bivector_delete(spec_err) ;
1992
1993 /* Plot the spectrum */
1994 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
1995 cpl_errorstate status;
1996
1997 status = cpl_errorstate_get();
1998 cpl_plot_bivector(
1999 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Intensity';",
2000 "t 'FPI Spectrum' w lines", "",
2001 spec);
2002 cpl_error_reset();
2003 cpl_errorstate_set(status);
2004 }
2005
2006 /* Identify the peaks */
2007 if ((xpeaks=cr2res_wave_etalon_measure_fringes(cpl_bivector_get_y(spec)))
2008 == NULL) {
2009 cpl_msg_warning(__func__, "Cannot identify the peaks") ;
2010 cpl_bivector_delete(spec) ;
2011 return -1 ;
2012 }
2013 npeaks = cpl_vector_get_size(xpeaks) ;
2014
2015 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
2016 cpl_vector_dump(xpeaks, stdout) ;
2017 }
2018
2019 /* Get the wavelength solution for this order */
2020 wlpoly = cr2res_get_trace_wave_poly(ref_tw, CR2RES_COL_WAVELENGTH,
2021 corder_idx, 1) ;
2022 if (wlpoly == NULL) {
2023 cpl_msg_warning(__func__, "Cannot get the wavelength") ;
2024 cpl_bivector_delete(spec) ;
2025 cpl_vector_delete(xpeaks) ;
2026 return -1 ;
2027 }
2028
2029 /* Get the wavelengths at the peak positions */
2030 lpeaks = cr2res_polynomial_eval_vector(wlpoly, xpeaks);
2031
2032 /* Get the Min after each peak */
2033 xmins = cpl_vector_new(npeaks) ;
2034 fpeaks = cpl_vector_new(npeaks);
2035 fmins = cpl_vector_new(npeaks);
2036 for (k=0 ; k<npeaks ; k++) {
2037 cpl_size start_val_search, xminpos;
2038
2039 /* Min of the peak */
2040 start_val_search = (int)cpl_vector_get(xpeaks, k) ;
2041 if (k == npeaks-1) {
2042 end_val_search = start_val_search ;// Not used
2043 } else {
2044 end_val_search = (int)cpl_vector_get(xpeaks, k+1) ;
2045 }
2046 tmp_vec = cpl_vector_extract(cpl_bivector_get_y(spec),
2047 start_val_search-1, end_val_search-1, 1) ;
2048 xminpos = cpl_vector_get_minpos(tmp_vec) ;
2049 cpl_vector_set(fpeaks,k,cpl_vector_get(tmp_vec,0));
2050 cpl_vector_set(fmins,k,cpl_vector_get(tmp_vec,xminpos));
2051 cpl_vector_delete(tmp_vec) ;
2052
2053 cpl_vector_set(xmins, k, start_val_search + xminpos) ;
2054 }
2055
2056 /* Get the wavelengths at the min positions */
2057 lmins = cr2res_polynomial_eval_vector(wlpoly, xmins);
2058 cpl_polynomial_delete(wlpoly) ;
2059
2060 for (k=0 ; k<npeaks ; k++) {
2061 cpl_msg_debug(__func__,
2062 "Peak #%"CPL_SIZE_FORMAT" Pos: %g / WL: %g / Val :%g",
2063 k+1,
2064 cpl_vector_get(xpeaks, k),
2065 cpl_vector_get(lpeaks, k),
2066 cpl_vector_get(cpl_bivector_get_y(spec),
2067 (int)cpl_vector_get(xpeaks, k))) ;
2068 cpl_msg_debug(__func__,
2069 " Min Pos: %g / WL: %g / Val :%g",
2070 cpl_vector_get(xmins, k),
2071 cpl_vector_get(lmins, k),
2072 cpl_vector_get(cpl_bivector_get_y(spec),
2073 (int)cpl_vector_get(xmins, k))) ;
2074 }
2075 cpl_bivector_delete(spec) ;
2076 cpl_vector_delete(xpeaks) ;
2077 cpl_vector_delete(xmins) ;
2078
2079 /* CONTRAST */
2080 /* Ignore first and last peaks */
2081 tmp_vec = cpl_vector_new(npeaks-2) ;
2082 flux_vec = cpl_vector_new(npeaks-2) ;
2083 for (k=1 ; k<npeaks-1 ; k++) {
2084 double fpeak, fmin, contrast_val ;
2085 fpeak = cpl_vector_get(fpeaks, k) ;
2086 fmin = cpl_vector_get(fmins, k) ;
2087 contrast_val = (fpeak-fmin) / (fmin+fpeak) ;
2088 cpl_vector_set(tmp_vec, k-1, contrast_val) ;
2089 cpl_vector_set(flux_vec, k-1, fpeak) ;
2090 }
2091 qc_contrast = cpl_vector_get_mean(tmp_vec) ;
2092 qc_flux = cpl_vector_get_mean(flux_vec) ;
2093 cpl_vector_delete(tmp_vec) ;
2094 cpl_vector_delete(flux_vec) ;
2095 cpl_vector_delete(lmins) ;
2096
2097 /* SEPARATION */
2098 first_fringe_idx = 1 ; // Skip first
2099 last_fringe_idx = npeaks-2 ; // Skip Last
2100 nb_fringes_between = last_fringe_idx - first_fringe_idx + 1 - 2 ;
2101
2102 qc_separation = (cpl_vector_get(lpeaks, last_fringe_idx) -
2103 cpl_vector_get(lpeaks, first_fringe_idx)) /
2104 nb_fringes_between ;
2105
2106 cpl_vector_delete(lpeaks) ;
2107 cpl_vector_delete(fpeaks) ;
2108 cpl_vector_delete(fmins) ;
2109
2110 /* Store the QCs */
2111 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FPI_CONTRAST,
2112 qc_contrast) ;
2113 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FPI_FLUX,
2114 qc_flux) ;
2115 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_FPI_SEPARATION,
2116 qc_separation) ;
2117
2118 return 0 ;
2119}
2120
2121/*----------------------------------------------------------------------------*/
2138/*----------------------------------------------------------------------------*/
2139static int cr2res_cal_wave_qc_tilt(
2140 const cpl_table ** tws,
2141 double cwlen,
2142 cpl_propertylist * plist)
2143{
2144 const cpl_table * ref_tw ;
2145 double tilt_avg;
2146 int ref_x, ntilt ;
2147 cpl_size nrows, k ;
2148
2149 /* Check Inputs */
2150 if (tws==NULL) return -1 ;
2151 for (k=0 ; k< CR2RES_NB_DETECTORS ; k++)
2152 if (tws[k] == NULL) return -1 ;
2153
2154 /* Initialize */
2155 ref_x = 1024 ;
2156 tilt_avg = 0.0 ;
2157 ntilt = 0 ;
2158
2159 /* Detector used depends on the cwlen */
2160 if (cwlen <= 1100.0) ref_tw = tws[0] ;
2161 else ref_tw = tws[1] ;
2162
2163 nrows = cpl_table_get_nrow(ref_tw) ;
2164
2165 /* Loop on rows */
2166 for (k=0 ; k<nrows ; k++) {
2167
2168 const cpl_array * tmp_array ;
2169 cpl_polynomial * slit_poly_a ;
2170 cpl_polynomial * slit_poly_b ;
2171 cpl_polynomial * slit_poly_c ;
2172 cpl_polynomial * upper_poly ;
2173 cpl_polynomial * lower_poly ;
2174 cpl_polynomial * slit_curv_poly ;
2175 char * qc_name;
2176 double top_x, top_y, bot_x, bot_y;
2177 double tilt;
2178 int cur_order ;
2179
2180 cur_order = cpl_table_get(ref_tw, CR2RES_COL_ORDER, k, NULL) ;
2181
2182 /* Get the Slit curvature for the trace */
2183 tmp_array = cpl_table_get_array(ref_tw, CR2RES_COL_SLIT_CURV_A, k) ;
2184 slit_poly_a = cr2res_convert_array_to_poly(tmp_array) ;
2185 tmp_array = cpl_table_get_array(ref_tw, CR2RES_COL_SLIT_CURV_B, k) ;
2186 slit_poly_b = cr2res_convert_array_to_poly(tmp_array) ;
2187 tmp_array = cpl_table_get_array(ref_tw, CR2RES_COL_SLIT_CURV_C, k) ;
2188 slit_poly_c = cr2res_convert_array_to_poly(tmp_array) ;
2189
2190 /* Get the Upper Polynomial */
2191 tmp_array = cpl_table_get_array(ref_tw, CR2RES_COL_UPPER, k) ;
2192 upper_poly = cr2res_convert_array_to_poly(tmp_array) ;
2193
2194 /* Get the Lower Polynomial */
2195 tmp_array = cpl_table_get_array(ref_tw, CR2RES_COL_LOWER, k) ;
2196 lower_poly = cr2res_convert_array_to_poly(tmp_array) ;
2197
2198 /* Create the slit curvature polynomial at position ref_x */
2199 slit_curv_poly = cr2res_slit_curv_build_poly(slit_poly_a,
2200 slit_poly_b, slit_poly_c, ref_x) ;
2201 cpl_polynomial_delete(slit_poly_a) ;
2202 cpl_polynomial_delete(slit_poly_b) ;
2203 cpl_polynomial_delete(slit_poly_c) ;
2204
2205 top_y = cpl_polynomial_eval_1d(upper_poly, ref_x, NULL) ;
2206 bot_y = cpl_polynomial_eval_1d(lower_poly, ref_x, NULL) ;
2207 cpl_polynomial_delete(upper_poly) ;
2208 cpl_polynomial_delete(lower_poly) ;
2209
2210 top_x = cpl_polynomial_eval_1d(slit_curv_poly, top_y, NULL) ;
2211 bot_x = cpl_polynomial_eval_1d(slit_curv_poly, bot_y, NULL) ;
2212 cpl_polynomial_delete(slit_curv_poly) ;
2213
2214 /* Compute the tilt */
2215 tilt = atan((top_x-bot_x)/(top_y-bot_y))*180.0/CRIRES_PI;
2216 cpl_msg_debug(__func__,
2217 "TILT : %g / Upper (x,y)=(%g,%g) Lower (x,y)=(%g,%g)",
2218 tilt, top_x, top_y, bot_x, bot_y) ;
2219
2220 /* Store the tilt */
2221 qc_name = cpl_sprintf(CR2RES_HEADER_QC_TILT, cur_order) ;
2222 cpl_propertylist_append_double(plist, qc_name, tilt) ;
2223 cpl_free(qc_name) ;
2224
2225 /* update the tilt average */
2226 tilt_avg += tilt ;
2227 ntilt++ ;
2228 }
2229
2230 /* Store global tilt */
2231 if (ntilt > 0) {
2232 cpl_msg_debug(__func__, "TILT GLOBAL: %g", tilt_avg/ntilt) ;
2233 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_TILT_GLOBAL,
2234 tilt_avg/ntilt) ;
2235 }
2236
2237 return 0 ;
2238}
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
int cr2res_extract_traces(const hdrl_image *img, const cpl_table *traces, const cpl_table *slit_func_in, const cpl_table *blaze_table_in, float blaze_norm, int reduce_order, int reduce_trace, cr2res_extr_method extr_method, int extr_height, int swath_width, int oversample, double smooth_slit, double smooth_spec, int niter, double kappa, double error_factor, int display, int disp_order_idx, int disp_trace, cpl_table **extracted, cpl_table **slit_func, hdrl_image **model_master)
Extracts all the passed traces at once.
int cr2res_extract_EXTRACT1D_get_spectrum(const cpl_table *tab, int order, int trace_nb, cpl_bivector **spec, cpl_bivector **spec_err)
Get a Spectrum and its error from the EXTRACT_1D table.
cpl_table * cr2res_io_load_EXTRACT_1D(const char *filename, int detector)
Load a table from a EXTRACT_1D.
Definition: cr2res_io.c:1296
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
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_WAVE_MAP(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 WAVE_MAP.
Definition: cr2res_io.c:1916
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_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_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
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
Definition: cr2res_io.c:1109
int cr2res_io_save_LINES_DIAGNOSTICS(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 LINES_DIAGNOSTICS.
Definition: cr2res_io.c:1701
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
Definition: cr2res_io.c:462
int cr2res_pfits_get_order_idx(const cpl_propertylist *plist, double yposition)
find out the order_idx closest to the passed y position
Definition: cr2res_pfits.c:412
double cr2res_pfits_get_cwlen(const cpl_propertylist *plist)
find out the CWLEN value
Definition: cr2res_pfits.c:229
double cr2res_qc_overexposed(const cpl_image *ima, const cpl_table *tw, int order_idx)
Computes the Overexposed fraction.
Definition: cr2res_qc.c:796
cpl_bivector * cr2res_qc_lines_intens_bgd(const cpl_bivector *spec)
Computes the lines intensities / background.
Definition: cr2res_qc.c:612
int cr2res_slit_curv_compute_order_trace(const hdrl_image *img, const cpl_table *trace_wave, const int order, const int trace, const int height, const int window, const cpl_size change_degree, const int slit_degree, cpl_polynomial **slit_poly_a, cpl_polynomial **slit_poly_b, cpl_polynomial **slit_poly_c)
Get the slit curvature directly from the image.
cpl_polynomial * cr2res_slit_curv_build_poly(cpl_polynomial *slit_poly_a, cpl_polynomial *slit_poly_b, cpl_polynomial *slit_poly_c, cpl_size x)
Create the slit curvature polynomial for x position.
cpl_polynomial * cr2res_get_trace_wave_poly(const cpl_table *trace_wave, const char *poly_column, int order_idx, int trace_nb)
Get a polynomial from a TRACE_WAVE table.
Definition: cr2res_trace.c:685
cpl_polynomial * cr2res_convert_array_to_poly(const cpl_array *arr)
Convert an array to polynomial.
cpl_vector * cr2res_polynomial_eval_vector(const cpl_polynomial *poly, const cpl_vector *vec)
Evaluate a polynomial on a vector.
cpl_array * cr2res_convert_poly_to_array(const cpl_polynomial *poly, int size)
Convert a polynomial to array.
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.
hdrl_image * cr2res_wave_gen_wave_map(const cpl_table *trace_wave)
Compute the wavelength map from the trace_wave table.
Definition: cr2res_wave.c:1608
int cr2res_wave_apply(cpl_table *tw_in, cpl_table *spectra_tab, const cpl_frame *catalog_frame, int reduce_order, int reduce_trace, cr2res_wavecal_type wavecal_type, int degree, int xdegree, double wl_start, double wl_end, double wl_err, double wl_shift, int log_flag, int fallback_input_wavecal_flag, int keep_higher_degrees_flag, int clean_spectrum, int display, double display_wmin, double display_wmax, int zp_order, int grat1_order, cpl_propertylist **qcs, cpl_table **lines_diagnostics, cpl_table **extracted_out, cpl_table **trace_wave_out)
Apply the Wavelength Calibration.
Definition: cr2res_wave.c:150
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
Definition: hdrl_image.c:105
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.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_collapse_median(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Median collapsing of image list.