30#include "cr2res_utils.h"
31#include "cr2res_idp.h"
32#include "cr2res_calib.h"
33#include "cr2res_pfits.h"
34#include "cr2res_dfs.h"
35#include "cr2res_bpm.h"
36#include "cr2res_trace.h"
37#include "cr2res_extract.h"
45#define RECIPE_STRING "cr2res_obs_staring"
51int cpl_plugin_get_info(cpl_pluginlist * list);
57static cpl_frameset * cr2res_obs_staring_find_RAW(
58 const cpl_frameset * in) ;
59static int cr2res_obs_staring_check_inputs_validity(
60 const cpl_frameset * rawframes) ;
61static int cr2res_obs_staring_reduce(
62 const cpl_frameset * rawframes,
63 const cpl_frame * trace_wave_frame,
64 const cpl_frame * detlin_frame,
65 const cpl_frame * master_dark_frame,
66 const cpl_frame * master_flat_frame,
67 const cpl_frame * bpm_frame,
68 const cpl_frame * blaze_frame,
69 const cpl_array * slit_frac,
70 int subtract_nolight_rows,
71 int subtract_interorder_column,
73 int extract_oversample,
75 int extract_swath_width,
77 double extract_smooth_slit,
78 double extract_smooth_spec,
80 hdrl_image ** combined,
82 cpl_table ** slitfunc,
84 cpl_propertylist ** ext_plist) ;
85static int cr2res_obs_staring_create(cpl_plugin *);
86static int cr2res_obs_staring_exec(cpl_plugin *);
87static int cr2res_obs_staring_destroy(cpl_plugin *);
88static int cr2res_obs_staring(cpl_frameset *,
const cpl_parameterlist *);
94static char cr2res_obs_staring_description[] =
"\
95Staring Observation \n\
96 This recipe handles staring observations. \n\
99 raw.fits " CR2RES_OBS_STARING_OTHER_RAW
" [1 to n] \n\
100 or " CR2RES_OBS_STARING_JITTER_RAW
" [1 to n] \n\
101 or " CR2RES_OBS_STARING_WAVE_SKY_RAW
" [1 to n] \n\
102 trace.fits " CR2RES_CAL_FLAT_TW_PROCATG
" [1] \n\
103 or " CR2RES_CAL_FLAT_TW_MERGED_PROCATG
" \n\
104 or " CR2RES_UTIL_TRACE_TW_PROCATG
" \n\
105 or " CR2RES_UTIL_WAVE_TW_PROCATG
" \n\
106 or " CR2RES_CAL_WAVE_TW_PROCATG
" \n\
107 or " CR2RES_UTIL_SLIT_CURV_TW_PROCATG
" \n\
108 detlin.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG
" [0 to 1] \n\
109 bpm.fits " CR2RES_CAL_DARK_BPM_PROCATG
" [0 to 1] \n\
110 or " CR2RES_CAL_FLAT_BPM_PROCATG
" \n\
111 or " CR2RES_CAL_DETLIN_BPM_PROCATG
" \n\
112 or " CR2RES_UTIL_BPM_MERGE_PROCATG
" \n\
113 or " CR2RES_UTIL_BPM_SPLIT_PROCATG
" \n\
114 master_dark.fits " CR2RES_CAL_DARK_MASTER_PROCATG
" [0 to 1] \n\
115 master_flat.fits " CR2RES_CAL_FLAT_MASTER_PROCATG
" [0 to 1] \n\
116 blaze.fits " CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG
" [0 to 1] \n\
119 cr2res_obs_staring_slitfunc.fits "
120 CR2RES_OBS_STARING_SLITFUNC_PROCATG
"\n\
121 cr2res_obs_staring_model.fits "
122 CR2RES_OBS_STARING_SLITMODEL_PROCATG
"\n\
123 cr2res_obs_staring_extracted.fits "
124 CR2RES_OBS_STARING_EXTRACT_PROCATG
"\n\
127 loop on detectors d: \n\
128 call cr2res_obs_staring_reduce() \n\
137 cr2res_obs_staring_reduce() \n\
138 Load the input raw frames in an image list \n\
139 Apply the calibrations to the image list \n\
140 Collapse the image list \n\
141 Load the input trace wave \n\
142 Recompute a new trace wave with the specified slit fraction \n\
143 (--slit_frac) if needed \n\
144 Extract the spectra from the collapsed image \n\
149 Compute QC parameters \n\
151 Library functions used \n\
152 cr2res_io_find_TRACE_WAVE() \n\
153 cr2res_io_find_BPM() \n\
154 cr2res_obs_staring_reduce() \n\
155 cr2res_io_read_dits() \n\
156 cr2res_io_load_image_list_from_set() \n\
157 cr2res_calib_imagelist() \n\
158 cr2res_io_load_TRACE_WAVE() \n\
159 cr2res_extract_traces() \n\
160 cr2res_io_save_COMBINED() \n\
161 cr2res_io_save_EXTRACT_1D() \n\
162 cr2res_io_save_SLIT_FUNC() \n\
180int cpl_plugin_get_info(cpl_pluginlist * list)
182 cpl_recipe * recipe = cpl_calloc(1,
sizeof *recipe );
183 cpl_plugin * plugin = &recipe->interface;
185 if (cpl_plugin_init(plugin,
187 CR2RES_BINARY_VERSION,
188 CPL_PLUGIN_TYPE_RECIPE,
190 "Staring Observation recipe",
191 cr2res_obs_staring_description,
192 CR2RES_PIPELINE_AUTHORS,
195 cr2res_obs_staring_create,
196 cr2res_obs_staring_exec,
197 cr2res_obs_staring_destroy)) {
198 cpl_msg_error(cpl_func,
"Plugin initialization failed");
199 (void)cpl_error_set_where(cpl_func);
203 if (cpl_pluginlist_append(list, plugin)) {
204 cpl_msg_error(cpl_func,
"Error adding plugin to list");
205 (void)cpl_error_set_where(cpl_func);
221static int cr2res_obs_staring_create(cpl_plugin * plugin)
223 cpl_recipe * recipe ;
227 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
228 recipe = (cpl_recipe *)plugin;
233 recipe->parameters = cpl_parameterlist_new();
237 p = cpl_parameter_new_value(
238 "cr2res.cr2res_obs_staring.subtract_nolight_rows",
240 "Subtract median row from baffled region at detector bottom",
241 "cr2res.cr2res_obs_staring", FALSE);
242 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"subtract_nolight_rows");
243 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
244 cpl_parameterlist_append(recipe->parameters, p);
246 p = cpl_parameter_new_value(
247 "cr2res.cr2res_obs_staring.subtract_interorder_column",
249 "Subtract column-by-column fit to the pixel values between"
251 "cr2res.cr2res_obs_staring", TRUE);
252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
253 "subtract_interorder_column");
254 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
255 cpl_parameterlist_append(recipe->parameters, p);
257 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.cosmics",
258 CPL_TYPE_BOOL,
"Find and mark cosmic rays hits as bad",
259 "cr2res.cr2res_obs_staring", FALSE);
260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
261 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
262 cpl_parameterlist_append(recipe->parameters, p);
264 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.slit_frac",
265 CPL_TYPE_STRING,
"Wished slit fraction",
266 "cr2res.cr2res_obs_staring",
"-1.0, -1.0");
267 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slit_frac");
268 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
269 cpl_parameterlist_append(recipe->parameters, p);
271 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_oversample",
272 CPL_TYPE_INT,
"factor by which to oversample the extraction",
273 "cr2res.cr2res_obs_staring", 5);
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_oversample");
275 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
276 cpl_parameterlist_append(recipe->parameters, p);
278 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_pclip",
279 CPL_TYPE_DOUBLE,
"percentage of high and low pixels to clip on first iteration",
280 "cr2res.cr2res_obs_staring", 0.1);
281 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_pclip");
282 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
283 cpl_parameterlist_append(recipe->parameters, p);
285 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_swath_width",
286 CPL_TYPE_INT,
"The swath width",
"cr2res.cr2res_obs_staring", 2048);
287 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_swath_width");
288 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
289 cpl_parameterlist_append(recipe->parameters, p);
291 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_height",
292 CPL_TYPE_INT,
"Extraction height",
293 "cr2res.cr2res_obs_staring", -1);
294 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_height");
295 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
296 cpl_parameterlist_append(recipe->parameters, p);
298 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_smooth_slit",
300 "Smoothing along the slit (1 for high S/N, 5 for low)",
301 "cr2res.cr2res_obs_staring", 2.0);
302 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_slit");
303 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
304 cpl_parameterlist_append(recipe->parameters, p);
306 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.extract_smooth_spec",
307 CPL_TYPE_DOUBLE,
"Smoothing along the spectrum",
308 "cr2res.cr2res_obs_staring", 0.0);
309 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_spec");
310 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
311 cpl_parameterlist_append(recipe->parameters, p);
313 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.detector",
314 CPL_TYPE_INT,
"Only reduce the specified detector",
315 "cr2res.cr2res_obs_staring", 0);
316 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detector");
317 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
318 cpl_parameterlist_append(recipe->parameters, p);
320 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.create_idp",
321 CPL_TYPE_BOOL,
"Flag to produce IDP files",
322 "cr2res.cr2res_obs_staring", FALSE);
323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"idp");
324 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
325 cpl_parameterlist_append(recipe->parameters, p);
327 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.display_order",
328 CPL_TYPE_INT,
"Apply the display for the specified order",
329 "cr2res.cr2res_obs_staring", 0);
330 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"display_order");
331 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
332 cpl_parameterlist_append(recipe->parameters, p);
334 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_staring.display_trace",
335 CPL_TYPE_INT,
"Apply the display for the specified trace",
336 "cr2res.cr2res_obs_staring", 0);
337 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"display_trace");
338 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
339 cpl_parameterlist_append(recipe->parameters, p);
351static int cr2res_obs_staring_exec(cpl_plugin * plugin)
356 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
357 recipe = (cpl_recipe *)plugin;
360 return cr2res_obs_staring(recipe->frames, recipe->parameters);
370static int cr2res_obs_staring_destroy(cpl_plugin * plugin)
375 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
376 recipe = (cpl_recipe *)plugin;
379 cpl_parameterlist_delete(recipe->parameters);
391static int cr2res_obs_staring(
392 cpl_frameset * frameset,
393 const cpl_parameterlist * parlist)
395 const cpl_parameter * param ;
396 int subtract_nolight_rows, subtract_interorder_column,
397 extract_oversample, create_idp, cosmics,
398 extract_swath_width, extract_height, reduce_det;
399 double extract_smooth_slit, extract_smooth_spec,
400 extract_pclip, slit_low, slit_up ;
402 cpl_array * slit_frac ;
403 cpl_frameset * rawframes ;
404 const cpl_frame * trace_wave_frame ;
405 const cpl_frame * detlin_frame ;
406 const cpl_frame * master_dark_frame ;
407 const cpl_frame * master_flat_frame ;
408 const cpl_frame * bpm_frame ;
409 const cpl_frame * blaze_frame ;
411 hdrl_image * combined[CR2RES_NB_DETECTORS] ;
412 cpl_table * extract[CR2RES_NB_DETECTORS] ;
413 cpl_table * slitfunc[CR2RES_NB_DETECTORS] ;
414 hdrl_image * model[CR2RES_NB_DETECTORS] ;
415 cpl_propertylist * qc_main ;
416 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
418 cpl_table * eop_table ;
422 param = cpl_parameterlist_find_const(parlist,
423 "cr2res.cr2res_obs_staring.subtract_nolight_rows");
424 subtract_nolight_rows = cpl_parameter_get_bool(param);
425 param = cpl_parameterlist_find_const(parlist,
426 "cr2res.cr2res_obs_staring.subtract_interorder_column");
427 subtract_interorder_column = cpl_parameter_get_bool(param);
428 param = cpl_parameterlist_find_const(parlist,
429 "cr2res.cr2res_obs_staring.cosmics");
430 cosmics = cpl_parameter_get_bool(param);
431 param = cpl_parameterlist_find_const(parlist,
432 "cr2res.cr2res_obs_staring.extract_oversample");
433 extract_oversample = cpl_parameter_get_int(param);
434 param = cpl_parameterlist_find_const(parlist,
435 "cr2res.cr2res_obs_staring.extract_pclip");
436 extract_pclip = cpl_parameter_get_double(param);
437 param = cpl_parameterlist_find_const(parlist,
438 "cr2res.cr2res_obs_staring.extract_swath_width");
439 extract_swath_width = cpl_parameter_get_int(param);
440 param = cpl_parameterlist_find_const(parlist,
441 "cr2res.cr2res_obs_staring.extract_height");
442 extract_height = cpl_parameter_get_int(param);
443 param = cpl_parameterlist_find_const(parlist,
444 "cr2res.cr2res_obs_staring.extract_smooth_slit");
445 extract_smooth_slit = cpl_parameter_get_double(param);
446 param = cpl_parameterlist_find_const(parlist,
447 "cr2res.cr2res_obs_staring.extract_smooth_spec");
448 extract_smooth_spec = cpl_parameter_get_double(param);
449 param = cpl_parameterlist_find_const(parlist,
450 "cr2res.cr2res_obs_staring.detector");
451 reduce_det = cpl_parameter_get_int(param);
452 param = cpl_parameterlist_find_const(parlist,
453 "cr2res.cr2res_obs_staring.create_idp");
454 create_idp = cpl_parameter_get_bool(param);
461 param = cpl_parameterlist_find_const(parlist,
462 "cr2res.cr2res_obs_staring.slit_frac");
463 sval = cpl_parameter_get_string(param) ;
464 if (sscanf(sval,
"%lg,%lg", &slit_low, &slit_up) != 2) {
465 cpl_msg_error(__func__,
"Invalid Slit Fraction specified");
466 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
471 if (slit_low >= 0.0 && slit_up >= 0.0 && slit_low <= 1.0 && slit_up <= 1.0
472 && slit_up > slit_low) {
473 slit_frac = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
474 cpl_array_set(slit_frac, 0, slit_low) ;
475 cpl_array_set(slit_frac, 1, (slit_low+slit_up)/2.0) ;
476 cpl_array_set(slit_frac, 2, slit_up) ;
483 if (slit_frac != NULL) cpl_array_delete(slit_frac) ;
484 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
485 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
491 if (trace_wave_frame == NULL) {
492 if (slit_frac != NULL) cpl_array_delete(slit_frac) ;
493 cpl_msg_error(__func__,
"Could not find TRACE_WAVE frame") ;
496 detlin_frame = cpl_frameset_find_const(frameset,
497 CR2RES_CAL_DETLIN_COEFFS_PROCATG);
498 master_dark_frame = cpl_frameset_find_const(frameset,
499 CR2RES_CAL_DARK_MASTER_PROCATG) ;
500 master_flat_frame = cpl_frameset_find_const(frameset,
501 CR2RES_CAL_FLAT_MASTER_PROCATG) ;
503 blaze_frame = cpl_frameset_find_const(frameset,
504 CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG) ;
507 rawframes = cr2res_obs_staring_find_RAW(frameset) ;
508 if (rawframes == NULL) {
509 if (slit_frac != NULL) cpl_array_delete(slit_frac) ;
510 cpl_msg_error(__func__,
"Could not find RAW frames") ;
515 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
517 combined[det_nr-1] = NULL ;
518 extract[det_nr-1] = NULL ;
519 slitfunc[det_nr-1] = NULL ;
520 model[det_nr-1] = NULL ;
521 ext_plist[det_nr-1] = NULL ;
524 if (reduce_det != 0 && det_nr != reduce_det) continue ;
526 cpl_msg_info(__func__,
"Process Detector %d", det_nr) ;
527 cpl_msg_indent_more() ;
530 if (cr2res_obs_staring_reduce(rawframes,
531 trace_wave_frame, detlin_frame, master_dark_frame,
532 master_flat_frame, bpm_frame, blaze_frame, slit_frac,
533 subtract_nolight_rows, subtract_interorder_column,
534 cosmics, extract_oversample, extract_pclip,
535 extract_swath_width, extract_height, extract_smooth_slit,
536 extract_smooth_spec, det_nr,
537 &(combined[det_nr-1]),
538 &(extract[det_nr-1]),
539 &(slitfunc[det_nr-1]),
541 &(ext_plist[det_nr-1])) == -1) {
542 cpl_msg_warning(__func__,
"Failed to reduce detector %d", det_nr);
544 cpl_msg_indent_less() ;
546 cpl_msg_indent_less() ;
548 if (slit_frac != NULL) cpl_array_delete(slit_frac) ;
553 qc_main = cpl_propertylist_new();
554 cpl_propertylist_append_double(qc_main,
555 CR2RES_HEADER_DRS_TMID,
560 if (eop_table != NULL) {
561 double ra, dec, mjd_obs, geolon, geolat, geoelev;
562 cpl_propertylist *plist;
563 plist=cpl_propertylist_load(cpl_frame_get_filename(
564 cpl_frameset_get_position_const(rawframes, 0)), 0) ;
566 ra = cpl_propertylist_get_double(plist,
"RA") ;
567 dec = cpl_propertylist_get_double(plist,
"DEC") ;
568 mjd_obs = cpl_propertylist_get_double(plist,
"MJD-OBS") ;
569 geolon = cpl_propertylist_get_double(plist,
"ESO TEL GEOLON") ;
570 geolat = cpl_propertylist_get_double(plist,
"ESO TEL GEOLAT") ;
571 geoelev = cpl_propertylist_get_double(plist,
"ESO TEL GEOELEV") ;
573 cpl_propertylist_delete(plist) ;
576 if (!cpl_error_get_code()) {
580 (mjd_cen-mjd_obs)*24*3600, geolon, geolat, geoelev,
581 0.0, 0.0, 0.0, 0.0, &barycorr);
583 cpl_msg_info(__func__,
"Barycentric correction: %g m/s",
587 cpl_msg_info(__func__,
"Cannot derive Barycentric correction");
590 cpl_table_delete(eop_table) ;
591 cpl_propertylist_append_double(qc_main, CR2RES_HEADER_DRS_BARYCORR,
596 cpl_propertylist_append_int(qc_main,
597 CR2RES_HEADER_QC_NUMSAT,
601 if (trace_wave_frame != NULL)
602 cpl_frameset_insert(rawframes,
603 cpl_frame_duplicate(trace_wave_frame)) ;
604 if (detlin_frame != NULL)
605 cpl_frameset_insert(rawframes,
606 cpl_frame_duplicate(detlin_frame)) ;
607 if (master_dark_frame != NULL)
608 cpl_frameset_insert(rawframes,
609 cpl_frame_duplicate(master_dark_frame)) ;
610 if (master_flat_frame!= NULL)
611 cpl_frameset_insert(rawframes,
612 cpl_frame_duplicate(master_flat_frame)) ;
613 if (bpm_frame!= NULL)
614 cpl_frameset_insert(rawframes,
615 cpl_frame_duplicate(bpm_frame)) ;
616 if (blaze_frame!= NULL)
617 cpl_frameset_insert(rawframes,
618 cpl_frame_duplicate(blaze_frame)) ;
620 out_file = cpl_sprintf(
"%s_combined.fits", RECIPE_STRING) ;
622 combined, qc_main, ext_plist,
623 CR2RES_OBS_STARING_COMBINED_PROCATG, RECIPE_STRING) ;
626 out_file = cpl_sprintf(
"%s_slitfunc.fits", RECIPE_STRING) ;
628 slitfunc, qc_main, ext_plist, CR2RES_OBS_STARING_SLITFUNC_PROCATG,
632 out_file = cpl_sprintf(
"%s_model.fits", RECIPE_STRING) ;
634 model, qc_main, ext_plist, CR2RES_OBS_STARING_SLITMODEL_PROCATG,
638 out_file = cpl_sprintf(
"%s_extracted.fits", RECIPE_STRING) ;
640 qc_main, ext_plist, CR2RES_OBS_STARING_EXTRACT_PROCATG,
644 extract, qc_main, ext_plist,
645 CR2RES_OBS_STARING_IDP_PROCATG,
649 cpl_frameset_delete(rawframes) ;
652 cpl_propertylist_delete(qc_main) ;
653 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
654 if (combined[det_nr-1] != NULL)
656 if (extract[det_nr-1] != NULL)
657 cpl_table_delete(extract[det_nr-1]) ;
658 if (slitfunc[det_nr-1] != NULL)
659 cpl_table_delete(slitfunc[det_nr-1]) ;
660 if (model[det_nr-1] != NULL)
662 if (ext_plist[det_nr-1] != NULL)
663 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
666 return (
int)cpl_error_get_code();
695static int cr2res_obs_staring_reduce(
696 const cpl_frameset * rawframes,
697 const cpl_frame * trace_wave_frame,
698 const cpl_frame * detlin_frame,
699 const cpl_frame * master_dark_frame,
700 const cpl_frame * master_flat_frame,
701 const cpl_frame * bpm_frame,
702 const cpl_frame * blaze_frame,
703 const cpl_array * slit_frac,
704 int subtract_nolight_rows,
705 int subtract_interorder_column,
707 int extract_oversample,
708 double extract_pclip,
709 int extract_swath_width,
711 double extract_smooth_slit,
712 double extract_smooth_spec,
714 hdrl_image ** combined,
715 cpl_table ** extract,
716 cpl_table ** slitfunc,
718 cpl_propertylist ** ext_plist)
720 hdrl_imagelist * in ;
721 hdrl_imagelist * in_calib ;
724 cpl_table * blaze_table ;
725 cpl_table * trace_wave ;
726 cpl_table * trace_wave_new ;
727 hdrl_image * collapsed ;
728 cpl_image * contrib ;
729 cpl_propertylist * plist ;
731 hdrl_image * model_master ;
732 cpl_table * slit_func ;
733 cpl_table * extracted ;
734 int * order_idx_values ;
736 cpl_array * fwhm_array ;
738 const char * first_fname ;
739 double qc_signal, qc_fwhm, gain, error_factor, blaze_norm ;
740 int order_zp, nb_order_idx_values,
741 order_idx, order_idxp ;
744 if (combined == NULL || extract == NULL || ext_plist == NULL ||
745 rawframes == NULL || trace_wave_frame == NULL)
return -1 ;
748 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
749 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
750 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
752 cpl_msg_error(__func__,
"Failed to get the Gain value") ;
757 if (cr2res_obs_staring_check_inputs_validity(rawframes) != 1) {
758 cpl_msg_error(__func__,
"Invalid Inputs") ;
763 first_fname = cpl_frame_get_filename(
764 cpl_frameset_get_position_const(rawframes, 0)) ;
767 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(trace_wave_frame),
769 cpl_msg_error(__func__,
"Cannot read the ORDER_ZP from the input TW") ;
772 order_zp = cr2res_pfits_get_order_zp(plist) ;
773 cpl_propertylist_delete(plist) ;
774 if (cpl_error_get_code()) {
775 cpl_msg_error(__func__,
"Missing ORDER_ZP in the header - Skip") ;
784 if (cpl_msg_get_level() == CPL_MSG_DEBUG && dits != NULL)
785 cpl_vector_dump(dits, stdout) ;
792 reduce_det)) == NULL) {
793 cpl_msg_error(__func__,
"Cannot load images") ;
794 if (dits != NULL) cpl_vector_delete(dits) ;
798 cpl_msg_error(__func__,
"Inconsistent number of loaded images") ;
799 if (dits != NULL) cpl_vector_delete(dits) ;
805 error_factor = gain * cpl_vector_get(ndits, 0) *
806 cpl_frameset_get_size(rawframes) ;
808 for (i=0; i<cpl_vector_get_size(ndits); i++){
809 if (cpl_vector_get(ndits,i) != cpl_vector_get(ndits, 0))
810 cpl_msg_warning(__func__,
"Raw frames have different NDIT! "
811 "Error spectrum will likely be scaled incorrectly.");
816 subtract_nolight_rows, subtract_interorder_column, cosmics,
817 master_flat_frame, master_dark_frame, bpm_frame, detlin_frame,
818 dits, ndits))==NULL) {
819 cpl_msg_error(__func__,
"Failed to apply the calibrations") ;
820 if (dits != NULL) cpl_vector_delete(dits) ;
821 if (ndits != NULL) cpl_vector_delete(ndits) ;
826 if (dits != NULL) cpl_vector_delete(dits) ;
827 if (ndits != NULL) cpl_vector_delete(ndits) ;
830 cpl_msg_info(__func__,
"Collapse") ;
831 cpl_msg_indent_more() ;
834 cpl_msg_error(__func__,
"Failed to Collapse") ;
836 cpl_msg_indent_less() ;
839 cpl_image_delete(contrib) ;
841 cpl_msg_indent_less() ;
844 cpl_msg_info(__func__,
"Load the TRACE WAVE") ;
846 trace_wave_frame), reduce_det)) == NULL) {
847 cpl_msg_error(__func__,
"Failed to Load the traces file") ;
853 if (slit_frac != NULL) {
855 trace_wave, slit_frac)) == NULL) {
856 cpl_msg_warning(__func__,
857 "Failed to compute the traces for user specified slit fraction") ;
860 cpl_table_delete(trace_wave) ;
861 trace_wave = trace_wave_new ;
862 trace_wave_new = NULL ;
869 if (blaze_frame != NULL) {
870 cpl_msg_info(__func__,
"Load the BLAZE") ;
872 blaze_frame), reduce_det)) == NULL) {
873 cpl_msg_error(__func__,
"Failed to Load the Blaze file") ;
875 cpl_table_delete(trace_wave) ;
878 cpl_propertylist * blaze_plist ;
879 blaze_plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(
880 blaze_frame),0,CR2RES_HEADER_QC_BLAZE_NORM,0);
881 if(cpl_propertylist_get_size(blaze_plist)>0){
882 blaze_norm = cpl_propertylist_get_double(blaze_plist, CR2RES_HEADER_QC_BLAZE_NORM);
886 cpl_msg_warning(__func__,
"QC BLAZE NORM value not found, reverting to per trace normalization") ;
888 if(blaze_plist!=NULL){
889 cpl_propertylist_delete(blaze_plist);
894 int extract_niter = 10;
895 double extract_kappa = 10;
898 cpl_msg_info(__func__,
"Spectra Extraction") ;
900 CR2RES_EXTR_OPT_CURV, extract_height, extract_swath_width,
901 extract_oversample, extract_pclip, extract_smooth_slit, extract_smooth_spec,
902 extract_niter, extract_kappa, error_factor,
903 0, 0, 0, &extracted, &slit_func, &model_master) == -1) {
904 cpl_msg_error(__func__,
"Failed to extract");
906 cpl_table_delete(trace_wave) ;
909 if (blaze_table != NULL) cpl_table_delete(blaze_table) ;
912 plist = cpl_propertylist_load(first_fname,
917 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SIGNAL, qc_signal) ;
920 qc_snrs =
cr2res_qc_snr(trace_wave, extracted, &order_idx_values,
921 &nb_order_idx_values) ;
922 for (i=0 ; i<nb_order_idx_values ; i++) {
923 order_idx = order_idx_values[i] ;
925 key_name = cpl_sprintf(CR2RES_HEADER_QC_SNR, order_idxp) ;
926 cpl_propertylist_append_double(plist, key_name, qc_snrs[i]) ;
929 cpl_free(order_idx_values) ;
934 &nb_order_idx_values);
937 fwhm_array = cpl_array_new(nb_order_idx_values, CPL_TYPE_DOUBLE);
938 for (i=0 ; i<nb_order_idx_values ; i++) {
939 order_idx = order_idx_values[i] ;
944 key_name = cpl_sprintf(CR2RES_HEADER_QC_SLITFWHM_ORDER, order_idxp) ;
945 cpl_propertylist_append_double(plist, key_name, qc_fwhm) ;
947 cpl_array_set(fwhm_array, i, qc_fwhm) ;
949 cpl_free(order_idx_values) ;
950 qc_fwhm = cpl_array_get_median(fwhm_array);
951 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SLITFWHM_MED,
954 cpl_msg_warning(__func__,
"Median FWHM of the PSF along the slit "
955 "is %gpix, i.e. below the slit width. This means the slit "
956 "is likely not evenly filled with light "
957 "in the spectral direction. This can result in a "
958 "wavelength offset between different positions along the slit,"
959 " and with respect to calibrations."
963 cpl_array_delete(fwhm_array) ;
969 &nb_order_idx_values);
972 for (i = 0; i < nb_order_idx_values; i++) {
974 order_idx = order_idx_values[i] ;
977 key_name = cpl_sprintf(CR2RES_HEADER_QC_REAL_ORDER, order_idxp) ;
978 cpl_propertylist_append_int(plist, key_name, order_real) ;
981 cpl_free(order_idx_values) ;
983 cpl_table_delete(trace_wave) ;
986 *combined = collapsed ;
987 *extract = extracted ;
988 *slitfunc = slit_func ;
989 *model = model_master ;
1002static int cr2res_obs_staring_check_inputs_validity(
1003 const cpl_frameset * rawframes)
1006 if (rawframes == NULL)
return -1 ;
1020static cpl_frameset * cr2res_obs_staring_find_RAW(
1021 const cpl_frameset * in)
1023 cpl_frameset * out ;
1026 if (in == NULL)
return NULL ;
hdrl_imagelist * cr2res_calib_imagelist(const hdrl_imagelist *in, int chip, int clean_bad, int subtract_nolight_rows, int subtract_interorder_column, int cosmics_corr, const cpl_frame *flat, const cpl_frame *dark, const cpl_frame *bpm, const cpl_frame *detlin, const cpl_vector *dits, const cpl_vector *ndits)
The images calibration routine for a given chip on a list.
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
int cr2res_idp_save(const char *filename, cpl_frameset *allframes, cpl_frameset *rawframes, const cpl_parameterlist *parlist, cpl_table **tables, cpl_propertylist *main_qc_plist, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save an IDP file.
cpl_table * cr2res_io_load_EXTRACT_1D(const char *filename, int detector)
Load a table from a EXTRACT_1D.
const cpl_frame * cr2res_io_find_BPM(const cpl_frameset *in)
Get the first CR2RES_BPM_DRSTYPE frame from a frameset.
int cr2res_io_save_SLIT_MODEL(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_image **data, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_MODEL.
const cpl_frame * cr2res_io_find_TRACE_WAVE(const cpl_frameset *in)
Get the first CR2RES_TW_DRSTYPE frame from a frameset.
int cr2res_io_convert_order_idx_to_idxp(int order_idx)
Convert the order_idx to the order_idxp.
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
int cr2res_io_save_EXTRACT_1D(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a 1D extracted spectrum.
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
cpl_table * cr2res_io_get_eop_table()
Get the eop_table.
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
int cr2res_io_save_SLIT_FUNC(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **slit_func, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_FUNC.
int cr2res_io_save_COMBINED(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 COMBINED.
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
int cr2res_qc_numsat(const cpl_frameset *frameset)
Calculate the number of saturated pixels.
double cr2res_qc_obs_nodding_signal(const cpl_table *extracted)
Computes the integrated flux over part of the spectrum.
double * cr2res_qc_snr(const cpl_table *tw, const cpl_table *extracted, int **out_order_idx_values, int *out_nb_order_idx_values)
Computes the SNR of several spectra.
double cr2res_qc_obs_slit_psf(const cpl_table *slitfu, int order_idxp, int oversample)
Computes the FWHM of the PSF along the slit for a given order.
cpl_table * cr2res_trace_new_slit_fraction(const cpl_table *traces, const cpl_array *new_slit_fraction)
Recompute the traces at a newly specified slit fraction.
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.
int cr2res_order_idx_to_real(int order_idx, int order_zp)
Convert the order_idx into order_real.
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 ...
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.