CR2RE Pipeline Reference Manual 1.6.7
cr2res_obs_2d.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 <cpl.h>
29
30#include "cr2res_utils.h"
31#include "cr2res_calib.h"
32#include "cr2res_pfits.h"
33#include "cr2res_dfs.h"
34#include "cr2res_bpm.h"
35#include "cr2res_trace.h"
36#include "cr2res_extract.h"
37#include "cr2res_io.h"
38#include "cr2res_qc.h"
39
40/*-----------------------------------------------------------------------------
41 Define
42 -----------------------------------------------------------------------------*/
43
44#define RECIPE_STRING "cr2res_obs_2d"
45
46/*-----------------------------------------------------------------------------
47 Plugin registration
48 -----------------------------------------------------------------------------*/
49
50int cpl_plugin_get_info(cpl_pluginlist * list);
51
52/*-----------------------------------------------------------------------------
53 Private function prototypes
54 -----------------------------------------------------------------------------*/
55
56static hdrl_image ** cr2res_obs_2d_average_sky(
57 const cpl_frameset * skyframes) ;
58static int cr2res_obs_2d_check_inputs_validity(
59 const cpl_frame * rawframe) ;
60static int cr2res_obs_2d_reduce(
61 const cpl_frame * rawframe_obj,
62 const cpl_frame * rawframe_sky,
63 const hdrl_image ** sky_average,
64 const cpl_frame * trace_wave_frame,
65 const cpl_frame * detlin_frame,
66 const cpl_frame * master_dark_frame,
67 const cpl_frame * master_flat_frame,
68 const cpl_frame * bpm_frame,
69 int subtract_nolight_rows,
70 int subtract_interorder_column,
71 int cosmics,
72 int reduce_det,
73 int reduce_order,
74 int reduce_trace,
75 hdrl_image ** calibrated,
76 cpl_table ** extract,
77 cpl_propertylist ** ext_plist) ;
78static int cr2res_obs_2d_create(cpl_plugin *);
79static int cr2res_obs_2d_exec(cpl_plugin *);
80static int cr2res_obs_2d_destroy(cpl_plugin *);
81static int cr2res_obs_2d(cpl_frameset *, const cpl_parameterlist *);
82
83/*-----------------------------------------------------------------------------
84 Static variables
85 -----------------------------------------------------------------------------*/
86
87static char cr2res_obs_2d_description[] = "\
882D Observation \n\
89 This recipe is meant for extended objects. In each trace, the pixels \n\
90 are calibrated, and stored in the output table. \n\
91 \n\
92 Inputs \n\
93 raw.fits " CR2RES_OBS_2D_OBJECT_RAW" [1 to n] \n\
94 and " CR2RES_OBS_2D_SKY_RAW " [0 to n] \n\
95 trace.fits " CR2RES_CAL_FLAT_TW_PROCATG " [1] \n\
96 or " CR2RES_CAL_FLAT_TW_MERGED_PROCATG " \n\
97 or " CR2RES_UTIL_TRACE_TW_PROCATG " \n\
98 or " CR2RES_UTIL_WAVE_TW_PROCATG " \n\
99 or " CR2RES_CAL_WAVE_TW_PROCATG " \n\
100 or " CR2RES_UTIL_SLIT_CURV_TW_PROCATG " \n\
101 detlin.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG " [0 to 1] \n\
102 bpm.fits " CR2RES_CAL_DARK_BPM_PROCATG " [0 to 1] \n\
103 or " CR2RES_CAL_FLAT_BPM_PROCATG " \n\
104 or " CR2RES_CAL_DETLIN_BPM_PROCATG " \n\
105 or " CR2RES_UTIL_BPM_MERGE_PROCATG " \n\
106 or " CR2RES_UTIL_BPM_SPLIT_PROCATG " \n\
107 master_dark.fits " CR2RES_CAL_DARK_MASTER_PROCATG " [0 to 1] \n\
108 master_flat.fits " CR2RES_CAL_FLAT_MASTER_PROCATG " [0 to 1] \n\
109 \n\
110 Outputs \n\
111 cr2res_obs_2d_frame_<nb>_extracted.fits "
112 CR2RES_OBS_2D_EXTRACT_PROCATG "\n\
113 cr2res_obs_2d_frame_<nb>_calibrated.fits "
114 CR2RES_OBS_2D_CALIBRATED_PROCATG"\n\
115 \n\
116 Algorithm \n\
117 loop on raw frames f: \n\
118 loop on detectors d: \n\
119 cr2res_obs_2d_reduce() \n\
120 -> extract(d) \n\
121 Save extract \n\
122 \n\
123 cr2res_obs_2d_reduce() \n\
124 Load the input image \n\
125 Apply the calibrations to the image \n\
126 Load the trace wave table \n\
127 Call cr2res_extract2d_traces() \n\
128 -> extract \n\
129 \n\
130 Library Functions used \n\
131 cr2res_io_find_TRACE_WAVE() \n\
132 cr2res_io_find_BPM() \n\
133 cr2res_obs_2d_reduce() \n\
134 cr2res_obs_2d_check_inputs_validity() \n\
135 cr2res_pfits_get_dit() \n\
136 cr2res_io_load_image() \n\
137 cr2res_calib_image() \n\
138 cr2res_io_load_TRACE_WAVE() \n\
139 cr2res_extract2d_traces() \n\
140 cr2res_io_save_EXTRACT_2D() \n\
141 cr2res_io_save_CALIBRATED() \n\
142";
143
144/*-----------------------------------------------------------------------------
145 Function code
146 -----------------------------------------------------------------------------*/
147
148/*----------------------------------------------------------------------------*/
158/*----------------------------------------------------------------------------*/
159int cpl_plugin_get_info(cpl_pluginlist * list)
160{
161 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
162 cpl_plugin * plugin = &recipe->interface;
163
164 if (cpl_plugin_init(plugin,
165 CPL_PLUGIN_API,
166 CR2RES_BINARY_VERSION,
167 CPL_PLUGIN_TYPE_RECIPE,
168 RECIPE_STRING,
169 "2D Observation recipe",
170 cr2res_obs_2d_description,
171 CR2RES_PIPELINE_AUTHORS,
172 PACKAGE_BUGREPORT,
174 cr2res_obs_2d_create,
175 cr2res_obs_2d_exec,
176 cr2res_obs_2d_destroy)) {
177 cpl_msg_error(cpl_func, "Plugin initialization failed");
178 (void)cpl_error_set_where(cpl_func);
179 return 1;
180 }
181
182 if (cpl_pluginlist_append(list, plugin)) {
183 cpl_msg_error(cpl_func, "Error adding plugin to list");
184 (void)cpl_error_set_where(cpl_func);
185 return 1;
186 }
187
188 return 0;
189}
190
191/*----------------------------------------------------------------------------*/
199/*----------------------------------------------------------------------------*/
200static int cr2res_obs_2d_create(cpl_plugin * plugin)
201{
202 cpl_recipe * recipe ;
203 cpl_parameter * p ;
204
205 /* Check that the plugin is part of a valid recipe */
206 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
207 recipe = (cpl_recipe *)plugin;
208 else
209 return -1;
210
211 /* Create the parameters list in the cpl_recipe object */
212 recipe->parameters = cpl_parameterlist_new();
213
214 /* Fill the parameters list */
215 p = cpl_parameter_new_value("cr2res.cr2res_obs_2d.subtract_nolight_rows",
216 CPL_TYPE_BOOL,
217 "Subtract median row from baffled region at detector bottom",
218 "cr2res.cr2res_obs_2d", FALSE);
219 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "subtract_nolight_rows");
220 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221 cpl_parameterlist_append(recipe->parameters, p);
222
223 p = cpl_parameter_new_value(
224 "cr2res.cr2res_obs_2d.subtract_interorder_column", CPL_TYPE_BOOL,
225 "Subtract column-by-column fit to the pixel values between"
226 " spectral orders",
227 "cr2res.cr2res_obs_2d", TRUE);
228 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
229 "subtract_interorder_column");
230 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
231 cpl_parameterlist_append(recipe->parameters, p);
232
233 p = cpl_parameter_new_value("cr2res.cr2res_obs_2d.cosmics",
234 CPL_TYPE_BOOL, "Find and mark cosmic rays hits as bad",
235 "cr2res.cr2res_obs_2d", FALSE);
236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics");
237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
238 cpl_parameterlist_append(recipe->parameters, p);
239
240 p = cpl_parameter_new_value("cr2res.cr2res_obs_2d.detector",
241 CPL_TYPE_INT, "Only reduce the specified detector",
242 "cr2res.cr2res_obs_2d", 0);
243 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detector");
244 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
245 cpl_parameterlist_append(recipe->parameters, p);
246
247 p = cpl_parameter_new_value("cr2res.cr2res_obs_2d.order",
248 CPL_TYPE_INT, "Only reduce the specified order",
249 "cr2res.cr2res_obs_2d", -1);
250 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order");
251 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
252 cpl_parameterlist_append(recipe->parameters, p);
253
254 p = cpl_parameter_new_value("cr2res.cr2res_obs_2d.trace_nb",
255 CPL_TYPE_INT, "Only reduce the specified trace number",
256 "cr2res.cr2res_obs_2d", -1);
257 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trace_nb");
258 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
259 cpl_parameterlist_append(recipe->parameters, p);
260
261 return 0;
262}
263
264/*----------------------------------------------------------------------------*/
270/*----------------------------------------------------------------------------*/
271static int cr2res_obs_2d_exec(cpl_plugin * plugin)
272{
273 cpl_recipe *recipe;
274
275 /* Get the recipe out of the plugin */
276 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
277 recipe = (cpl_recipe *)plugin;
278 else return -1;
279
280 return cr2res_obs_2d(recipe->frames, recipe->parameters);
281}
282
283/*----------------------------------------------------------------------------*/
289/*----------------------------------------------------------------------------*/
290static int cr2res_obs_2d_destroy(cpl_plugin * plugin)
291{
292 cpl_recipe *recipe;
293
294 /* Get the recipe out of the plugin */
295 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
296 recipe = (cpl_recipe *)plugin;
297 else return -1 ;
298
299 cpl_parameterlist_delete(recipe->parameters);
300 return 0 ;
301}
302
303/*----------------------------------------------------------------------------*/
310/*----------------------------------------------------------------------------*/
311static int cr2res_obs_2d(
312 cpl_frameset * frameset,
313 const cpl_parameterlist * parlist)
314{
315 const cpl_parameter * param ;
316 int reduce_det, reduce_order, reduce_trace, cosmics,
317 subtract_nolight_rows, subtract_interorder_column ;
318 cpl_frameset * rawframes_obj ;
319 cpl_frameset * used_frameset ;
320 cpl_frameset * rawframes_sky ;
321 cpl_frame * rawframe_sky ;
322 const cpl_frame * detlin_frame ;
323 const cpl_frame * master_dark_frame ;
324 const cpl_frame * master_flat_frame ;
325 const cpl_frame * bpm_frame ;
326 const cpl_frame * trace_wave_frame ;
327 hdrl_image ** sky_average ;
328 cpl_propertylist * qc_main ;
329 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
330 hdrl_image * calibrated[CR2RES_NB_DETECTORS] ;
331 cpl_table * extract[CR2RES_NB_DETECTORS] ;
332 char * out_file;
333 cpl_table * eop_table ;
334 cpl_propertylist * plist ;
335 double ra, dec, mjd_obs, mjd_cen, geolon, geolat, geoelev,
336 barycorr;
337 cpl_size nsky, nobj ;
338 int i, det_nr;
339
340 /* Initialise */
341
342 /* RETRIEVE INPUT PARAMETERS */
343 param = cpl_parameterlist_find_const(parlist,
344 "cr2res.cr2res_obs_2d.detector");
345 reduce_det = cpl_parameter_get_int(param);
346 param = cpl_parameterlist_find_const(parlist,
347 "cr2res.cr2res_obs_2d.subtract_nolight_rows");
348 subtract_nolight_rows = cpl_parameter_get_bool(param);
349 param = cpl_parameterlist_find_const(parlist,
350 "cr2res.cr2res_obs_2d.subtract_interorder_column");
351 subtract_interorder_column = cpl_parameter_get_bool(param);
352 param = cpl_parameterlist_find_const(parlist,
353 "cr2res.cr2res_obs_2d.cosmics");
354 cosmics = cpl_parameter_get_bool(param);
355 param = cpl_parameterlist_find_const(parlist,
356 "cr2res.cr2res_obs_2d.order");
357 reduce_order = cpl_parameter_get_int(param);
358 param = cpl_parameterlist_find_const(parlist,
359 "cr2res.cr2res_obs_2d.trace_nb");
360 reduce_trace = cpl_parameter_get_int(param);
361
362 /* Identify the RAW and CALIB frames in the input frameset */
363 if (cr2res_dfs_set_groups(frameset)) {
364 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
365 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
366 return -1 ;
367 }
368
369 /* Get Calibration frames */
370 trace_wave_frame = cr2res_io_find_TRACE_WAVE(frameset) ;
371 if (trace_wave_frame == NULL) {
372 cpl_msg_error(__func__, "Could not find TRACE_WAVE frame") ;
373 return -1 ;
374 }
375 detlin_frame = cpl_frameset_find_const(frameset,
376 CR2RES_CAL_DETLIN_COEFFS_PROCATG);
377 master_dark_frame = cpl_frameset_find_const(frameset,
378 CR2RES_CAL_DARK_MASTER_PROCATG) ;
379 master_flat_frame = cpl_frameset_find_const(frameset,
380 CR2RES_CAL_FLAT_MASTER_PROCATG) ;
381 bpm_frame = cr2res_io_find_BPM(frameset) ;
382
383 /* Get the Object Frames */
384 rawframes_obj = cr2res_extract_frameset(frameset, CR2RES_OBS_2D_OBJECT_RAW);
385 if (rawframes_obj == NULL) {
386 cpl_msg_error(__func__, "Could not find RAW frames") ;
387 return -1 ;
388 }
389 nobj = cpl_frameset_get_size(rawframes_obj) ;
390
391 /* Get the Sky Frames */
392 // rawframes_sky sky_average Effect
393 // NULL NULL No correction
394 // NULL not NULL Use sky average
395 // not NULL NULL Use individual Sky frames
396 // not NULL not NULL Not allowed
397 rawframes_sky = cr2res_extract_frameset(frameset, CR2RES_OBS_2D_SKY_RAW);
398 if (rawframes_sky == NULL) {
399 nsky = 0;
400 } else {
401 nsky = cpl_frameset_get_size(rawframes_sky);
402 }
403
404 if (nsky == 0) {
405 cpl_msg_info(__func__, "No Sky Correction") ;
406 if (rawframes_sky != NULL) cpl_frameset_delete(rawframes_sky) ;
407 rawframes_sky = NULL ;
408 sky_average = NULL ;
409 } else if (nsky > 0 && nsky != nobj) {
410 cpl_msg_info(__func__, "Sky Correction using Average") ;
411 // Compute sky_average TODO
412 sky_average = cr2res_obs_2d_average_sky(rawframes_sky) ;
413 if (rawframes_sky != NULL) cpl_frameset_delete(rawframes_sky) ;
414 rawframes_sky = NULL ;
415 } else if (nsky == nobj) {
416 cpl_msg_info(__func__, "Sky Correction using Individual Frames") ;
417 sky_average = NULL ;
418 } else {
419 // Should never happen
420 if (rawframes_sky != NULL) cpl_frameset_delete(rawframes_sky) ;
421 rawframes_sky = NULL ;
422 sky_average = NULL ;
423 }
424 /* Loop on the RAW files */
425 for (i = 0; i < cpl_frameset_get_size(rawframes_obj); i++) {
426 cpl_frame *rawframe_obj;
427 /* Current frame */
428 rawframe_obj = cpl_frameset_get_position(rawframes_obj, i);
429
430 cpl_msg_info(__func__, "Process Frame %s",
431 cpl_frame_get_filename(rawframe_obj)) ;
432 cpl_msg_indent_more() ;
433
434 /* Current SKY frame if 1 per OBJ */
435 if (rawframes_sky != NULL) {
436 rawframe_sky = cpl_frameset_get_position(rawframes_sky, i);
437 cpl_msg_info(__func__, "Use SKY Frame %s",
438 cpl_frame_get_filename(rawframe_sky)) ;
439 } else {
440 rawframe_sky = NULL ;
441 }
442
443 /* Loop on the detectors */
444 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
445 /* Initialise */
446 calibrated[det_nr-1] = NULL ;
447 extract[det_nr-1] = NULL ;
448 ext_plist[det_nr-1] = NULL ;
449
450 /* Compute only one detector */
451 if (reduce_det != 0 && det_nr != reduce_det) continue ;
452
453 cpl_msg_info(__func__, "Process Detector %d", det_nr) ;
454 cpl_msg_indent_more() ;
455
456 /* Call the reduction function */
457 if (cr2res_obs_2d_reduce(rawframe_obj, rawframe_sky,
458 (const hdrl_image**)sky_average,
459 trace_wave_frame, detlin_frame, master_dark_frame,
460 master_flat_frame, bpm_frame, subtract_nolight_rows,
461 subtract_interorder_column, cosmics, det_nr,
462 reduce_order, reduce_trace,
463 &(calibrated[det_nr-1]),
464 &(extract[det_nr-1]),
465 &(ext_plist[det_nr-1])) == -1) {
466 cpl_msg_warning(__func__, "Failed to reduce detector %d",
467 det_nr);
468 cpl_error_reset() ;
469 }
470 cpl_msg_indent_less() ;
471 }
472 cpl_msg_indent_less() ;
473
474 /* Save Products */
475
476 /* Add ESO.DRS.TMID in the Main Header */
477 qc_main = cpl_propertylist_new();
478 cpl_propertylist_append_double(qc_main,
479 CR2RES_HEADER_DRS_TMID,
480 cr2res_utils_get_center_mjd(rawframes_obj)) ;
481
482 /* Add barycentric correction */
483 eop_table = cr2res_io_get_eop_table() ;
484 if (eop_table != NULL) {
485 plist=cpl_propertylist_load(cpl_frame_get_filename(
486 cpl_frameset_get_position_const(rawframes_obj, 0)), 0) ;
487
488 ra = cpl_propertylist_get_double(plist, "RA") ;
489 dec = cpl_propertylist_get_double(plist, "DEC") ;
490 mjd_obs = cpl_propertylist_get_double(plist, "MJD-OBS") ;
491 geolon = cpl_propertylist_get_double(plist, "ESO TEL GEOLON") ;
492 geolat = cpl_propertylist_get_double(plist, "ESO TEL GEOLAT") ;
493 geoelev = cpl_propertylist_get_double(plist, "ESO TEL GEOELEV") ;
494
495 cpl_propertylist_delete(plist) ;
496
497 barycorr = 0.0 ;
498 if (!cpl_error_get_code()) {
499 mjd_cen = cr2res_utils_get_center_mjd(rawframes_obj) ;
500 hdrl_barycorr_compute(ra, dec, eop_table, mjd_obs,
501 (mjd_cen-mjd_obs)*24*3600, geolon, geolat, geoelev,
502 0.0, 0.0, 0.0, 0.0, &barycorr);
503
504 cpl_msg_info(__func__, "Barycentric correction: %g m/s",
505 barycorr);
506 } else {
507 cpl_msg_info(__func__, "Cannot derive Barycentric correction");
508 cpl_error_reset() ;
509 }
510 cpl_table_delete(eop_table) ;
511 cpl_propertylist_append_double(qc_main, CR2RES_HEADER_DRS_BARYCORR,
512 barycorr);
513 }
514
515 /* Add QC NUMSAT */
516 cpl_propertylist_append_int(qc_main,
517 CR2RES_HEADER_QC_NUMSAT,
518 cr2res_qc_numsat(rawframes_obj)) ;
519
520 /* Save only the used RAW - fill rawframe_obj with CALIBS */
521 used_frameset = cpl_frameset_new() ;
522 cpl_frameset_insert(used_frameset, cpl_frame_duplicate(rawframe_obj)) ;
523 if (rawframe_sky != NULL)
524 cpl_frameset_insert(frameset,
525 cpl_frame_duplicate(rawframe_sky)) ;
526 if (trace_wave_frame!= NULL)
527 cpl_frameset_insert(used_frameset,
528 cpl_frame_duplicate(trace_wave_frame)) ;
529 if (detlin_frame!= NULL)
530 cpl_frameset_insert(used_frameset,
531 cpl_frame_duplicate(detlin_frame)) ;
532 if (master_dark_frame!= NULL)
533 cpl_frameset_insert(used_frameset,
534 cpl_frame_duplicate(master_dark_frame)) ;
535 if (master_flat_frame!= NULL)
536 cpl_frameset_insert(used_frameset,
537 cpl_frame_duplicate(master_flat_frame)) ;
538 if (bpm_frame!= NULL)
539 cpl_frameset_insert(used_frameset,
540 cpl_frame_duplicate(bpm_frame)) ;
541
542 /* Calibrated */
543 out_file = cpl_sprintf("%s_frame_%d_calibrated.fits",
544 RECIPE_STRING, i+1) ;
545 cr2res_io_save_CALIBRATED(out_file, frameset, used_frameset, parlist,
546 calibrated, qc_main, ext_plist,
547 CR2RES_OBS_2D_CALIBRATED_PROCATG, RECIPE_STRING) ;
548 cpl_free(out_file);
549
550 /* Extracted */
551 out_file = cpl_sprintf("%s_frame_%d_extracted.fits",
552 RECIPE_STRING, i+1) ;
553 cr2res_io_save_EXTRACT_2D(out_file, frameset, used_frameset, parlist,
554 extract, qc_main, ext_plist, CR2RES_OBS_2D_EXTRACT_PROCATG,
555 RECIPE_STRING) ;
556 cpl_free(out_file);
557 cpl_frameset_delete(used_frameset);
558
559 /* Free */
560 cpl_propertylist_delete(qc_main) ;
561 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
562 if (calibrated[det_nr-1] != NULL)
563 hdrl_image_delete(calibrated[det_nr-1]) ;
564 if (extract[det_nr-1] != NULL)
565 cpl_table_delete(extract[det_nr-1]) ;
566 if (ext_plist[det_nr-1] != NULL)
567 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
568 }
569 cpl_msg_indent_less() ;
570 }
571 cpl_frameset_delete(rawframes_obj) ;
572 if (sky_average != NULL) {
573 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
574 if (sky_average[det_nr-1] != NULL)
575 hdrl_image_delete(sky_average[det_nr-1]) ;
576 cpl_free(sky_average) ;
577 }
578 if (rawframes_sky != NULL) cpl_frameset_delete(rawframes_sky) ;
579
580 return (int)cpl_error_get_code();
581}
582
583/*----------------------------------------------------------------------------*/
605/*----------------------------------------------------------------------------*/
606static int cr2res_obs_2d_reduce(
607 const cpl_frame * rawframe_obj,
608 const cpl_frame * rawframe_sky,
609 const hdrl_image ** sky_average,
610 const cpl_frame * trace_wave_frame,
611 const cpl_frame * detlin_frame,
612 const cpl_frame * master_dark_frame,
613 const cpl_frame * master_flat_frame,
614 const cpl_frame * bpm_frame,
615 int subtract_nolight_rows,
616 int subtract_interorder_column,
617 int cosmics,
618 int reduce_det,
619 int reduce_order,
620 int reduce_trace,
621 hdrl_image ** calibrated,
622 cpl_table ** extract,
623 cpl_propertylist ** ext_plist)
624{
625 hdrl_image * in ;
626 hdrl_image * in_calib ;
627 hdrl_image * in_sky ;
628 hdrl_image * in_sky_calib ;
629 cpl_table * trace_wave ;
630 cpl_propertylist * plist ;
631 double dit, dit_sky ;
632 int ndit, ndit_sky ;
633 cpl_table * extracted ;
634 int * order_idx_values ;
635 int nb_order_idx_values, order_zp;
636
637 /* Check Inputs */
638 if (extract == NULL || calibrated == NULL || ext_plist == NULL ||
639 rawframe_obj == NULL || trace_wave_frame == NULL) return -1 ;
640
641 /* Check raw frames consistency */
642 if (cr2res_obs_2d_check_inputs_validity(rawframe_obj) != 1) {
643 cpl_msg_error(__func__, "Invalid Inputs") ;
644 return -1 ;
645 }
646
647 /* Get the order zeropoint */
648 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(trace_wave_frame),
649 0)) == NULL) {
650 cpl_msg_error(__func__, "Cannot read the ORDER_ZP from the input TW") ;
651 return -1 ;
652 }
653 order_zp = cr2res_pfits_get_order_zp(plist) ;
654 cpl_propertylist_delete(plist) ;
655 if (cpl_error_get_code()) {
656 cpl_msg_error(__func__, "Missing ORDER_ZP in the header - Skip") ;
657 cpl_error_reset() ;
658 /* Negative Zerop to log the fact that it is missing */
659 order_zp = -100 ;
660 }
661
662 /* Get the DIT */
663 plist = cpl_propertylist_load(cpl_frame_get_filename(rawframe_obj), 0) ;
664 dit = cr2res_pfits_get_dit(plist) ;
665 ndit = cr2res_pfits_get_ndit(plist) ;
666 cpl_propertylist_delete(plist);
667 if (cpl_error_get_code()) {
668 cpl_msg_error(__func__, "Cannot read the DIT & NDIT") ;
669 return -1 ;
670 }
671 cpl_msg_debug(__func__, "DIT value : %g", dit) ;
672
673 /* Load the input image */
674 if ((in = cr2res_io_load_image(cpl_frame_get_filename(rawframe_obj),
675 reduce_det)) == NULL) {
676 cpl_msg_error(__func__, "Cannot load image") ;
677 return -1 ;
678 }
679
680 /* Calibrate the image */
681 if ((in_calib = cr2res_calib_image(in, reduce_det, 0,
682 subtract_nolight_rows, subtract_interorder_column, cosmics,
683 master_flat_frame, master_dark_frame, bpm_frame,
684 detlin_frame, dit, ndit)) == NULL) {
685 cpl_msg_error(__func__, "Failed to apply the calibrations") ;
687 return -1 ;
688 }
690
691 /* Correct for the sky */
692 if (sky_average != NULL && sky_average[reduce_det-1] != NULL) {
693 /* Average SKY correction */
694 hdrl_image_sub_image(in_calib, sky_average[reduce_det-1]) ;
695 } else if (rawframe_sky != NULL) {
696 /* Individual SKY correction */
697
698 /* Get the DIT */
699 plist = cpl_propertylist_load(cpl_frame_get_filename(rawframe_sky), 0) ;
700 dit_sky = cr2res_pfits_get_dit(plist) ;
701 ndit_sky = cr2res_pfits_get_ndit(plist) ;
702 cpl_propertylist_delete(plist);
703 if (cpl_error_get_code()) {
704 cpl_msg_error(__func__, "Cannot read the DIT from the sky") ;
705 hdrl_image_delete(in_calib) ;
706 return -1 ;
707 }
708 cpl_msg_debug(__func__, "SKY DIT value : %g", dit) ;
709
710 /* Load the input image */
711 if ((in_sky = cr2res_io_load_image(cpl_frame_get_filename(rawframe_sky),
712 reduce_det)) == NULL) {
713 cpl_msg_error(__func__, "Cannot load sky image") ;
714 hdrl_image_delete(in_calib) ;
715 return -1 ;
716 }
717
718 /* Calibrate the image */
719 if ((in_sky_calib = cr2res_calib_image(in_sky, reduce_det, 0,
720 subtract_nolight_rows, subtract_interorder_column, cosmics,
721 master_flat_frame, master_dark_frame, bpm_frame, detlin_frame,
722 dit_sky, ndit_sky)) == NULL) {
723 cpl_msg_error(__func__,
724 "Failed to apply the calibrations to SKY") ;
725 hdrl_image_delete(in_calib) ;
726 hdrl_image_delete(in_sky) ;
727 return -1 ;
728 }
729 hdrl_image_delete(in_sky) ;
730
731 /* Subtract the SKY */
732 hdrl_image_sub_image(in_calib, in_sky_calib) ;
733 hdrl_image_delete(in_sky_calib) ;
734 } else {
735 cpl_msg_warning(__func__, "No Sky Correction") ;
736 }
737
738 /* Load the trace wave */
739 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
740 if ((trace_wave = cr2res_io_load_TRACE_WAVE(
741 cpl_frame_get_filename(trace_wave_frame),
742 reduce_det)) == NULL) {
743 cpl_msg_error(__func__, "Failed to Load the traces file") ;
744 hdrl_image_delete(in_calib) ;
745 return -1 ;
746 }
747
748 /* Execute the extraction */
749 cpl_msg_info(__func__, "Spectra Extraction 2D") ;
750 if (cr2res_extract2d_traces(in_calib, trace_wave, reduce_order,
751 reduce_trace, &extracted) == -1) {
752 cpl_msg_error(__func__, "Failed to extract");
753 hdrl_image_delete(in_calib) ;
754 cpl_table_delete(trace_wave) ;
755 return -1 ;
756 }
757
758 /* Extension header for products */
759 plist = cpl_propertylist_load(
760 cpl_frame_get_filename(rawframe_obj),
761 cr2res_io_get_ext_idx(cpl_frame_get_filename(rawframe_obj),
762 reduce_det, 1)) ;
763
764 /* Compute the QC parameters */
765
766 /* Real Orders in QCs */
767 if (order_zp > 0) {
768 cpl_size i;
769 /* Get the order numbers from the TW rows */
770 order_idx_values = cr2res_trace_get_order_idx_values(trace_wave,
771 &nb_order_idx_values);
772
773 /* Compute the Real Order numbers and store them in QCs */
774 for (i = 0; i < nb_order_idx_values; i++) {
775 int order_real, order_idx, order_idxp;
776 char *key_name;
777 order_idx = order_idx_values[i] ;
778 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
779 order_real = cr2res_order_idx_to_real(order_idx, order_zp) ;
780 key_name = cpl_sprintf(CR2RES_HEADER_QC_REAL_ORDER, order_idxp) ;
781 cpl_propertylist_append_int(plist, key_name, order_real) ;
782 cpl_free(key_name) ;
783 }
784 cpl_free(order_idx_values) ;
785 }
786 cpl_table_delete(trace_wave) ;
787
788 /* Return */
789 *extract = extracted ;
790 *calibrated = in_calib ;
791 *ext_plist = plist ;
792
793 return 0 ;
794}
795
796/*----------------------------------------------------------------------------*/
802/*----------------------------------------------------------------------------*/
803static int cr2res_obs_2d_check_inputs_validity(
804 const cpl_frame * rawframe)
805{
806 /* TODO */
807
808 /* Check Inputs */
809 if (rawframe == NULL) return -1 ;
810 return 1 ;
811}
812
813/*----------------------------------------------------------------------------*/
819/*----------------------------------------------------------------------------*/
820static hdrl_image ** cr2res_obs_2d_average_sky(
821 const cpl_frameset * skyframes)
822{
823 hdrl_image ** sky_average ;
824 hdrl_image * avg ;
825 cpl_image * contrib ;
826 int det_nr ;
827
828 /* Check Inputs */
829 if (skyframes == NULL) return NULL ;
830
831 /* Allocate and Initialise */
832 sky_average = cpl_malloc(CR2RES_NB_DETECTORS * sizeof(hdrl_image *)) ;
833 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++)
834 sky_average[det_nr-1] = NULL ;
835
836 /* Loop on the detectors */
837 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
838 hdrl_imagelist *sky_list;
839
840 /* Load the images */
841 sky_list = cr2res_io_load_image_list_from_set(skyframes, det_nr) ;
842
843 /* Compute the average */
844 hdrl_imagelist_collapse_mean(sky_list, &avg, &contrib) ;
845 hdrl_imagelist_delete(sky_list) ;
846 cpl_image_delete(contrib) ;
847
848 /* Store the result */
849 if (cpl_error_get_code() == CPL_ERROR_NONE) {
850 sky_average[det_nr-1] = avg ;
851 }
852 }
853 return sky_average ;
854}
855
856
hdrl_image * cr2res_calib_image(const hdrl_image *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, double dit, int ndit)
The images calibration routine for a given chip.
Definition: cr2res_calib.c:148
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_extract2d_traces(const hdrl_image *img, const cpl_table *traces, int reduce_order, int reduce_trace, cpl_table **extracted)
Extract2d all the passed traces at once.
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_convert_order_idx_to_idxp(int order_idx)
Convert the order_idx to the order_idxp.
Definition: cr2res_io.c:583
int cr2res_io_save_EXTRACT_2D(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 2D extracted spectrum.
Definition: cr2res_io.c:2009
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
cpl_table * cr2res_io_get_eop_table()
Get the eop_table.
Definition: cr2res_io.c:120
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_CALIBRATED(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_image **calib_collapsed, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a CALIBRATED frame.
Definition: cr2res_io.c:1608
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
Definition: cr2res_io.c:1109
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: cr2res_pfits.c:199
int cr2res_pfits_get_ndit(const cpl_propertylist *plist)
find out the NDIT value
Definition: cr2res_pfits.c:363
int cr2res_qc_numsat(const cpl_frameset *frameset)
Calculate the number of saturated pixels.
Definition: cr2res_qc.c:1290
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
int cr2res_order_idx_to_real(int order_idx, int order_zp)
Convert the order_idx into order_real.
Definition: cr2res_utils.c:89
double cr2res_utils_get_center_mjd(const cpl_frameset *frameset)
Calculate the middle of the exposures in the frameset.
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_barycorr_compute(double ra, double dec, const cpl_table *eop_table, double mjdobs, double time_to_mid_exposure, double longitude, double latitude, double elevation, double pressure, double temperature, double humidity, double wavelength, double *barycorr)
Derives the barycentric correction using the erfa function eraApco13(). The latter For a terrestrial ...
cpl_error_code hdrl_image_sub_image(hdrl_image *self, const hdrl_image *other)
Subtract two images, store the result in the first image.
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.