31#include "cr2res_utils.h"
32#include "cr2res_idp.h"
33#include "cr2res_nodding.h"
34#include "cr2res_calib.h"
35#include "cr2res_pfits.h"
36#include "cr2res_dfs.h"
37#include "cr2res_bpm.h"
38#include "cr2res_trace.h"
39#include "cr2res_extract.h"
42#include "cr2res_photom.h"
48#define RECIPE_STRING "cr2res_obs_nodding"
54int cpl_plugin_get_info(cpl_pluginlist * list);
60static int cr2res_obs_nodding_astrometry_compare(
61 const cpl_frame * frame1,
62 const cpl_frame * frame2) ;
63static cpl_frameset * cr2res_obs_nodding_find_RAW(
64 const cpl_frameset * in,
66static int cr2res_obs_nodding_check_inputs_validity(
67 const cpl_frameset * rawframes) ;
68static int cr2res_obs_nodding_reduce(
69 const cpl_frameset * rawframes,
70 const cpl_frame * trace_wave_frame,
71 const cpl_frame * detlin_frame,
72 const cpl_frame * master_dark_frame,
73 const cpl_frame * master_flat_frame,
74 const cpl_frame * bpm_frame,
75 const cpl_frame * blaze_frame,
77 int subtract_nolight_rows,
78 int subtract_interorder_column,
81 int extract_oversample,
83 int extract_swath_width,
85 double extract_smooth_slit,
86 double extract_smooth_spec,
93 hdrl_image ** combineda,
94 cpl_table ** extracta,
95 cpl_table ** slitfunca,
98 hdrl_image ** combinedb,
99 cpl_table ** extractb,
100 cpl_table ** slitfuncb,
101 hdrl_image ** modelb,
103 cpl_table ** extractc,
104 cpl_propertylist ** ext_plist) ;
106static int cr2res_obs_nodding_create(cpl_plugin *);
107static int cr2res_obs_nodding_exec(cpl_plugin *);
108static int cr2res_obs_nodding_destroy(cpl_plugin *);
109static int cr2res_obs_nodding(cpl_frameset *,
const cpl_parameterlist *);
115static char cr2res_obs_nodding_description[] =
"\
116Nodding Observation \n\
117 This recipe handles nodding observations. It expects an even number \n\
118 of rawframes in input, and as many A positions as B positions \n\
119 If the input are standard stars, it computes a post processing step \n\
120 to determine the throughput. \n\
121 If the input are spectro astrometric data, it will apply the nodding \n\
122 on each of the sub-groups \n\
125 raw.fits " CR2RES_CAL_NODDING_OTHER_RAW
" [2 to 2n] \n\
126 or " CR2RES_CAL_NODDING_JITTER_RAW
" [2 to 2n] \n\
127 or " CR2RES_OBS_NODDING_OTHER_RAW
" [2 to 2n] \n\
128 or " CR2RES_OBS_NODDING_JITTER_RAW
" [2 to 2n] \n\
129 or " CR2RES_OBS_ASTROMETRY_OTHER_RAW
" [2 to 2n] \n\
130 or " CR2RES_OBS_ASTROMETRY_JITTER_RAW
" [2 to 2n] \n\
131 trace.fits " CR2RES_CAL_FLAT_TW_PROCATG
" [1] \n\
132 or " CR2RES_CAL_FLAT_TW_MERGED_PROCATG
" \n\
133 or " CR2RES_UTIL_TRACE_TW_PROCATG
" \n\
134 or " CR2RES_UTIL_WAVE_TW_PROCATG
" \n\
135 or " CR2RES_CAL_WAVE_TW_PROCATG
" \n\
136 or " CR2RES_UTIL_SLIT_CURV_TW_PROCATG
" \n\
137 detlin.fits " CR2RES_CAL_DETLIN_COEFFS_PROCATG
" [0 to 1] \n\
138 bpm.fits " CR2RES_CAL_DARK_BPM_PROCATG
" [0 to 1] \n\
139 or " CR2RES_CAL_FLAT_BPM_PROCATG
" \n\
140 or " CR2RES_CAL_DETLIN_BPM_PROCATG
" \n\
141 or " CR2RES_UTIL_BPM_MERGE_PROCATG
" \n\
142 or " CR2RES_UTIL_BPM_SPLIT_PROCATG
" \n\
143 master_dark.fits " CR2RES_CAL_DARK_MASTER_PROCATG
" [0 to 1] \n\
144 master_flat.fits " CR2RES_CAL_FLAT_MASTER_PROCATG
" [0 to 1] \n\
145 photo_flux.fits " CR2RES_PHOTO_FLUX_PROCATG
" [0 to 1] \n\
146 blaze.fits " CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG
" [0 to 1] \n\
149 cr2res_obs_nodding_extractedA.fits "
150 CR2RES_OBS_NODDING_EXTRACTA_PROCATG
"\n\
151 cr2res_obs_nodding_extractedB.fits "
152 CR2RES_OBS_NODDING_EXTRACTB_PROCATG
"\n\
153 cr2res_obs_nodding_combinedA.fits "
154 CR2RES_OBS_NODDING_COMBINEDA_PROCATG
"\n\
155 cr2res_obs_nodding_combinedB.fits "
156 CR2RES_OBS_NODDING_COMBINEDB_PROCATG
"\n\
157 cr2res_obs_nodding_trace_wave_A.fits "
158 CR2RES_OBS_NODDING_TWA_PROCATG
"\n\
159 cr2res_obs_nodding_trace_wave_B.fits "
160 CR2RES_OBS_NODDING_TWB_PROCATG
"\n\
161 cr2res_obs_nodding_modelA.fits "
162 CR2RES_OBS_NODDING_SLITMODELA_PROCATG
"\n\
163 cr2res_obs_nodding_modelB.fits "
164 CR2RES_OBS_NODDING_SLITMODELB_PROCATG
"\n\
165 cr2res_obs_nodding_slitfuncA.fits "
166 CR2RES_OBS_NODDING_SLITFUNCA_PROCATG
"\n\
167 cr2res_obs_nodding_slitfuncB.fits "
168 CR2RES_OBS_NODDING_SLITFUNCB_PROCATG
"\n\
169 cr2res_obs_nodding_throughput.fits "
170 CR2RES_OBS_NODDING_THROUGHPUT_PROCATG
"\n\
173 loop on detectors d: \n\
174 call cr2res_obs_nodding_reduce() \n\
175 -> combined[a|b](d) \n\
176 -> extract[a|b|c](d) \n\
177 -> slitfunc[a|b](d) \n\
180 Save combineda and combinedb \n\
181 Save extracta, extractb, extractc \n\
182 Save slitfunca and slitfuncb \n\
183 Save modela and modelb \n\
186 cr2res_obs_nodding_reduce() \n\
187 Load the input raw frames in an image list \n\
188 Apply the calibrations to the image list \n\
189 Split the list in listA and listB image lists \n\
190 Compute diffA=listA-listB and diffB=listB-listA \n\
191 Collapse diffA and diffB \n\
193 Load the input trace wave \n\
194 Compute the slit fractions for A and B by using the nodthrow \n\
195 and the assumption that A and B are at equal distances \n\
196 from the slit center. \n\
197 Compute 2 new trace_wave files with these 2 computed slit fractions\n\
198 Extract the spectra for A and for B \n\
199 -> extracted[a|b] \n\
200 -> slit_func[a|b] \n\
201 -> model_master[a|b] \n\
202 -> trace_wave[a|b] \n\
203 Compute QC parameters \n\
204 If STD star, compute the throughput \n\
207 Library functions used \n\
208 cr2res_io_find_TRACE_WAVE() \n\
209 cr2res_io_find_BPM() \n\
210 cr2res_obs_nodding_reduce() \n\
211 cr2res_nodding_read_positions() \n\
212 cr2res_io_read_dits() \n\
213 cr2res_io_load_image_list_from_set() \n\
214 cr2res_calib_imagelist() \n\
215 cr2res_combine_nodding_split() \n\
216 cr2res_io_load_TRACE_WAVE() \n\
217 cr2res_pfits_get_nodthrow() \n\
218 cr2res_trace_new_slit_fraction() \n\
219 cr2res_extract_traces() \n\
220 cr2res_qc_obs_nodding_signal() \n\
221 cr2res_qc_obs_nodding_transmission() \n\
222 cr2res_qc_obs_slit_psf() \n\
223 cr2res_photom_engine() \n\
224 cr2res_io_save_COMBINED() \n\
225 cr2res_io_save_EXTRACT_1D() \n\
226 cr2res_io_save_SLIT_FUNC() \n\
227 cr2res_io_save_SLIT_MODEL() \n\
228 cr2res_io_save_THROUGHPUT() \n\
247int cpl_plugin_get_info(cpl_pluginlist * list)
249 cpl_recipe * recipe = cpl_calloc(1,
sizeof *recipe );
250 cpl_plugin * plugin = &recipe->interface;
252 if (cpl_plugin_init(plugin,
254 CR2RES_BINARY_VERSION,
255 CPL_PLUGIN_TYPE_RECIPE,
257 "Nodding Observation recipe",
258 cr2res_obs_nodding_description,
259 CR2RES_PIPELINE_AUTHORS,
262 cr2res_obs_nodding_create,
263 cr2res_obs_nodding_exec,
264 cr2res_obs_nodding_destroy)) {
265 cpl_msg_error(cpl_func,
"Plugin initialization failed");
266 (void)cpl_error_set_where(cpl_func);
270 if (cpl_pluginlist_append(list, plugin)) {
271 cpl_msg_error(cpl_func,
"Error adding plugin to list");
272 (void)cpl_error_set_where(cpl_func);
288static int cr2res_obs_nodding_create(cpl_plugin * plugin)
290 cpl_recipe * recipe ;
294 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
295 recipe = (cpl_recipe *)plugin;
300 recipe->parameters = cpl_parameterlist_new();
303 p = cpl_parameter_new_value(
304 "cr2res.cr2res_obs_nodding.subtract_nolight_rows",
306 "Subtract median row from baffled region at detector bottom",
307 "cr2res.cr2res_obs_nodding", FALSE);
308 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"subtract_nolight_rows");
309 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
310 cpl_parameterlist_append(recipe->parameters, p);
312 p = cpl_parameter_new_value(
313 "cr2res.cr2res_obs_nodding.subtract_interorder_column",
315 "Subtract column-by-column fit to the pixel values between orders",
316 "cr2res.cr2res_obs_nodding", TRUE);
317 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
318 "subtract_interorder_column");
319 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
320 cpl_parameterlist_append(recipe->parameters, p);
322 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.cosmics",
323 CPL_TYPE_BOOL,
"Find and mark cosmic rays hits as bad",
324 "cr2res.cr2res_obs_nodding", FALSE);
325 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
326 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
327 cpl_parameterlist_append(recipe->parameters, p);
329 p = cpl_parameter_new_enum(
"cr2res.cr2res_obs_nodding.error_method",
330 CPL_TYPE_STRING,
"The 1d extraction error calculation method",
331 "cr2res.cr2res_obs_nodding",
332 "Poisson", 2,
"Poisson",
"Horne");
333 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"error_method");
334 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
335 cpl_parameterlist_append(recipe->parameters, p);
337 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.nodding_invert",
338 CPL_TYPE_BOOL,
"Flag to use when A is above B",
339 "cr2res.cr2res_obs_nodding", FALSE);
340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nodding_invert");
341 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
342 cpl_parameterlist_append(recipe->parameters, p);
344 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_oversample",
345 CPL_TYPE_INT,
"factor by which to oversample the extraction",
346 "cr2res.cr2res_obs_nodding", 7);
347 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_oversample");
348 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
349 cpl_parameterlist_append(recipe->parameters, p);
351 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_pclip",
352 CPL_TYPE_DOUBLE,
"percentage of high and low pixels to clip on first iteration",
353 "cr2res.cr2res_obs_nodding", 0.1);
354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_pclip");
355 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
356 cpl_parameterlist_append(recipe->parameters, p);
358 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_swath_width",
359 CPL_TYPE_INT,
"The swath width",
"cr2res.cr2res_obs_nodding", 2048);
360 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_swath_width");
361 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
362 cpl_parameterlist_append(recipe->parameters, p);
364 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_height",
365 CPL_TYPE_INT,
"Extraction height",
"cr2res.cr2res_obs_nodding", -1);
366 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_height");
367 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
368 cpl_parameterlist_append(recipe->parameters, p);
370 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_smooth_slit",
371 CPL_TYPE_DOUBLE,
"Smoothing along the slit",
372 "cr2res.cr2res_obs_nodding", 1.0);
373 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_slit");
374 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
375 cpl_parameterlist_append(recipe->parameters, p);
377 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.extract_smooth_spec",
378 CPL_TYPE_DOUBLE,
"Smoothing along spectrum",
379 "cr2res.cr2res_obs_nodding", 8e-8);
380 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extract_smooth_spec");
381 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
382 cpl_parameterlist_append(recipe->parameters, p);
384 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.detector",
385 CPL_TYPE_INT,
"Only reduce the specified detector",
386 "cr2res.cr2res_obs_nodding", 0);
387 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"detector");
388 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
389 cpl_parameterlist_append(recipe->parameters, p);
391 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.create_idp",
392 CPL_TYPE_BOOL,
"Flag to produce IDP files",
393 "cr2res.cr2res_obs_nodding", FALSE);
394 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"idp");
395 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
396 cpl_parameterlist_append(recipe->parameters, p);
398 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.display_detector",
399 CPL_TYPE_INT,
"Apply the display for the specified detector",
400 "cr2res.cr2res_obs_nodding", 0);
401 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"display_detector");
402 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
403 cpl_parameterlist_append(recipe->parameters, p);
405 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.display_order",
406 CPL_TYPE_INT,
"Apply the display for the specified order",
407 "cr2res.cr2res_obs_nodding", 1000);
408 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"display_order");
409 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
410 cpl_parameterlist_append(recipe->parameters, p);
412 p = cpl_parameter_new_value(
"cr2res.cr2res_obs_nodding.display_trace",
413 CPL_TYPE_INT,
"Apply the display for the specified trace",
414 "cr2res.cr2res_obs_nodding", 0);
415 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"display_trace");
416 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
417 cpl_parameterlist_append(recipe->parameters, p);
429static int cr2res_obs_nodding_exec(cpl_plugin * plugin)
434 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
435 recipe = (cpl_recipe *)plugin;
438 return cr2res_obs_nodding(recipe->frames, recipe->parameters);
448static int cr2res_obs_nodding_destroy(cpl_plugin * plugin)
453 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
454 recipe = (cpl_recipe *)plugin;
457 cpl_parameterlist_delete(recipe->parameters);
469static int cr2res_obs_nodding(
470 cpl_frameset * frameset,
471 const cpl_parameterlist * parlist)
473 const cpl_parameter * param ;
474 int extract_oversample, extract_swath_width,
475 extract_height, reduce_det,
476 disp_order_idx, disp_trace, disp_det,
477 nodding_invert, create_idp, subtract_nolight_rows,
478 subtract_interorder_column, cosmics,
480 double extract_smooth_slit, extract_smooth_spec,
483 double ra, dec, mjd_obs, mjd_cen, geolon, geolat, geoelev,
485 cpl_frameset * rawframes ;
486 cpl_frameset * raw_flat_frames ;
487 const cpl_frame * trace_wave_frame ;
488 const cpl_frame * detlin_frame ;
489 const cpl_frame * master_dark_frame ;
490 const cpl_frame * photo_flux_frame ;
491 const cpl_frame * blaze_frame ;
492 const cpl_frame * master_flat_frame ;
493 const cpl_frame * bpm_frame ;
495 cpl_size nlabels, l ;
496 char * product_name_addon ;
497 hdrl_image * combineda[CR2RES_NB_DETECTORS] ;
498 cpl_table * extracta[CR2RES_NB_DETECTORS] ;
499 cpl_table * slitfunca[CR2RES_NB_DETECTORS] ;
500 hdrl_image * modela[CR2RES_NB_DETECTORS] ;
501 cpl_table * twa[CR2RES_NB_DETECTORS] ;
502 hdrl_image * combinedb[CR2RES_NB_DETECTORS] ;
503 cpl_table * extractb[CR2RES_NB_DETECTORS] ;
504 cpl_table * slitfuncb[CR2RES_NB_DETECTORS] ;
505 hdrl_image * modelb[CR2RES_NB_DETECTORS] ;
506 cpl_table * twb[CR2RES_NB_DETECTORS] ;
507 cpl_table * extractc[CR2RES_NB_DETECTORS] ;
508 cpl_table * throughput[CR2RES_NB_DETECTORS] ;
509 cpl_propertylist * qc_main ;
510 cpl_propertylist * ext_plist[CR2RES_NB_DETECTORS] ;
511 cpl_propertylist * ext_plist_photom[CR2RES_NB_DETECTORS] ;
514 cpl_table * eop_table ;
522 param = cpl_parameterlist_find_const(parlist,
523 "cr2res.cr2res_obs_nodding.subtract_nolight_rows");
524 subtract_nolight_rows = cpl_parameter_get_bool(param);
525 param = cpl_parameterlist_find_const(parlist,
526 "cr2res.cr2res_obs_nodding.subtract_interorder_column");
527 subtract_interorder_column = cpl_parameter_get_bool(param);
528 param = cpl_parameterlist_find_const(parlist,
529 "cr2res.cr2res_obs_nodding.nodding_invert");
530 nodding_invert = cpl_parameter_get_bool(param);
531 param = cpl_parameterlist_find_const(parlist,
532 "cr2res.cr2res_obs_nodding.extract_oversample");
533 extract_oversample = cpl_parameter_get_int(param);
534 param = cpl_parameterlist_find_const(parlist,
535 "cr2res.cr2res_obs_nodding.extract_pclip");
536 extract_pclip = cpl_parameter_get_double(param);
537 param = cpl_parameterlist_find_const(parlist,
538 "cr2res.cr2res_obs_nodding.extract_swath_width");
539 extract_swath_width = cpl_parameter_get_int(param);
540 param = cpl_parameterlist_find_const(parlist,
541 "cr2res.cr2res_obs_nodding.extract_height");
542 extract_height = cpl_parameter_get_int(param);
543 param = cpl_parameterlist_find_const(parlist,
544 "cr2res.cr2res_obs_nodding.extract_smooth_slit");
545 extract_smooth_slit = cpl_parameter_get_double(param);
546 param = cpl_parameterlist_find_const(parlist,
547 "cr2res.cr2res_obs_nodding.extract_smooth_spec");
548 extract_smooth_spec = cpl_parameter_get_double(param);
549 param = cpl_parameterlist_find_const(parlist,
550 "cr2res.cr2res_obs_nodding.detector");
551 reduce_det = cpl_parameter_get_int(param);
552 param = cpl_parameterlist_find_const(parlist,
553 "cr2res.cr2res_obs_nodding.create_idp");
554 create_idp = cpl_parameter_get_bool(param);
555 param = cpl_parameterlist_find_const(parlist,
556 "cr2res.cr2res_obs_nodding.display_detector");
557 disp_det = cpl_parameter_get_int(param);
558 param = cpl_parameterlist_find_const(parlist,
559 "cr2res.cr2res_obs_nodding.display_order");
560 disp_order_idx = cpl_parameter_get_int(param);
561 param = cpl_parameterlist_find_const(parlist,
562 "cr2res.cr2res_obs_nodding.display_trace");
563 disp_trace = cpl_parameter_get_int(param);
564 param = cpl_parameterlist_find_const(parlist,
565 "cr2res.cr2res_obs_nodding.cosmics");
566 cosmics = cpl_parameter_get_bool(param);
567 param = cpl_parameterlist_find_const(parlist,
568 "cr2res.cr2res_obs_nodding.error_method");
569 if(strcmp(cpl_parameter_get_string(param),
"Horne") == 0)
570 error_method = CR2RES_EXTRACT_ERROR_HORNE;
572 error_method = CR2RES_EXTRACT_ERROR_POISSON;
575 int extract_niter = 30;
576 double extract_kappa = 10;
580 cpl_msg_error(__func__,
"Cannot identify RAW and CALIB frames") ;
581 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
587 if (trace_wave_frame == NULL) {
588 cpl_msg_error(__func__,
"Could not find TRACE_WAVE frame") ;
591 detlin_frame = cpl_frameset_find_const(frameset,
592 CR2RES_CAL_DETLIN_COEFFS_PROCATG);
593 master_dark_frame = cpl_frameset_find_const(frameset,
594 CR2RES_CAL_DARK_MASTER_PROCATG) ;
595 if (master_dark_frame != NULL) {
596 cpl_msg_warning(__func__,
597 "Providing a MASTER DARK is not recommended for this recipe") ;
599 blaze_frame = cpl_frameset_find_const(frameset,
600 CR2RES_CAL_FLAT_EXTRACT_1D_PROCATG) ;
601 photo_flux_frame = cpl_frameset_find_const(frameset,
602 CR2RES_PHOTO_FLUX_PROCATG) ;
603 master_flat_frame = cpl_frameset_find_const(frameset,
604 CR2RES_CAL_FLAT_MASTER_PROCATG) ;
608 rawframes = cr2res_obs_nodding_find_RAW(frameset, &type) ;
609 if (rawframes == NULL) {
610 cpl_msg_error(__func__,
"Could not find RAW frames") ;
618 if ((labels = cpl_frameset_labelise(rawframes,
619 cr2res_obs_nodding_astrometry_compare, &nlabels)) == NULL) {
620 cpl_msg_error(__func__,
"Cannot label input frames") ;
621 cpl_frameset_delete(rawframes) ;
622 if (raw_flat_frames != NULL) cpl_frameset_delete(raw_flat_frames) ;
623 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
628 if (type != 3 && nlabels != 1) {
629 cpl_msg_error(__func__,
"Expect only one DROT POSANG value - abort") ;
630 cpl_frameset_delete(rawframes) ;
631 if (raw_flat_frames != NULL) cpl_frameset_delete(raw_flat_frames) ;
633 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
638 for (l = 0; l < (int)nlabels; l++) {
640 cpl_frameset *raw_one_angle;
641 cpl_propertylist *plist;
643 raw_one_angle = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
646 plist = cpl_propertylist_load(cpl_frame_get_filename(
647 cpl_frameset_get_position(raw_one_angle, 0)), 0) ;
649 cpl_propertylist_delete(plist) ;
651 cpl_msg_info(__func__,
"Process Angle %g", drot_posang) ;
652 cpl_msg_indent_more() ;
655 for (det_nr = 1; det_nr <= CR2RES_NB_DETECTORS; det_nr++) {
657 combineda[det_nr - 1] = NULL;
658 extracta[det_nr - 1] = NULL;
659 slitfunca[det_nr - 1] = NULL;
660 modela[det_nr - 1] = NULL;
661 twa[det_nr - 1] = NULL;
662 combinedb[det_nr - 1] = NULL;
663 extractb[det_nr - 1] = NULL;
664 slitfuncb[det_nr - 1] = NULL;
665 modelb[det_nr - 1] = NULL;
666 twb[det_nr - 1] = NULL;
667 extractc[det_nr - 1] = NULL;
668 ext_plist[det_nr - 1] = NULL;
669 ext_plist_photom[det_nr - 1] = NULL;
670 throughput[det_nr - 1] = NULL;
673 if (reduce_det != 0 && det_nr != reduce_det)
676 cpl_msg_info(__func__,
"Process Detector %d", det_nr);
677 cpl_msg_indent_more();
680 if (cr2res_obs_nodding_reduce(
681 raw_one_angle, trace_wave_frame,
682 detlin_frame, master_dark_frame, master_flat_frame,
683 bpm_frame, blaze_frame, nodding_invert,
684 subtract_nolight_rows, subtract_interorder_column, cosmics,
686 extract_oversample, extract_pclip, extract_swath_width, extract_height,
687 extract_smooth_slit, extract_smooth_spec, extract_niter,
688 extract_kappa, det_nr, disp_det, disp_order_idx, disp_trace,
689 &(combineda[det_nr - 1]), &(extracta[det_nr - 1]),
690 &(slitfunca[det_nr - 1]), &(modela[det_nr - 1]),
691 &(twa[det_nr - 1]), &(combinedb[det_nr - 1]),
692 &(extractb[det_nr - 1]), &(slitfuncb[det_nr - 1]),
693 &(modelb[det_nr - 1]), &(twb[det_nr - 1]),
694 &(extractc[det_nr - 1]), &(ext_plist[det_nr - 1])) == -1) {
695 cpl_msg_warning(__func__,
"Failed to reduce detector %d",
699 else if (type == 2) {
702 "Sensitivity / Conversion / Throughput computation");
703 cpl_msg_indent_more();
707 gain = CR2RES_GAIN_CHIP1;
709 gain = CR2RES_GAIN_CHIP2;
711 gain = CR2RES_GAIN_CHIP3;
714 plist = cpl_propertylist_load(
715 cpl_frame_get_filename(
716 cpl_frameset_get_position_const(raw_one_angle, 0)),
723 cpl_propertylist_delete(plist);
724 if (cpl_error_get_code()) {
725 cpl_msg_indent_less();
727 cpl_msg_warning(__func__,
"Missing Header Informations");
732 extracta[det_nr - 1],
733 cpl_frame_get_filename(photo_flux_frame),
734 cur_setting, ra, dec, gain, dit, disp_det == det_nr,
735 disp_order_idx, disp_trace,
736 &(throughput[det_nr - 1]),
737 &(ext_plist_photom[det_nr - 1])) == -1) {
738 cpl_msg_warning(__func__,
739 "Failed to reduce detector %d", det_nr);
743 cpl_free(cur_setting);
744 cpl_msg_indent_less();
746 cpl_msg_indent_less();
750 if (nlabels == 1) product_name_addon = cpl_sprintf(
".fits") ;
751 else product_name_addon = cpl_sprintf(
"_%g.fits",
755 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
756 if (ext_plist_photom[det_nr-1] != NULL &&
757 ext_plist[det_nr-1] != NULL) {
758 cpl_propertylist_append(ext_plist[det_nr-1],
759 ext_plist_photom[det_nr-1]) ;
764 qc_main = cpl_propertylist_new();
765 cpl_propertylist_append_double(qc_main,
766 CR2RES_HEADER_DRS_TMID,
771 if (eop_table != NULL) {
772 plist=cpl_propertylist_load(cpl_frame_get_filename(
773 cpl_frameset_get_position_const(raw_one_angle, 0)), 0) ;
775 ra = cpl_propertylist_get_double(plist,
"RA") ;
776 dec = cpl_propertylist_get_double(plist,
"DEC") ;
777 mjd_obs = cpl_propertylist_get_double(plist,
"MJD-OBS") ;
778 geolon = cpl_propertylist_get_double(plist,
"ESO TEL GEOLON") ;
779 geolat = cpl_propertylist_get_double(plist,
"ESO TEL GEOLAT") ;
780 geoelev = cpl_propertylist_get_double(plist,
"ESO TEL GEOELEV") ;
782 cpl_propertylist_delete(plist) ;
785 if (!cpl_error_get_code()) {
788 (mjd_cen-mjd_obs)*24*3600, geolon, geolat, geoelev,
789 0.0, 0.0, 0.0, 0.0, &barycorr);
791 cpl_msg_info(__func__,
"Barycentric correction: %g m/s",
794 cpl_msg_info(__func__,
"Cannot derive Barycentric correction");
797 cpl_table_delete(eop_table) ;
802 if(error_method == CR2RES_EXTRACT_ERROR_HORNE){
803 cpl_propertylist_append_string(qc_main, CR2RES_HEADER_DRS_ERRMETHOD,
807 cpl_propertylist_append_string(qc_main, CR2RES_HEADER_DRS_ERRMETHOD,
811 cpl_propertylist_append_int(qc_main,
812 CR2RES_HEADER_QC_NUMSAT,
817 if (trace_wave_frame != NULL)
818 cpl_frameset_insert(raw_one_angle,
819 cpl_frame_duplicate(trace_wave_frame)) ;
820 if (detlin_frame != NULL)
821 cpl_frameset_insert(raw_one_angle,
822 cpl_frame_duplicate(detlin_frame)) ;
823 if (master_dark_frame != NULL)
824 cpl_frameset_insert(raw_one_angle,
825 cpl_frame_duplicate(master_dark_frame)) ;
826 if (master_flat_frame!= NULL)
827 cpl_frameset_insert(raw_one_angle,
828 cpl_frame_duplicate(master_flat_frame)) ;
829 if (bpm_frame!= NULL)
830 cpl_frameset_insert(raw_one_angle,
831 cpl_frame_duplicate(bpm_frame)) ;
832 if (blaze_frame!= NULL)
833 cpl_frameset_insert(raw_one_angle,
834 cpl_frame_duplicate(blaze_frame)) ;
835 if (photo_flux_frame!= NULL)
836 cpl_frameset_insert(raw_one_angle,
837 cpl_frame_duplicate(photo_flux_frame)) ;
839 out_file = cpl_sprintf(
"%s_combinedA%s", RECIPE_STRING,
840 product_name_addon) ;
842 combineda, qc_main, ext_plist,
843 CR2RES_OBS_NODDING_COMBINEDA_PROCATG, RECIPE_STRING) ;
846 char *qc_perdet_keywords[] = { CR2RES_HEADER_QC_SIGNAL,
847 CR2RES_HEADER_QC_STANDARD_FLUX,
848 CR2RES_HEADER_QC_SLITFWHM_MED };
850 char *qc_pertrace_keywords[] = { CR2RES_HEADER_QC_SNR_BASE,
851 CR2RES_HEADER_QC_SLITFWHM_ORDER_BASE };
853 int qc_perdet_size =
sizeof(qc_perdet_keywords) /
sizeof(
char *);
854 int qc_pertrace_size =
sizeof(qc_pertrace_keywords) /
sizeof(
char *);
856 int qc_sizes_ext[] = {CR2RES_NB_DETECTORS};
857 cpl_propertylist** qc_plists_ext[] = {ext_plist} ;
858 char * qc_res_avg, * qc_res_rmsd, * qc_ref;
862 for (qc_i=0; qc_i<qc_perdet_size ; qc_i++) {
864 qc_res_avg = cpl_sprintf(
"%s %s",
865 qc_perdet_keywords[qc_i],
"AVG");
866 qc_res_rmsd = cpl_sprintf(
"%s %s",
867 qc_perdet_keywords[qc_i],
"RMS");
869 cr2res_qc_calculate_mean_and_rmsd(qc_plists_ext, 1, qc_sizes_ext,
870 qc_perdet_keywords[qc_i], qc_main,
871 qc_res_avg, qc_res_rmsd);
873 cpl_free(qc_res_avg);
874 cpl_free(qc_res_rmsd);
878 int min_order = INT_MAX;
879 int max_order = INT_MIN;
880 int current_min, current_max;
882 for (qc_i = 0; qc_i < CR2RES_NB_DETECTORS; qc_i++) {
883 if (twa[qc_i] == NULL) {
887 cpl_table_get_column_min(twa[qc_i],
"Order");
888 if (cpl_error_get_code() != CPL_ERROR_NONE) {
891 if (current_min < min_order) {
892 min_order = current_min;
896 cpl_table_get_column_max(twa[qc_i],
"Order");
897 if (cpl_error_get_code() != CPL_ERROR_NONE) {
900 if (current_max > max_order) {
901 max_order = current_max;
905 for (qc_i = 0; qc_i < qc_pertrace_size; qc_i++) {
906 for (
int order_id = min_order; order_id <= max_order; order_id++) {
908 qc_ref = cpl_sprintf(
"%s%d", qc_pertrace_keywords[qc_i],
911 cpl_sprintf(
"%s%d %s", qc_pertrace_keywords[qc_i],
914 cpl_sprintf(
"%s%d %s", qc_pertrace_keywords[qc_i],
917 cr2res_qc_calculate_mean_and_rmsd(qc_plists_ext, 1, qc_sizes_ext,
918 qc_ref, qc_main, qc_res_avg,
922 cpl_free(qc_res_avg);
923 cpl_free(qc_res_rmsd);
927 out_file = cpl_sprintf(
"%s_extractedA%s", RECIPE_STRING,
928 product_name_addon) ;
930 extracta, qc_main, ext_plist,
931 CR2RES_OBS_NODDING_EXTRACTA_PROCATG, RECIPE_STRING);
934 extracta, qc_main, ext_plist,
935 CR2RES_OBS_NODDING_EXTRACTA_IDP_PROCATG,
964 out_file = cpl_sprintf(
"%s_slitfuncA%s", RECIPE_STRING,
965 product_name_addon) ;
967 slitfunca, qc_main, ext_plist,
968 CR2RES_OBS_NODDING_SLITFUNCA_PROCATG, RECIPE_STRING) ;
971 out_file = cpl_sprintf(
"%s_modelA%s", RECIPE_STRING,
972 product_name_addon) ;
974 modela, qc_main, ext_plist,
975 CR2RES_OBS_NODDING_SLITMODELA_PROCATG, RECIPE_STRING) ;
978 out_file = cpl_sprintf(
"%s_trace_wave_A%s", RECIPE_STRING,
979 product_name_addon) ;
981 twa, qc_main, ext_plist, CR2RES_OBS_NODDING_TWA_PROCATG,
985 out_file = cpl_sprintf(
"%s_combinedB%s", RECIPE_STRING,
986 product_name_addon) ;
988 combinedb, qc_main, ext_plist,
989 CR2RES_OBS_NODDING_COMBINEDB_PROCATG, RECIPE_STRING) ;
992 out_file = cpl_sprintf(
"%s_extractedB%s", RECIPE_STRING,
993 product_name_addon) ;
995 extractb, qc_main, ext_plist,
996 CR2RES_OBS_NODDING_EXTRACTB_PROCATG, RECIPE_STRING);
999 extractb, qc_main, ext_plist,
1000 CR2RES_OBS_NODDING_EXTRACTB_IDP_PROCATG,
1005 out_file = cpl_sprintf(
"%s_slitfuncB%s", RECIPE_STRING,
1006 product_name_addon) ;
1008 slitfuncb, qc_main, ext_plist,
1009 CR2RES_OBS_NODDING_SLITFUNCB_PROCATG, RECIPE_STRING) ;
1012 out_file = cpl_sprintf(
"%s_modelB%s", RECIPE_STRING,
1013 product_name_addon) ;
1015 modelb, qc_main, ext_plist,
1016 CR2RES_OBS_NODDING_SLITMODELB_PROCATG, RECIPE_STRING) ;
1019 out_file = cpl_sprintf(
"%s_trace_wave_B%s", RECIPE_STRING,
1020 product_name_addon) ;
1022 twb, qc_main, ext_plist, CR2RES_OBS_NODDING_TWB_PROCATG,
1026 out_file = cpl_sprintf(
"%s_extracted_combined%s", RECIPE_STRING,
1027 product_name_addon) ;
1029 extractc, qc_main, ext_plist,
1030 CR2RES_OBS_NODDING_EXTRACTC_PROCATG, RECIPE_STRING);
1033 extractc, qc_main, ext_plist,
1034 CR2RES_OBS_NODDING_EXTRACTC_IDP_PROCATG,
1041 qc_res_avg = cpl_sprintf(
"%s %s", CR2RES_HEADER_QC_THROUGHPUT,
"AVG");
1042 qc_res_rmsd = cpl_sprintf(
"%s %s", CR2RES_HEADER_QC_THROUGHPUT,
"RMS");
1044 cr2res_qc_calculate_mean_and_rmsd(qc_plists_ext, 1, qc_sizes_ext,
1045 CR2RES_HEADER_QC_THROUGHPUT, qc_main,
1046 qc_res_avg, qc_res_rmsd);
1048 cpl_free(qc_res_avg);
1049 cpl_free(qc_res_rmsd);
1051 out_file = cpl_sprintf(
"%s_throughput%s", RECIPE_STRING,
1052 product_name_addon) ;
1054 parlist, throughput, qc_main, ext_plist,
1055 CR2RES_OBS_NODDING_THROUGHPUT_PROCATG, RECIPE_STRING) ;
1058 cpl_free(product_name_addon) ;
1061 cpl_propertylist_delete(qc_main) ;
1062 for (det_nr=1 ; det_nr<=CR2RES_NB_DETECTORS ; det_nr++) {
1063 if (combineda[det_nr-1] != NULL)
1065 if (extracta[det_nr-1] != NULL)
1066 cpl_table_delete(extracta[det_nr-1]) ;
1067 if (slitfunca[det_nr-1] != NULL)
1068 cpl_table_delete(slitfunca[det_nr-1]) ;
1069 if (modela[det_nr-1] != NULL)
1071 if (twa[det_nr-1] != NULL)
1072 cpl_table_delete(twa[det_nr-1]) ;
1073 if (combinedb[det_nr-1] != NULL)
1075 if (extractb[det_nr-1] != NULL)
1076 cpl_table_delete(extractb[det_nr-1]) ;
1077 if (slitfuncb[det_nr-1] != NULL)
1078 cpl_table_delete(slitfuncb[det_nr-1]) ;
1079 if (modelb[det_nr-1] != NULL)
1081 if (twb[det_nr-1] != NULL)
1082 cpl_table_delete(twb[det_nr-1]) ;
1083 if (extractc[det_nr-1] != NULL)
1084 cpl_table_delete(extractc[det_nr-1]) ;
1085 if (throughput[det_nr-1] != NULL)
1086 cpl_table_delete(throughput[det_nr-1]) ;
1087 if (ext_plist[det_nr-1] != NULL)
1088 cpl_propertylist_delete(ext_plist[det_nr-1]) ;
1089 if (ext_plist_photom[det_nr-1] != NULL)
1090 cpl_propertylist_delete(ext_plist_photom[det_nr-1]) ;
1092 cpl_frameset_delete(raw_one_angle) ;
1093 cpl_msg_indent_less() ;
1096 cpl_frameset_delete(rawframes) ;
1097 if (raw_flat_frames != NULL) cpl_frameset_delete(raw_flat_frames) ;
1099 return (
int)cpl_error_get_code();
1142static int cr2res_obs_nodding_reduce(
1143 const cpl_frameset * rawframes,
1144 const cpl_frame * trace_wave_frame,
1145 const cpl_frame * detlin_frame,
1146 const cpl_frame * master_dark_frame,
1147 const cpl_frame * master_flat_frame,
1148 const cpl_frame * bpm_frame,
1149 const cpl_frame * blaze_frame,
1151 int subtract_nolight_rows,
1152 int subtract_interorder_column,
1155 int extract_oversample,
1156 double extract_pclip,
1157 int extract_swath_width,
1159 double extract_smooth_slit,
1160 double extract_smooth_spec,
1162 double extract_kappa,
1167 hdrl_image ** combineda,
1168 cpl_table ** extracta,
1169 cpl_table ** slitfunca,
1170 hdrl_image ** modela,
1172 hdrl_image ** combinedb,
1173 cpl_table ** extractb,
1174 cpl_table ** slitfuncb,
1175 hdrl_image ** modelb,
1177 cpl_table ** extractc,
1178 cpl_propertylist ** ext_plist)
1180 hdrl_imagelist * in ;
1181 hdrl_imagelist * in_calib ;
1182 hdrl_imagelist * in_a ;
1183 hdrl_imagelist * in_b ;
1184 hdrl_imagelist * diff_a ;
1185 hdrl_imagelist * diff_b ;
1186 hdrl_image * collapsed_a ;
1187 hdrl_image * collapsed_b ;
1188 cpl_image * contrib_a ;
1189 cpl_image * contrib_b ;
1190 cr2res_nodding_pos * nod_positions ;
1192 cpl_vector * ndits=NULL ;
1193 cpl_table * trace_wave ;
1195 cpl_table * trace_wave_a ;
1196 cpl_table * trace_wave_b ;
1197 cpl_table * blaze_table ;
1198 cpl_array * slit_frac_a ;
1199 cpl_array * slit_frac_b ;
1200 cpl_table * extracted_a ;
1201 cpl_table * extracted_b ;
1202 cpl_table * extracted_combined ;
1203 cpl_table * slit_func_a ;
1204 cpl_table * slit_func_b ;
1205 hdrl_image * model_master_a ;
1206 hdrl_image * model_master_b ;
1207 cpl_propertylist * plist ;
1208 cpl_size nframes, i ;
1210 const char * first_fname ;
1211 double slit_length, extr_width_frac, slit_frac_a_bot,
1212 slit_frac_a_mid, slit_frac_a_top, slit_frac_b_bot,
1213 slit_frac_b_mid, slit_frac_b_top, nod_throw,
1214 gain, error_factor ;
1215 double qc_signal_a, qc_signal_b, qc_fwhm_a,
1216 qc_fwhm_b, qc_standard_flux_a,
1217 qc_standard_flux_b, qc_fwhm_med, blaze_norm ;
1218 cpl_array * fwhm_a_array ;
1219 cpl_array * fwhm_b_array ;
1220 char * cur_setting ;
1221 int * order_idx_values ;
1222 int * order_idx_values_der ;
1224 double * qc_der_snrs ;
1225 int nb_order_idx_values,
1226 nb_order_idx_values_der,
1227 order_zp, order_idx, order_idxp ;
1230 if (combineda == NULL || combinedb == NULL ||
1231 twa == NULL || twb == NULL ||
1232 slitfunca == NULL || slitfuncb == NULL ||
1233 modela == NULL || modelb == NULL ||
1234 extracta == NULL || extractb == NULL || extractc == NULL ||
1235 ext_plist == NULL || rawframes == NULL || trace_wave_frame == NULL)
1239 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
1240 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
1241 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
1243 cpl_msg_error(__func__,
"Failed to get the Gain value") ;
1248 if (cr2res_obs_nodding_check_inputs_validity(rawframes) != 1) {
1249 cpl_msg_error(__func__,
"Invalid Inputs") ;
1254 nframes = cpl_frameset_get_size(rawframes) ;
1255 first_fname = cpl_frame_get_filename(
1256 cpl_frameset_get_position_const(rawframes, 0)) ;
1259 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(trace_wave_frame),
1261 cpl_msg_error(__func__,
"Cannot read the ORDER_ZP from the input TW") ;
1264 order_zp = cr2res_pfits_get_order_zp(plist) ;
1265 cpl_propertylist_delete(plist) ;
1266 if (cpl_error_get_code()) {
1267 cpl_msg_error(__func__,
"Missing ORDER_ZP in the header - Skip") ;
1274 cpl_msg_info(__func__,
"Get the Nodding positions") ;
1275 cpl_msg_indent_more() ;
1277 for (i=0 ; i<nframes ; i++) {
1278 cpl_msg_info(__func__,
"Frame %s - Nodding %c",
1279 cpl_frame_get_filename(
1280 cpl_frameset_get_position_const(rawframes, i)),
1283 cpl_msg_indent_less() ;
1289 if (cpl_msg_get_level() == CPL_MSG_DEBUG && dits != NULL)
1290 cpl_vector_dump(dits, stdout) ;
1294 if (cpl_msg_get_level() == CPL_MSG_DEBUG && ndits != NULL)
1295 cpl_vector_dump(ndits, stdout) ;
1298 cpl_msg_info(__func__,
"Load the image list") ;
1300 reduce_det)) == NULL) {
1301 cpl_msg_error(__func__,
"Cannot load images") ;
1302 cpl_free(nod_positions) ;
1303 if (dits != NULL) cpl_vector_delete(dits) ;
1307 cpl_msg_error(__func__,
"Inconsistent number of loaded images") ;
1308 cpl_free(nod_positions) ;
1309 if (dits != NULL) cpl_vector_delete(dits) ;
1315 cpl_msg_info(__func__,
"Apply the Calibrations") ;
1316 cpl_msg_indent_more() ;
1318 subtract_nolight_rows, subtract_interorder_column, cosmics,
1319 master_flat_frame, master_dark_frame, bpm_frame, detlin_frame, dits,
1321 cpl_msg_error(__func__,
"Failed to apply the calibrations") ;
1322 cpl_msg_indent_less() ;
1323 cpl_free(nod_positions) ;
1324 if (dits != NULL) cpl_vector_delete(dits) ;
1325 if (ndits != NULL) cpl_vector_delete(ndits) ;
1330 if (dits != NULL) cpl_vector_delete(dits) ;
1331 cpl_msg_indent_less() ;
1334 cpl_msg_info(__func__,
"Split the images in A and B lists") ;
1335 cpl_msg_indent_more() ;
1338 cpl_msg_error(__func__,
"Failed to split the nodding positions") ;
1339 cpl_msg_indent_less() ;
1340 cpl_free(nod_positions) ;
1342 cpl_vector_delete(ndits) ;
1347 if (error_method == CR2RES_EXTRACT_ERROR_HORNE) {
1348 error_factor = -1.0;
1351 error_factor = gain * cpl_vector_get(ndits, 0) *
1355 for (i=0; i<cpl_vector_get_size(ndits); i++){
1356 if (cpl_vector_get(ndits,i) != cpl_vector_get(ndits, 0))
1357 cpl_msg_warning(__func__,
"Raw frames have different NDIT! "
1358 "Error spectrum will likely be scaled incorrectly.");
1360 cpl_vector_delete(ndits) ;
1361 cpl_free(nod_positions) ;
1363 cpl_msg_indent_less() ;
1368 cpl_msg_error(__func__,
"Inconsistent A / B number of images") ;
1375 cpl_msg_info(__func__,
"Compute difference image lists A-B and B-A") ;
1384 cpl_msg_info(__func__,
"Collapse image lists A-B and B-A") ;
1385 cpl_msg_indent_more() ;
1388 cpl_msg_error(__func__,
"Failed to Collapse A-B") ;
1391 cpl_msg_indent_less() ;
1394 cpl_image_delete(contrib_a) ;
1398 cpl_msg_error(__func__,
"Failed to Collapse B-A") ;
1401 cpl_msg_indent_less() ;
1404 cpl_image_delete(contrib_b) ;
1406 cpl_msg_indent_less() ;
1409 cpl_msg_info(__func__,
"Load the TRACE WAVE") ;
1411 trace_wave_frame), reduce_det)) == NULL) {
1412 cpl_msg_error(__func__,
"Failed to Load the traces file") ;
1419 cpl_msg_warning(__func__,
"TRACE ADJUST NOT YET IMPLEMENTED") ;
1434 cpl_msg_info(__func__,
"Compute the slit fractions for A and B positions");
1435 cpl_msg_indent_more() ;
1444 if ((plist = cpl_propertylist_load(first_fname, 0)) == NULL) {
1445 cpl_msg_error(__func__,
"Cannot read the NODTHROW in the input files") ;
1446 cpl_msg_indent_less() ;
1449 cpl_table_delete(trace_wave) ;
1453 cpl_propertylist_delete(plist) ;
1454 if (nod_throw < slit_length / 2.0) {
1455 extr_width_frac = nod_throw/slit_length ;
1456 if (nodding_invert == 1) {
1457 slit_frac_a_bot = 0.5 ;
1458 slit_frac_a_mid = slit_frac_a_bot + extr_width_frac/2.0 ;
1459 slit_frac_a_top = slit_frac_a_bot + extr_width_frac ;
1460 slit_frac_b_top = 0.5 ;
1461 slit_frac_b_mid = slit_frac_b_top - extr_width_frac/2.0 ;
1462 slit_frac_b_bot = slit_frac_b_top - extr_width_frac ;
1464 slit_frac_a_top = 0.5 ;
1465 slit_frac_a_mid = slit_frac_a_top - extr_width_frac/2.0 ;
1466 slit_frac_a_bot = slit_frac_a_top - extr_width_frac ;
1467 slit_frac_b_bot = 0.5 ;
1468 slit_frac_b_mid = slit_frac_b_bot + extr_width_frac/2.0 ;
1469 slit_frac_b_top = slit_frac_b_bot + extr_width_frac ;
1471 }
else if (nod_throw <= slit_length) {
1472 extr_width_frac = (slit_length - nod_throw)/slit_length ;
1473 if (nodding_invert == 1) {
1474 slit_frac_a_top = 1.0 ;
1475 slit_frac_a_mid = slit_frac_a_top - extr_width_frac/2.0 ;
1476 slit_frac_a_bot = slit_frac_a_top - extr_width_frac ;
1477 slit_frac_b_bot = 0.0 ;
1478 slit_frac_b_mid = slit_frac_b_bot + extr_width_frac/2.0 ;
1479 slit_frac_b_top = slit_frac_b_bot + extr_width_frac ;
1481 slit_frac_a_bot = 0.0 ;
1482 slit_frac_a_mid = slit_frac_a_bot + extr_width_frac/2.0 ;
1483 slit_frac_a_top = slit_frac_a_bot + extr_width_frac ;
1484 slit_frac_b_top = 1.0 ;
1485 slit_frac_b_mid = slit_frac_b_top - extr_width_frac/2.0 ;
1486 slit_frac_b_bot = slit_frac_b_top - extr_width_frac ;
1489 cpl_msg_error(__func__,
"NODTHROW > slit length (%g>%g)- abort",
1490 nod_throw, slit_length) ;
1491 cpl_msg_indent_less() ;
1494 cpl_table_delete(trace_wave) ;
1497 cpl_msg_info(__func__,
"Nod Throw : %g arcsecs", nod_throw) ;
1498 cpl_msg_info(__func__,
"Nodding A extraction: Slit fraction %g - %g",
1499 slit_frac_a_bot, slit_frac_a_top) ;
1500 cpl_msg_info(__func__,
"Nodding B extraction: Slit fraction %g - %g",
1501 slit_frac_b_bot, slit_frac_b_top) ;
1503 slit_frac_a = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1504 cpl_array_set(slit_frac_a, 0, slit_frac_a_bot) ;
1505 cpl_array_set(slit_frac_a, 1, slit_frac_a_mid) ;
1506 cpl_array_set(slit_frac_a, 2, slit_frac_a_top) ;
1508 slit_frac_b = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1509 cpl_array_set(slit_frac_b, 0, slit_frac_b_bot) ;
1510 cpl_array_set(slit_frac_b, 1, slit_frac_b_mid) ;
1511 cpl_array_set(slit_frac_b, 2, slit_frac_b_top) ;
1512 cpl_msg_indent_less() ;
1515 cpl_msg_info(__func__,
"Recompute the traces for the A slit fraction") ;
1517 slit_frac_a)) == NULL) {
1518 cpl_msg_error(__func__,
1519 "Failed to compute the traces for extraction of A") ;
1522 cpl_table_delete(trace_wave) ;
1523 cpl_array_delete(slit_frac_a) ;
1524 cpl_array_delete(slit_frac_b) ;
1527 cpl_array_delete(slit_frac_a) ;
1529 cpl_msg_info(__func__,
"Recompute the traces for the B slit fraction") ;
1531 slit_frac_b)) == NULL) {
1532 cpl_msg_error(__func__,
1533 "Failed to compute the traces for extraction of B") ;
1536 cpl_table_delete(trace_wave) ;
1537 cpl_table_delete(trace_wave_a) ;
1538 cpl_array_delete(slit_frac_b) ;
1541 cpl_array_delete(slit_frac_b) ;
1544 blaze_table = NULL ;
1546 if (blaze_frame != NULL) {
1547 cpl_msg_info(__func__,
"Load the BLAZE") ;
1549 blaze_frame), reduce_det)) == NULL) {
1550 cpl_msg_error(__func__,
"Failed to Load the Blaze file") ;
1553 cpl_table_delete(trace_wave) ;
1554 cpl_table_delete(trace_wave_a) ;
1555 cpl_table_delete(trace_wave_b) ;
1558 cpl_propertylist * blaze_plist ;
1559 blaze_plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(
1560 blaze_frame),0,CR2RES_HEADER_QC_BLAZE_NORM,0);
1561 if(cpl_propertylist_get_size(blaze_plist)>0){
1562 blaze_norm = cpl_propertylist_get_double(blaze_plist, CR2RES_HEADER_QC_BLAZE_NORM);
1566 cpl_msg_warning(__func__,
"QC BLAZE NORM value not found, reverting to per trace normalization") ;
1568 if(blaze_plist!=NULL){
1569 cpl_propertylist_delete(blaze_plist);
1574 cpl_msg_info(__func__,
"A position Spectra Extraction") ;
1575 cpl_msg_indent_more() ;
1577 -1, CR2RES_EXTR_OPT_CURV, extract_height, extract_swath_width,
1578 extract_oversample, extract_pclip, extract_smooth_slit, extract_smooth_spec,
1579 extract_niter, extract_kappa, error_factor,
1580 disp_det==reduce_det, disp_order_idx, disp_trace,
1581 &extracted_a, &slit_func_a, &model_master_a) == -1) {
1582 cpl_msg_error(__func__,
"Failed to extract A");
1583 cpl_msg_indent_less() ;
1586 cpl_table_delete(trace_wave_a) ;
1587 cpl_table_delete(trace_wave_b) ;
1588 cpl_table_delete(trace_wave) ;
1591 cpl_msg_indent_less() ;
1593 cpl_msg_info(__func__,
"B position Spectra Extraction") ;
1594 cpl_msg_indent_more() ;
1596 -1, CR2RES_EXTR_OPT_CURV, extract_height, extract_swath_width,
1597 extract_oversample, extract_pclip, extract_smooth_slit, extract_smooth_spec,
1598 extract_niter, extract_kappa, error_factor,
1599 disp_det==reduce_det, disp_order_idx, disp_trace,
1600 &extracted_b, &slit_func_b, &model_master_b) == -1) {
1601 cpl_msg_error(__func__,
"Failed to extract B");
1602 cpl_msg_indent_less() ;
1603 cpl_table_delete(extracted_a) ;
1604 cpl_table_delete(slit_func_a) ;
1608 cpl_table_delete(trace_wave_a) ;
1609 cpl_table_delete(trace_wave_b) ;
1610 cpl_table_delete(trace_wave) ;
1613 cpl_msg_indent_less() ;
1615 if (blaze_table != NULL) cpl_table_delete(blaze_table) ;
1618 cpl_msg_info(__func__,
"A and B spectra combination") ;
1619 cpl_msg_indent_more() ;
1621 cpl_msg_indent_less() ;
1624 plist = cpl_propertylist_load(first_fname, 0) ;
1627 cpl_propertylist_delete(plist) ;
1630 plist = cpl_propertylist_load(first_fname,
1634 cpl_msg_info(__func__,
"QC parameters computation") ;
1637 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SIGNAL,
1638 (qc_signal_a+qc_signal_b)/2.0) ;
1641 qc_standard_flux_a =
1643 qc_standard_flux_b =
1645 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_STANDARD_FLUX,
1646 (qc_standard_flux_a+qc_standard_flux_b)/2.0) ;
1647 cpl_free(cur_setting) ;
1650 qc_snrs =
cr2res_qc_snr(trace_wave_a, extracted_a, &order_idx_values,
1651 &nb_order_idx_values) ;
1652 qc_der_snrs =
cr2res_qc_der_snr(trace_wave_a, extracted_a, &order_idx_values_der,
1653 &nb_order_idx_values_der) ;
1654 for (i=0 ; i<nb_order_idx_values ; i++) {
1655 order_idx = order_idx_values[i] ;
1657 key_name = cpl_sprintf(CR2RES_HEADER_QC_SNR, order_idxp) ;
1658 cpl_propertylist_append_double(plist, key_name, qc_snrs[i]) ;
1659 cpl_free(key_name) ;
1660 key_name = cpl_sprintf(CR2RES_HEADER_QC_DER_SNR, order_idxp) ;
1661 cpl_propertylist_append_double(plist, key_name, qc_der_snrs[i]) ;
1662 cpl_free(key_name) ;
1664 cpl_free(order_idx_values) ;
1665 cpl_free(order_idx_values_der) ;
1667 cpl_free(qc_der_snrs) ;
1671 &nb_order_idx_values);
1674 fwhm_a_array = cpl_array_new(nb_order_idx_values, CPL_TYPE_DOUBLE);
1675 fwhm_b_array = cpl_array_new(nb_order_idx_values, CPL_TYPE_DOUBLE);
1676 for (i=0 ; i<nb_order_idx_values ; i++) {
1677 order_idx = order_idx_values[i] ;
1680 extract_oversample);
1682 extract_oversample);
1684 key_name = cpl_sprintf(CR2RES_HEADER_QC_SLITFWHM_ORDER, order_idxp) ;
1685 cpl_propertylist_append_double(plist, key_name,
1686 (qc_fwhm_a+qc_fwhm_b)/2.0) ;
1687 cpl_free(key_name) ;
1688 cpl_array_set(fwhm_a_array, i, qc_fwhm_a) ;
1689 cpl_array_set(fwhm_b_array, i, qc_fwhm_b) ;
1691 qc_fwhm_a = cpl_array_get_median(fwhm_a_array);
1692 qc_fwhm_b = cpl_array_get_median(fwhm_b_array);
1693 qc_fwhm_med = (qc_fwhm_a+qc_fwhm_b)/2.0 ;
1694 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SLITFWHM_MED,
1696 if (qc_fwhm_med < 3.5) {
1697 cpl_msg_warning(__func__,
"Median FWHM of the PSF along the slit "
1698 "is %gpix, i.e. below the slit width. This means the slit "
1699 "is likely not evenly filled with light "
1700 "in the spectral direction. This can result in a "
1701 "wavelength offset between A and B nodding positions, and with "
1702 "respect to calibrations."
1705 cpl_array_delete(fwhm_a_array) ;
1706 cpl_array_delete(fwhm_b_array) ;
1711 for (i = 0; i < nb_order_idx_values; i++) {
1713 order_idx = order_idx_values[i] ;
1717 key_name = cpl_sprintf(CR2RES_HEADER_QC_REAL_ORDER, order_idxp) ;
1718 cpl_propertylist_append_int(plist, key_name, order_real) ;
1719 cpl_free(key_name) ;
1722 cpl_table_delete(trace_wave) ;
1723 cpl_free(order_idx_values) ;
1726 *combineda = collapsed_a ;
1727 *extracta = extracted_a ;
1728 *slitfunca = slit_func_a ;
1729 *modela = model_master_a ;
1730 *twa = trace_wave_a ;
1732 *combinedb = collapsed_b ;
1733 *extractb = extracted_b ;
1734 *slitfuncb = slit_func_b ;
1735 *modelb = model_master_b ;
1736 *twb = trace_wave_b ;
1738 *extractc = extracted_combined ;
1739 *ext_plist = plist ;
1751static int cr2res_obs_nodding_check_inputs_validity(
1752 const cpl_frameset * rawframes)
1754 cpl_propertylist * plist ;
1755 cr2res_nodding_pos * nod_positions ;
1756 cpl_size nframes, i ;
1761 if (rawframes == NULL)
return -1 ;
1764 nframes = cpl_frameset_get_size(rawframes) ;
1766 cpl_msg_error(__func__,
"Require an even number of raw frames") ;
1773 if (nod_positions == NULL)
return -1 ;
1774 for (i=0 ; i<nframes ; i++) {
1775 if (nod_positions[i] == CR2RES_NODDING_A) nb_a++ ;
1776 if (nod_positions[i] == CR2RES_NODDING_B) nb_b++ ;
1778 cpl_free(nod_positions) ;
1780 if (nb_a == 0 || nb_b == 0 || nb_a != nb_b) {
1781 cpl_msg_error(__func__,
"Require as many A and B positions") ;
1786 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(
1787 cpl_frameset_get_position_const(rawframes, 0)),
1792 cpl_propertylist_delete(plist) ;
1793 for (i = 1; i < nframes; i++) {
1794 double nodthrow_cur;
1795 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(
1796 cpl_frameset_get_position_const(rawframes, i)),
1801 cpl_propertylist_delete(plist) ;
1803 if (fabs(nodthrow_cur-nodthrow) > 1e-3) {
1804 cpl_msg_error(__func__,
1805 "Require constant NOD THROW in the raw frames") ;
1829static cpl_frameset * cr2res_obs_nodding_find_RAW(
1830 const cpl_frameset * in,
1833 cpl_frameset * out ;
1836 if (in == NULL)
return NULL ;
1843 if (type != NULL) *type = 1 ;
1850 if (type != NULL) *type = 2 ;
1855 CR2RES_OBS_ASTROMETRY_JITTER_RAW) ;
1858 if (type != NULL) *type = 3 ;
1863 if (type != NULL) *type = 0 ;
1876static int cr2res_obs_nodding_astrometry_compare(
1877 const cpl_frame * frame1,
1878 const cpl_frame * frame2)
1881 cpl_propertylist * plist1 ;
1882 cpl_propertylist * plist2 ;
1883 double dval1, dval2 ;
1886 if (frame1==NULL || frame2==NULL)
return -1 ;
1889 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1890 cpl_msg_error(__func__,
"getting header from reference frame");
1893 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1894 cpl_msg_error(__func__,
"getting header from reference frame");
1895 cpl_propertylist_delete(plist1) ;
1900 if (cpl_error_get_code()) {
1901 cpl_propertylist_delete(plist1) ;
1902 cpl_propertylist_delete(plist2) ;
1911 if (cpl_error_get_code()) {
1912 cpl_msg_error(__func__,
"Cannot get the angle");
1913 cpl_propertylist_delete(plist1) ;
1914 cpl_propertylist_delete(plist2) ;
1917 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
1919 cpl_propertylist_delete(plist1) ;
1920 cpl_propertylist_delete(plist2) ;
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.
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.
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_save_THROUGHPUT(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 THROUGHPUT 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.
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
double cr2res_pfits_get_dec(const cpl_propertylist *plist)
find out the DEC
double cr2res_pfits_get_drot_posang(const cpl_propertylist *plist)
find out the DROT POSANG value
double cr2res_pfits_get_nodthrow(const cpl_propertylist *plist)
find out the NODTHROW value
double cr2res_pfits_get_ra(const cpl_propertylist *plist)
find out the RA
int cr2res_photom_engine(const cpl_table *extr, const char *std_star_file, const char *setting, double ra, double dec, double gain, double exptime, int display, int display_order, int display_trace, cpl_table **throughput, cpl_propertylist **ext_plist)
Compute the conversion/throughput/sensitivity high level.
int cr2res_qc_numsat(const cpl_frameset *frameset)
Calculate the number of saturated pixels.
double * cr2res_qc_der_snr(const cpl_table *tw, const cpl_table *extracted, int **out_order_idx_values, int *out_nb_order_idx_values)
Computes the DER SNR of several spectra.
double cr2res_qc_obs_nodding_signal(const cpl_table *extracted)
Computes the integrated flux over part of the spectrum.
double cr2res_qc_obs_nodding_standard_flux(const cpl_table *extracted, char *setting)
Computes the standard 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_format_setting(char *setting_id)
Format the setting.
int cr2res_order_idx_to_real(int order_idx, int order_zp)
Convert the order_idx into order_real.
char cr2res_nodding_position_char(cr2res_nodding_pos pos)
Get the nodding position character for display.
int cr2res_combine_nodding_split(const hdrl_imagelist *in, const cr2res_nodding_pos *positions, hdrl_imagelist **pos_a, hdrl_imagelist **pos_b)
Split A/B positions in 2 image lists.
double cr2res_utils_get_center_mjd(const cpl_frameset *frameset)
Calculate the middle of the exposures in the frameset.
cr2res_nodding_pos * cr2res_nodding_read_positions(const cpl_frameset *in)
Get the nodding positions from a frame set.
cpl_table * cr2res_combine_extracted(const cpl_table *extracta, const cpl_table *extractb)
Combine two extracted spectra by resampling one to the other's WL.
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.
cpl_error_code hdrl_imagelist_sub_imagelist(hdrl_imagelist *himlist1, const hdrl_imagelist *himlist2)
Subtract two image lists, the first one is replaced by the result.
hdrl_imagelist * hdrl_imagelist_duplicate(const hdrl_imagelist *himlist)
Duplicate an image list.