CR2RE Pipeline Reference Manual 1.6.11
cr2res_obs_nodding.c
1/*
2 * This file is part of the CR2RES Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include <string.h>
29#include <cpl.h>
30
31#include "cr2res_utils.h"
32#include "cr2res_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"
40#include "cr2res_io.h"
41#include "cr2res_qc.h"
42#include "cr2res_photom.h"
43
44/*-----------------------------------------------------------------------------
45 Define
46 -----------------------------------------------------------------------------*/
47
48#define RECIPE_STRING "cr2res_obs_nodding"
49
50/*-----------------------------------------------------------------------------
51 Plugin registration
52 -----------------------------------------------------------------------------*/
53
54int cpl_plugin_get_info(cpl_pluginlist * list);
55
56/*-----------------------------------------------------------------------------
57 Private function prototypes
58 -----------------------------------------------------------------------------*/
59
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,
65 int * type) ;
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,
76 int nodding_invert,
77 int subtract_nolight_rows,
78 int subtract_interorder_column,
79 int cosmics,
80 int error_method,
81 int extract_oversample,
82 double extract_pclip,
83 int extract_swath_width,
84 int extract_height,
85 double extract_smooth_slit,
86 double extract_smooth_spec,
87 int extract_niter,
88 double extract_kappa,
89 int reduce_det,
90 int disp_det,
91 int disp_order_idx,
92 int disp_trace,
93 hdrl_image ** combineda,
94 cpl_table ** extracta,
95 cpl_table ** slitfunca,
96 hdrl_image ** modela,
97 cpl_table ** twa,
98 hdrl_image ** combinedb,
99 cpl_table ** extractb,
100 cpl_table ** slitfuncb,
101 hdrl_image ** modelb,
102 cpl_table ** twb,
103 cpl_table ** extractc,
104 cpl_propertylist ** ext_plist) ;
105
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 *);
110
111/*-----------------------------------------------------------------------------
112 Static variables
113 -----------------------------------------------------------------------------*/
114
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\
123 \n\
124 Inputs \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\
147 \n\
148 Outputs \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\
171 \n\
172 Algorithm \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\
178 -> model[a|b](d) \n\
179 -> tw[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\
184 Save throughput \n\
185 \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\
192 -> combined[a|b] \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\
205 -> throughput \n\
206 \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\
229";
230
231
232/*-----------------------------------------------------------------------------
233 Function code
234 -----------------------------------------------------------------------------*/
235
236/*----------------------------------------------------------------------------*/
246/*----------------------------------------------------------------------------*/
247int cpl_plugin_get_info(cpl_pluginlist * list)
248{
249 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
250 cpl_plugin * plugin = &recipe->interface;
251
252 if (cpl_plugin_init(plugin,
253 CPL_PLUGIN_API,
254 CR2RES_BINARY_VERSION,
255 CPL_PLUGIN_TYPE_RECIPE,
256 RECIPE_STRING,
257 "Nodding Observation recipe",
258 cr2res_obs_nodding_description,
259 CR2RES_PIPELINE_AUTHORS,
260 PACKAGE_BUGREPORT,
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);
267 return 1;
268 }
269
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);
273 return 1;
274 }
275
276 return 0;
277}
278
279/*----------------------------------------------------------------------------*/
287/*----------------------------------------------------------------------------*/
288static int cr2res_obs_nodding_create(cpl_plugin * plugin)
289{
290 cpl_recipe * recipe ;
291 cpl_parameter * p ;
292
293 /* Check that the plugin is part of a valid recipe */
294 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
295 recipe = (cpl_recipe *)plugin;
296 else
297 return -1;
298
299 /* Create the parameters list in the cpl_recipe object */
300 recipe->parameters = cpl_parameterlist_new();
301
302 /* Fill the parameters list */
303 p = cpl_parameter_new_value(
304 "cr2res.cr2res_obs_nodding.subtract_nolight_rows",
305 CPL_TYPE_BOOL,
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);
311
312 p = cpl_parameter_new_value(
313 "cr2res.cr2res_obs_nodding.subtract_interorder_column",
314 CPL_TYPE_BOOL,
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);
321
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);
328
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);
336
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);
343
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);
350
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);
357
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);
363
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);
369
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);
376
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);
383
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);
390
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);
397
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);
404
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);
411
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);
418
419 return 0;
420}
421
422/*----------------------------------------------------------------------------*/
428/*----------------------------------------------------------------------------*/
429static int cr2res_obs_nodding_exec(cpl_plugin * plugin)
430{
431 cpl_recipe *recipe;
432
433 /* Get the recipe out of the plugin */
434 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
435 recipe = (cpl_recipe *)plugin;
436 else return -1;
437
438 return cr2res_obs_nodding(recipe->frames, recipe->parameters);
439}
440
441/*----------------------------------------------------------------------------*/
447/*----------------------------------------------------------------------------*/
448static int cr2res_obs_nodding_destroy(cpl_plugin * plugin)
449{
450 cpl_recipe *recipe;
451
452 /* Get the recipe out of the plugin */
453 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
454 recipe = (cpl_recipe *)plugin;
455 else return -1 ;
456
457 cpl_parameterlist_delete(recipe->parameters);
458 return 0 ;
459}
460
461/*----------------------------------------------------------------------------*/
468/*----------------------------------------------------------------------------*/
469static int cr2res_obs_nodding(
470 cpl_frameset * frameset,
471 const cpl_parameterlist * parlist)
472{
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,
479 error_method;
480 double extract_smooth_slit, extract_smooth_spec,
481 extract_pclip;
482 double dit, gain;
483 double ra, dec, mjd_obs, mjd_cen, geolon, geolat, geoelev,
484 barycorr;
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 ;
494 cpl_size * labels ;
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] ;
512 char * cur_setting ;
513 char * out_file;
514 cpl_table * eop_table ;
515 int det_nr, type;
516
517 /* Initialise */
518 gain = 0.0 ;
519 barycorr = 0.0;
520
521 /* RETRIEVE INPUT PARAMETERS */
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;
571 else
572 error_method = CR2RES_EXTRACT_ERROR_POISSON;
573
574 /* TODO, make parameters, maybe */
575 int extract_niter = 30;
576 double extract_kappa = 10;
577
578 /* Identify the RAW and CALIB frames in the input frameset */
579 if (cr2res_dfs_set_groups(frameset)) {
580 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
581 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
582 return -1 ;
583 }
584
585 /* Get Calibration frames */
586 trace_wave_frame = cr2res_io_find_TRACE_WAVE(frameset) ;
587 if (trace_wave_frame == NULL) {
588 cpl_msg_error(__func__, "Could not find TRACE_WAVE frame") ;
589 return -1 ;
590 }
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") ;
598 }
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) ;
605 bpm_frame = cr2res_io_find_BPM(frameset) ;
606
607 /* Get the RAW Frames */
608 rawframes = cr2res_obs_nodding_find_RAW(frameset, &type) ;
609 if (rawframes == NULL) {
610 cpl_msg_error(__func__, "Could not find RAW frames") ;
611 return -1 ;
612 }
613
614 /* Get the RAW flat frames */
615 raw_flat_frames = cr2res_extract_frameset(frameset, CR2RES_FLAT_RAW) ;
616
617 /* Label the raw frames with the different angles */
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) ;
624 return -1 ;
625 }
626
627 /* Check the number of angles */
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) ;
632 cpl_free(labels) ;
633 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
634 return -1 ;
635 }
636
637 /* Loop on the settings */
638 for (l = 0; l < (int)nlabels; l++) {
639 double drot_posang;
640 cpl_frameset *raw_one_angle;
641 cpl_propertylist *plist;
642 /* Get the frames for the current angle */
643 raw_one_angle = cpl_frameset_extract(rawframes, labels, (cpl_size)l) ;
644
645 /* Get the current angle */
646 plist = cpl_propertylist_load(cpl_frame_get_filename(
647 cpl_frameset_get_position(raw_one_angle, 0)), 0) ;
648 drot_posang = cr2res_pfits_get_drot_posang(plist) ;
649 cpl_propertylist_delete(plist) ;
650
651 cpl_msg_info(__func__, "Process Angle %g", drot_posang) ;
652 cpl_msg_indent_more() ;
653
654 /* Loop on the detectors */
655 for (det_nr = 1; det_nr <= CR2RES_NB_DETECTORS; det_nr++) {
656 /* Initialise */
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;
671
672 /* Compute only one detector */
673 if (reduce_det != 0 && det_nr != reduce_det)
674 continue;
675
676 cpl_msg_info(__func__, "Process Detector %d", det_nr);
677 cpl_msg_indent_more();
678
679 /* Call the reduction function */
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,
685 error_method,
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",
696 det_nr);
697 cpl_error_reset();
698 }
699 else if (type == 2) {
700 cpl_msg_info(
701 __func__,
702 "Sensitivity / Conversion / Throughput computation");
703 cpl_msg_indent_more();
704
705 /* Define the gain */
706 if (det_nr == 1)
707 gain = CR2RES_GAIN_CHIP1;
708 if (det_nr == 2)
709 gain = CR2RES_GAIN_CHIP2;
710 if (det_nr == 3)
711 gain = CR2RES_GAIN_CHIP3;
712
713 /* Get the RA and DEC observed */
714 plist = cpl_propertylist_load(
715 cpl_frame_get_filename(
716 cpl_frameset_get_position_const(raw_one_angle, 0)),
717 0);
718 ra = cr2res_pfits_get_ra(plist);
719 dec = cr2res_pfits_get_dec(plist);
720 dit = cr2res_pfits_get_dit(plist);
721 cur_setting = cpl_strdup(cr2res_pfits_get_wlen_id(plist));
722 cr2res_format_setting(cur_setting);
723 cpl_propertylist_delete(plist);
724 if (cpl_error_get_code()) {
725 cpl_msg_indent_less();
726 cpl_error_reset();
727 cpl_msg_warning(__func__, "Missing Header Informations");
728 }
729 else {
730 /* Compute the photometry */
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);
740 cpl_error_reset();
741 }
742 }
743 cpl_free(cur_setting);
744 cpl_msg_indent_less();
745 }
746 cpl_msg_indent_less();
747 }
748
749 /* Save Products */
750 if (nlabels == 1) product_name_addon = cpl_sprintf(".fits") ;
751 else product_name_addon = cpl_sprintf("_%g.fits",
752 drot_posang);
753
754 /* Add the photom QC to the std ones */
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]) ;
760 }
761 }
762
763 /* Add ESO.DRS.TMID in the Main Header */
764 qc_main = cpl_propertylist_new();
765 cpl_propertylist_append_double(qc_main,
766 CR2RES_HEADER_DRS_TMID,
767 cr2res_utils_get_center_mjd(raw_one_angle)) ;
768
769 /* Add barycentric correction */
770 eop_table = cr2res_io_get_eop_table() ;
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) ;
774
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") ;
781
782 cpl_propertylist_delete(plist) ;
783
784 barycorr = 0.0 ;
785 if (!cpl_error_get_code()) {
786 mjd_cen = cr2res_utils_get_center_mjd(raw_one_angle) ;
787 hdrl_barycorr_compute(ra, dec, eop_table, mjd_obs,
788 (mjd_cen-mjd_obs)*24*3600, geolon, geolat, geoelev,
789 0.0, 0.0, 0.0, 0.0, &barycorr);
790
791 cpl_msg_info(__func__, "Barycentric correction: %g m/s",
792 barycorr);
793 } else {
794 cpl_msg_info(__func__, "Cannot derive Barycentric correction");
795 cpl_error_reset() ;
796 }
797 cpl_table_delete(eop_table) ;
798
799 }
800
801
802 if(error_method == CR2RES_EXTRACT_ERROR_HORNE){
803 cpl_propertylist_append_string(qc_main, CR2RES_HEADER_DRS_ERRMETHOD,
804 "Horne") ;
805 }
806 else {
807 cpl_propertylist_append_string(qc_main, CR2RES_HEADER_DRS_ERRMETHOD,
808 "Poisson") ;
809 }
810 /* Add QC NUMSAT */
811 cpl_propertylist_append_int(qc_main,
812 CR2RES_HEADER_QC_NUMSAT,
813 cr2res_qc_numsat(raw_one_angle)) ;
814
815
816 /* Save only the used RAW - fill raw_one_angle with CALIBS */
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)) ;
838
839 out_file = cpl_sprintf("%s_combinedA%s", RECIPE_STRING,
840 product_name_addon) ;
841 cr2res_io_save_COMBINED(out_file, frameset, raw_one_angle, parlist,
842 combineda, qc_main, ext_plist,
843 CR2RES_OBS_NODDING_COMBINEDA_PROCATG, RECIPE_STRING) ;
844 cpl_free(out_file);
845
846 char *qc_perdet_keywords[] = { CR2RES_HEADER_QC_SIGNAL,
847 CR2RES_HEADER_QC_STANDARD_FLUX,
848 CR2RES_HEADER_QC_SLITFWHM_MED };
849
850 char *qc_pertrace_keywords[] = { CR2RES_HEADER_QC_SNR_BASE,
851 CR2RES_HEADER_QC_SLITFWHM_ORDER_BASE };
852
853 int qc_perdet_size = sizeof(qc_perdet_keywords) / sizeof(char *);
854 int qc_pertrace_size = sizeof(qc_pertrace_keywords) / sizeof(char *);
855
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;
859
860 int qc_i;
861
862 for (qc_i=0; qc_i<qc_perdet_size ; qc_i++) {
863
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");
868
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);
872
873 cpl_free(qc_res_avg);
874 cpl_free(qc_res_rmsd);
875 }
876
877
878 int min_order = INT_MAX;
879 int max_order = INT_MIN;
880 int current_min, current_max;
881
882 for (qc_i = 0; qc_i < CR2RES_NB_DETECTORS; qc_i++) {
883 if (twa[qc_i] == NULL) {
884 continue;
885 }
886 current_min =
887 cpl_table_get_column_min(twa[qc_i], "Order");
888 if (cpl_error_get_code() != CPL_ERROR_NONE) {
889 continue;
890 }
891 if (current_min < min_order) {
892 min_order = current_min;
893 }
894
895 current_max =
896 cpl_table_get_column_max(twa[qc_i], "Order");
897 if (cpl_error_get_code() != CPL_ERROR_NONE) {
898 continue;
899 }
900 if (current_max > max_order) {
901 max_order = current_max;
902 }
903 }
904
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++) {
907
908 qc_ref = cpl_sprintf("%s%d", qc_pertrace_keywords[qc_i],
909 order_id);
910 qc_res_avg =
911 cpl_sprintf("%s%d %s", qc_pertrace_keywords[qc_i],
912 order_id, "AVG");
913 qc_res_rmsd =
914 cpl_sprintf("%s%d %s", qc_pertrace_keywords[qc_i],
915 order_id, "RMS");
916
917 cr2res_qc_calculate_mean_and_rmsd(qc_plists_ext, 1, qc_sizes_ext,
918 qc_ref, qc_main, qc_res_avg,
919 qc_res_rmsd);
920
921 cpl_free(qc_ref);
922 cpl_free(qc_res_avg);
923 cpl_free(qc_res_rmsd);
924 }
925 }
926
927 out_file = cpl_sprintf("%s_extractedA%s", RECIPE_STRING,
928 product_name_addon) ;
929 cr2res_io_save_EXTRACT_1D(out_file, frameset, raw_one_angle, parlist,
930 extracta, qc_main, ext_plist,
931 CR2RES_OBS_NODDING_EXTRACTA_PROCATG, RECIPE_STRING);
932 if (create_idp) {
933 cr2res_idp_save(out_file, frameset, raw_one_angle, parlist,
934 extracta, qc_main, ext_plist,
935 CR2RES_OBS_NODDING_EXTRACTA_IDP_PROCATG,
936 RECIPE_STRING);
937 }
938 cpl_free(out_file);
939
940 /* for (qc_i=0; qc_i<qc_perdet_size ; qc_i++) {
941
942 qc_res_avg = cpl_sprintf("%s %s",
943 qc_perdet_keywords[qc_i], "AVG");
944 qc_res_rmsd = cpl_sprintf("%s %s",
945 qc_perdet_keywords[qc_i], "RMS");
946
947 cpl_propertylist_erase(qc_main, qc_res_avg);
948 if(cpl_error_get_code() != CPL_ERROR_NONE) {
949 cpl_msg_debug(__func__, "Cannot erase %s", qc_perdet_keywords[qc_i]);
950 cpl_error_reset();
951 }
952
953 cpl_propertylist_erase(qc_main, qc_res_rmsd);
954 if(cpl_error_get_code() != CPL_ERROR_NONE) {
955 cpl_msg_debug(__func__, "Cannot erase %s", qc_perdet_keywords[qc_i]);
956 cpl_error_reset();
957 }
958
959
960 cpl_free(qc_res_avg);
961 cpl_free(qc_res_rmsd);
962 }
963 */
964 out_file = cpl_sprintf("%s_slitfuncA%s", RECIPE_STRING,
965 product_name_addon) ;
966 cr2res_io_save_SLIT_FUNC(out_file, frameset, raw_one_angle, parlist,
967 slitfunca, qc_main, ext_plist,
968 CR2RES_OBS_NODDING_SLITFUNCA_PROCATG, RECIPE_STRING) ;
969 cpl_free(out_file);
970
971 out_file = cpl_sprintf("%s_modelA%s", RECIPE_STRING,
972 product_name_addon) ;
973 cr2res_io_save_SLIT_MODEL(out_file, frameset, raw_one_angle, parlist,
974 modela, qc_main, ext_plist,
975 CR2RES_OBS_NODDING_SLITMODELA_PROCATG, RECIPE_STRING) ;
976 cpl_free(out_file);
977
978 out_file = cpl_sprintf("%s_trace_wave_A%s", RECIPE_STRING,
979 product_name_addon) ;
980 cr2res_io_save_TRACE_WAVE(out_file, frameset, raw_one_angle, parlist,
981 twa, qc_main, ext_plist, CR2RES_OBS_NODDING_TWA_PROCATG,
982 RECIPE_STRING) ;
983 cpl_free(out_file);
984
985 out_file = cpl_sprintf("%s_combinedB%s", RECIPE_STRING,
986 product_name_addon) ;
987 cr2res_io_save_COMBINED(out_file, frameset, raw_one_angle, parlist,
988 combinedb, qc_main, ext_plist,
989 CR2RES_OBS_NODDING_COMBINEDB_PROCATG, RECIPE_STRING) ;
990 cpl_free(out_file);
991
992 out_file = cpl_sprintf("%s_extractedB%s", RECIPE_STRING,
993 product_name_addon) ;
994 cr2res_io_save_EXTRACT_1D(out_file, frameset, raw_one_angle, parlist,
995 extractb, qc_main, ext_plist,
996 CR2RES_OBS_NODDING_EXTRACTB_PROCATG, RECIPE_STRING);
997 if (create_idp) {
998 cr2res_idp_save(out_file, frameset, raw_one_angle, parlist,
999 extractb, qc_main, ext_plist,
1000 CR2RES_OBS_NODDING_EXTRACTB_IDP_PROCATG,
1001 RECIPE_STRING);
1002 }
1003 cpl_free(out_file);
1004
1005 out_file = cpl_sprintf("%s_slitfuncB%s", RECIPE_STRING,
1006 product_name_addon) ;
1007 cr2res_io_save_SLIT_FUNC(out_file, frameset, raw_one_angle, parlist,
1008 slitfuncb, qc_main, ext_plist,
1009 CR2RES_OBS_NODDING_SLITFUNCB_PROCATG, RECIPE_STRING) ;
1010 cpl_free(out_file);
1011
1012 out_file = cpl_sprintf("%s_modelB%s", RECIPE_STRING,
1013 product_name_addon) ;
1014 cr2res_io_save_SLIT_MODEL(out_file, frameset, raw_one_angle, parlist,
1015 modelb, qc_main, ext_plist,
1016 CR2RES_OBS_NODDING_SLITMODELB_PROCATG, RECIPE_STRING) ;
1017 cpl_free(out_file);
1018
1019 out_file = cpl_sprintf("%s_trace_wave_B%s", RECIPE_STRING,
1020 product_name_addon) ;
1021 cr2res_io_save_TRACE_WAVE(out_file, frameset, raw_one_angle, parlist,
1022 twb, qc_main, ext_plist, CR2RES_OBS_NODDING_TWB_PROCATG,
1023 RECIPE_STRING) ;
1024 cpl_free(out_file);
1025
1026 out_file = cpl_sprintf("%s_extracted_combined%s", RECIPE_STRING,
1027 product_name_addon) ;
1028 cr2res_io_save_EXTRACT_1D(out_file, frameset, raw_one_angle, parlist,
1029 extractc, qc_main, ext_plist,
1030 CR2RES_OBS_NODDING_EXTRACTC_PROCATG, RECIPE_STRING);
1031 if (create_idp) {
1032 cr2res_idp_save(out_file, frameset, raw_one_angle, parlist,
1033 extractc, qc_main, ext_plist,
1034 CR2RES_OBS_NODDING_EXTRACTC_IDP_PROCATG,
1035 RECIPE_STRING);
1036 }
1037 cpl_free(out_file);
1038
1039 if (type == 2) {
1040
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");
1043
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);
1047
1048 cpl_free(qc_res_avg);
1049 cpl_free(qc_res_rmsd);
1050
1051 out_file = cpl_sprintf("%s_throughput%s", RECIPE_STRING,
1052 product_name_addon) ;
1053 cr2res_io_save_THROUGHPUT(out_file, frameset, raw_one_angle,
1054 parlist, throughput, qc_main, ext_plist,
1055 CR2RES_OBS_NODDING_THROUGHPUT_PROCATG, RECIPE_STRING) ;
1056 cpl_free(out_file);
1057 }
1058 cpl_free(product_name_addon) ;
1059
1060 /* Free */
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)
1064 hdrl_image_delete(combineda[det_nr-1]) ;
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)
1070 hdrl_image_delete(modela[det_nr-1]) ;
1071 if (twa[det_nr-1] != NULL)
1072 cpl_table_delete(twa[det_nr-1]) ;
1073 if (combinedb[det_nr-1] != NULL)
1074 hdrl_image_delete(combinedb[det_nr-1]) ;
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)
1080 hdrl_image_delete(modelb[det_nr-1]) ;
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]) ;
1091 }
1092 cpl_frameset_delete(raw_one_angle) ;
1093 cpl_msg_indent_less() ;
1094 }
1095 cpl_free(labels);
1096 cpl_frameset_delete(rawframes) ;
1097 if (raw_flat_frames != NULL) cpl_frameset_delete(raw_flat_frames) ;
1098
1099 return (int)cpl_error_get_code();
1100}
1101
1102/*----------------------------------------------------------------------------*/
1141/*----------------------------------------------------------------------------*/
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,
1150 int nodding_invert,
1151 int subtract_nolight_rows,
1152 int subtract_interorder_column,
1153 int cosmics,
1154 int error_method,
1155 int extract_oversample,
1156 double extract_pclip,
1157 int extract_swath_width,
1158 int extract_height,
1159 double extract_smooth_slit,
1160 double extract_smooth_spec,
1161 int extract_niter,
1162 double extract_kappa,
1163 int reduce_det,
1164 int disp_det,
1165 int disp_order_idx,
1166 int disp_trace,
1167 hdrl_image ** combineda,
1168 cpl_table ** extracta,
1169 cpl_table ** slitfunca,
1170 hdrl_image ** modela,
1171 cpl_table ** twa,
1172 hdrl_image ** combinedb,
1173 cpl_table ** extractb,
1174 cpl_table ** slitfuncb,
1175 hdrl_image ** modelb,
1176 cpl_table ** twb,
1177 cpl_table ** extractc,
1178 cpl_propertylist ** ext_plist)
1179{
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 ;
1191 cpl_vector * dits ;
1192 cpl_vector * ndits=NULL ;
1193 cpl_table * trace_wave ;
1194 // cpl_table * trace_wave_corrected ;
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 ;
1209 char * key_name ;
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 ;
1223 double * qc_snrs ;
1224 double * qc_der_snrs ;
1225 int nb_order_idx_values,
1226 nb_order_idx_values_der,
1227 order_zp, order_idx, order_idxp ;
1228
1229 /* Check Inputs */
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)
1236 return -1 ;
1237
1238 /* Get the Gain */
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 ;
1242 else {
1243 cpl_msg_error(__func__, "Failed to get the Gain value") ;
1244 return -1 ;
1245 }
1246
1247 /* Check raw frames consistency */
1248 if (cr2res_obs_nodding_check_inputs_validity(rawframes) != 1) {
1249 cpl_msg_error(__func__, "Invalid Inputs") ;
1250 return -1 ;
1251 }
1252
1253 /* Initialise */
1254 nframes = cpl_frameset_get_size(rawframes) ;
1255 first_fname = cpl_frame_get_filename(
1256 cpl_frameset_get_position_const(rawframes, 0)) ;
1257
1258 /* Get the order zeropoint */
1259 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(trace_wave_frame),
1260 0)) == NULL) {
1261 cpl_msg_error(__func__, "Cannot read the ORDER_ZP from the input TW") ;
1262 return -1 ;
1263 }
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") ;
1268 cpl_error_reset() ;
1269 /* Negative Zerop to log the fact that it is missing */
1270 order_zp = -100 ;
1271 }
1272
1273 /* Get the Nodding positions */
1274 cpl_msg_info(__func__, "Get the Nodding positions") ;
1275 cpl_msg_indent_more() ;
1276 nod_positions = cr2res_nodding_read_positions(rawframes) ;
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)),
1281 cr2res_nodding_position_char(nod_positions[i])) ;
1282 }
1283 cpl_msg_indent_less() ;
1284
1285 /* Load the DITs if necessary */
1286 dits = cr2res_io_read_dits(rawframes) ;
1287 //if (master_dark_frame != NULL) dits = cr2res_io_read_dits(rawframes) ;
1288 //else dits = NULL ;
1289 if (cpl_msg_get_level() == CPL_MSG_DEBUG && dits != NULL)
1290 cpl_vector_dump(dits, stdout) ;
1291
1292 /*Load the NDITs */
1293 ndits = cr2res_io_read_ndits(rawframes);
1294 if (cpl_msg_get_level() == CPL_MSG_DEBUG && ndits != NULL)
1295 cpl_vector_dump(ndits, stdout) ;
1296
1297 /* Load image list */
1298 cpl_msg_info(__func__, "Load the image list") ;
1299 if ((in = cr2res_io_load_image_list_from_set(rawframes,
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) ;
1304 return -1 ;
1305 }
1306 if (hdrl_imagelist_get_size(in) != cpl_frameset_get_size(rawframes)) {
1307 cpl_msg_error(__func__, "Inconsistent number of loaded images") ;
1308 cpl_free(nod_positions) ;
1309 if (dits != NULL) cpl_vector_delete(dits) ;
1311 return -1 ;
1312 }
1313
1314 /* Calibrate the images */
1315 cpl_msg_info(__func__, "Apply the Calibrations") ;
1316 cpl_msg_indent_more() ;
1317 if ((in_calib = cr2res_calib_imagelist(in, reduce_det, 0,
1318 subtract_nolight_rows, subtract_interorder_column, cosmics,
1319 master_flat_frame, master_dark_frame, bpm_frame, detlin_frame, dits,
1320 ndits))==NULL) {
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) ;
1327 return -1 ;
1328 }
1330 if (dits != NULL) cpl_vector_delete(dits) ;
1331 cpl_msg_indent_less() ;
1332
1333 /* Split the image lists */
1334 cpl_msg_info(__func__, "Split the images in A and B lists") ;
1335 cpl_msg_indent_more() ;
1336 if (cr2res_combine_nodding_split(in_calib, nod_positions, &in_a,
1337 &in_b)) {
1338 cpl_msg_error(__func__, "Failed to split the nodding positions") ;
1339 cpl_msg_indent_less() ;
1340 cpl_free(nod_positions) ;
1341 hdrl_imagelist_delete(in_calib) ;
1342 cpl_vector_delete(ndits) ;
1343 return -1 ;
1344 }
1345
1346 /* error factor is gain * ndit *nexp */
1347 if (error_method == CR2RES_EXTRACT_ERROR_HORNE) {
1348 error_factor = -1.0;
1349 }
1350 else {
1351 error_factor = gain * cpl_vector_get(ndits, 0) *
1353 }
1354
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.");
1359 }
1360 cpl_vector_delete(ndits) ;
1361 cpl_free(nod_positions) ;
1362 hdrl_imagelist_delete(in_calib) ;
1363 cpl_msg_indent_less() ;
1364
1365 /* Check the sizes of A/B image lists */
1367 || hdrl_imagelist_get_size(in_a) == 0) {
1368 cpl_msg_error(__func__, "Inconsistent A / B number of images") ;
1369 hdrl_imagelist_delete(in_a) ;
1370 hdrl_imagelist_delete(in_b) ;
1371 return -1 ;
1372 }
1373
1374 /* Compute diff_a = in_a - in_b and diff_b = in_b - in_a */
1375 cpl_msg_info(__func__, "Compute difference image lists A-B and B-A") ;
1376 diff_a = hdrl_imagelist_duplicate(in_a) ;
1377 hdrl_imagelist_sub_imagelist(diff_a, in_b) ;
1378 diff_b = hdrl_imagelist_duplicate(in_b) ;
1379 hdrl_imagelist_sub_imagelist(diff_b, in_a) ;
1380 hdrl_imagelist_delete(in_a) ;
1381 hdrl_imagelist_delete(in_b) ;
1382
1383 /* Collapse A-B and B-A */
1384 cpl_msg_info(__func__, "Collapse image lists A-B and B-A") ;
1385 cpl_msg_indent_more() ;
1386 if (hdrl_imagelist_collapse_mean(diff_a, &collapsed_a, &contrib_a) !=
1387 CPL_ERROR_NONE) {
1388 cpl_msg_error(__func__, "Failed to Collapse A-B") ;
1389 hdrl_imagelist_delete(diff_a) ;
1390 hdrl_imagelist_delete(diff_b) ;
1391 cpl_msg_indent_less() ;
1392 return -1 ;
1393 }
1394 cpl_image_delete(contrib_a) ;
1395 hdrl_imagelist_delete(diff_a) ;
1396 if (hdrl_imagelist_collapse_mean(diff_b, &collapsed_b, &contrib_b) !=
1397 CPL_ERROR_NONE) {
1398 cpl_msg_error(__func__, "Failed to Collapse B-A") ;
1399 hdrl_imagelist_delete(diff_b) ;
1400 hdrl_image_delete(collapsed_a) ;
1401 cpl_msg_indent_less() ;
1402 return -1 ;
1403 }
1404 cpl_image_delete(contrib_b) ;
1405 hdrl_imagelist_delete(diff_b) ;
1406 cpl_msg_indent_less() ;
1407
1408 /* Load the trace wave */
1409 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
1410 if ((trace_wave = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(
1411 trace_wave_frame), reduce_det)) == NULL) {
1412 cpl_msg_error(__func__, "Failed to Load the traces file") ;
1413 hdrl_image_delete(collapsed_a) ;
1414 hdrl_image_delete(collapsed_b) ;
1415 return -1 ;
1416 }
1417
1418 /* Correct trace_wave with some provided raw flats */
1419 cpl_msg_warning(__func__, "TRACE ADJUST NOT YET IMPLEMENTED") ;
1420 /*if (raw_flat_frames != NULL) {
1421 cpl_msg_info(__func__, "Try to correct the reproducibility error") ;
1422 cpl_msg_indent_more() ;
1423 trace_wave_corrected = cr2res_trace_adjust(trace_wave, raw_flat_frames,
1424 reduce_det) ;
1425 if (trace_wave_corrected != NULL) {
1426 cpl_table_delete(trace_wave) ;
1427 trace_wave = trace_wave_corrected ;
1428 trace_wave_corrected = NULL ;
1429 }
1430 cpl_msg_indent_less() ;
1431 }*/
1432
1433 /* Compute the slit fractions for A and B positions extraction */
1434 cpl_msg_info(__func__, "Compute the slit fractions for A and B positions");
1435 cpl_msg_indent_more() ;
1436 /*
1437 The assumption is made here that :
1438 - The slit center is exactly in the middle of A and B positions
1439 - The nodthrow is the distance in arcseconds between A and B
1440 - The slit size is 10 arcseconds
1441 - The B position is above the A position (--nodding-invert=false)
1442 */
1443 slit_length = 10 ;
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() ;
1447 hdrl_image_delete(collapsed_a) ;
1448 hdrl_image_delete(collapsed_b) ;
1449 cpl_table_delete(trace_wave) ;
1450 return -1 ;
1451 }
1452 nod_throw = cr2res_pfits_get_nodthrow(plist) ;
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 ;
1463 } else {
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 ;
1470 }
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 ;
1480 } else {
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 ;
1487 }
1488 } else {
1489 cpl_msg_error(__func__, "NODTHROW > slit length (%g>%g)- abort",
1490 nod_throw, slit_length) ;
1491 cpl_msg_indent_less() ;
1492 hdrl_image_delete(collapsed_a) ;
1493 hdrl_image_delete(collapsed_b) ;
1494 cpl_table_delete(trace_wave) ;
1495 return -1 ;
1496 }
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) ;
1502
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) ;
1507
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() ;
1513
1514 /* Recompute the traces for the new slit fractions */
1515 cpl_msg_info(__func__, "Recompute the traces for the A slit fraction") ;
1516 if ((trace_wave_a = cr2res_trace_new_slit_fraction(trace_wave,
1517 slit_frac_a)) == NULL) {
1518 cpl_msg_error(__func__,
1519 "Failed to compute the traces for extraction of A") ;
1520 hdrl_image_delete(collapsed_a) ;
1521 hdrl_image_delete(collapsed_b) ;
1522 cpl_table_delete(trace_wave) ;
1523 cpl_array_delete(slit_frac_a) ;
1524 cpl_array_delete(slit_frac_b) ;
1525 return -1 ;
1526 }
1527 cpl_array_delete(slit_frac_a) ;
1528
1529 cpl_msg_info(__func__, "Recompute the traces for the B slit fraction") ;
1530 if ((trace_wave_b = cr2res_trace_new_slit_fraction(trace_wave,
1531 slit_frac_b)) == NULL) {
1532 cpl_msg_error(__func__,
1533 "Failed to compute the traces for extraction of B") ;
1534 hdrl_image_delete(collapsed_a) ;
1535 hdrl_image_delete(collapsed_b) ;
1536 cpl_table_delete(trace_wave) ;
1537 cpl_table_delete(trace_wave_a) ;
1538 cpl_array_delete(slit_frac_b) ;
1539 return -1 ;
1540 }
1541 cpl_array_delete(slit_frac_b) ;
1542
1543 /* Load Blaze */
1544 blaze_table = NULL ;
1545 blaze_norm = 0;
1546 if (blaze_frame != NULL) {
1547 cpl_msg_info(__func__, "Load the BLAZE") ;
1548 if ((blaze_table = cr2res_io_load_EXTRACT_1D(cpl_frame_get_filename(
1549 blaze_frame), reduce_det)) == NULL) {
1550 cpl_msg_error(__func__, "Failed to Load the Blaze file") ;
1551 hdrl_image_delete(collapsed_a) ;
1552 hdrl_image_delete(collapsed_b) ;
1553 cpl_table_delete(trace_wave) ;
1554 cpl_table_delete(trace_wave_a) ;
1555 cpl_table_delete(trace_wave_b) ;
1556 return -1 ;
1557 }
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);
1563 }
1564 else {
1565 blaze_norm = -1;
1566 cpl_msg_warning(__func__, "QC BLAZE NORM value not found, reverting to per trace normalization") ;
1567 }
1568 if(blaze_plist!=NULL){
1569 cpl_propertylist_delete(blaze_plist);
1570 }
1571 }
1572
1573 /* Execute the extraction */
1574 cpl_msg_info(__func__, "A position Spectra Extraction") ;
1575 cpl_msg_indent_more() ;
1576 if (cr2res_extract_traces(collapsed_a, trace_wave_a, NULL, blaze_table, blaze_norm, -1,
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() ;
1584 hdrl_image_delete(collapsed_a) ;
1585 hdrl_image_delete(collapsed_b) ;
1586 cpl_table_delete(trace_wave_a) ;
1587 cpl_table_delete(trace_wave_b) ;
1588 cpl_table_delete(trace_wave) ;
1589 return -1 ;
1590 }
1591 cpl_msg_indent_less() ;
1592
1593 cpl_msg_info(__func__, "B position Spectra Extraction") ;
1594 cpl_msg_indent_more() ;
1595 if (cr2res_extract_traces(collapsed_b, trace_wave_b, NULL, blaze_table, blaze_norm, -1,
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) ;
1605 hdrl_image_delete(model_master_a) ;
1606 hdrl_image_delete(collapsed_a) ;
1607 hdrl_image_delete(collapsed_b) ;
1608 cpl_table_delete(trace_wave_a) ;
1609 cpl_table_delete(trace_wave_b) ;
1610 cpl_table_delete(trace_wave) ;
1611 return -1 ;
1612 }
1613 cpl_msg_indent_less() ;
1614
1615 if (blaze_table != NULL) cpl_table_delete(blaze_table) ;
1616
1617 /* Combine both a and b extracted spectra together */
1618 cpl_msg_info(__func__, "A and B spectra combination") ;
1619 cpl_msg_indent_more() ;
1620 extracted_combined = cr2res_combine_extracted(extracted_a, extracted_b) ;
1621 cpl_msg_indent_less() ;
1622
1623 /* Get the Setting */
1624 plist = cpl_propertylist_load(first_fname, 0) ;
1625 cur_setting = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
1626 cr2res_format_setting(cur_setting) ;
1627 cpl_propertylist_delete(plist) ;
1628
1629 /* Store the extension header for product saving */
1630 plist = cpl_propertylist_load(first_fname,
1631 cr2res_io_get_ext_idx(first_fname, reduce_det, 1)) ;
1632
1633 /* QC - Signal and FWHM */
1634 cpl_msg_info(__func__, "QC parameters computation") ;
1635 qc_signal_a = cr2res_qc_obs_nodding_signal(extracted_a) ;
1636 qc_signal_b = cr2res_qc_obs_nodding_signal(extracted_b) ;
1637 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SIGNAL,
1638 (qc_signal_a+qc_signal_b)/2.0) ;
1639
1640 /* QC STANDARD FLUX */
1641 qc_standard_flux_a =
1642 cr2res_qc_obs_nodding_standard_flux(extracted_a, cur_setting) ;
1643 qc_standard_flux_b =
1644 cr2res_qc_obs_nodding_standard_flux(extracted_b, cur_setting) ;
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) ;
1648
1649 /* QC - SNR on nodding A position */
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] ;
1656 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
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) ;
1663 }
1664 cpl_free(order_idx_values) ;
1665 cpl_free(order_idx_values_der) ;
1666 cpl_free(qc_snrs) ;
1667 cpl_free(qc_der_snrs) ;
1668
1669 /* Get the order numbers from the TW rows */
1670 order_idx_values = cr2res_trace_get_order_idx_values(trace_wave,
1671 &nb_order_idx_values);
1672
1673 /* QC - SLIT FWHM */
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] ;
1678 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
1679 qc_fwhm_a = cr2res_qc_obs_slit_psf(slit_func_a, order_idxp,
1680 extract_oversample);
1681 qc_fwhm_b = cr2res_qc_obs_slit_psf(slit_func_b, order_idxp,
1682 extract_oversample);
1683
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) ;
1690 }
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,
1695 qc_fwhm_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."
1703 , qc_fwhm_med);
1704 }
1705 cpl_array_delete(fwhm_a_array) ;
1706 cpl_array_delete(fwhm_b_array) ;
1707
1708 /* QC - Real Orders */
1709 if (order_zp > 0) {
1710 /* Compute the Real Order numbers and store them in QCs */
1711 for (i = 0; i < nb_order_idx_values; i++) {
1712 int order_real;
1713 order_idx = order_idx_values[i] ;
1714 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
1715
1716 order_real = cr2res_order_idx_to_real(order_idx, order_zp) ;
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) ;
1720 }
1721 }
1722 cpl_table_delete(trace_wave) ;
1723 cpl_free(order_idx_values) ;
1724
1725 /* Return */
1726 *combineda = collapsed_a ;
1727 *extracta = extracted_a ;
1728 *slitfunca = slit_func_a ;
1729 *modela = model_master_a ;
1730 *twa = trace_wave_a ;
1731
1732 *combinedb = collapsed_b ;
1733 *extractb = extracted_b ;
1734 *slitfuncb = slit_func_b ;
1735 *modelb = model_master_b ;
1736 *twb = trace_wave_b ;
1737
1738 *extractc = extracted_combined ;
1739 *ext_plist = plist ;
1740
1741 return 0 ;
1742}
1743
1744/*----------------------------------------------------------------------------*/
1750/*----------------------------------------------------------------------------*/
1751static int cr2res_obs_nodding_check_inputs_validity(
1752 const cpl_frameset * rawframes)
1753{
1754 cpl_propertylist * plist ;
1755 cr2res_nodding_pos * nod_positions ;
1756 cpl_size nframes, i ;
1757 double nodthrow;
1758 int nb_a, nb_b ;
1759
1760 /* Check Inputs */
1761 if (rawframes == NULL) return -1 ;
1762
1763 /* Need even number of frames */
1764 nframes = cpl_frameset_get_size(rawframes) ;
1765 if (nframes % 2) {
1766 cpl_msg_error(__func__, "Require an even number of raw frames") ;
1767 return 0 ;
1768 }
1769
1770 /* Need same number of A and B positions */
1771 nb_a = nb_b = 0 ;
1772 nod_positions = cr2res_nodding_read_positions(rawframes) ;
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++ ;
1777 }
1778 cpl_free(nod_positions) ;
1779
1780 if (nb_a == 0 || nb_b == 0 || nb_a != nb_b) {
1781 cpl_msg_error(__func__, "Require as many A and B positions") ;
1782 return 0 ;
1783 }
1784
1785 /* Need the same nod throw in all frames */
1786 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(
1787 cpl_frameset_get_position_const(rawframes, 0)),
1788 0)) == NULL) {
1789 return -1;
1790 }
1791 nodthrow = cr2res_pfits_get_nodthrow(plist);
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)),
1797 0)) == NULL) {
1798 return -1;
1799 }
1800 nodthrow_cur = cr2res_pfits_get_nodthrow(plist);
1801 cpl_propertylist_delete(plist) ;
1802
1803 if (fabs(nodthrow_cur-nodthrow) > 1e-3) {
1804 cpl_msg_error(__func__,
1805 "Require constant NOD THROW in the raw frames") ;
1806 return 0 ;
1807 }
1808 }
1809 return 1 ;
1810}
1811
1812/*----------------------------------------------------------------------------*/
1828/*----------------------------------------------------------------------------*/
1829static cpl_frameset * cr2res_obs_nodding_find_RAW(
1830 const cpl_frameset * in,
1831 int * type)
1832{
1833 cpl_frameset * out ;
1834
1835 /* Check entries */
1836 if (in == NULL) return NULL ;
1837
1838 out = cr2res_extract_frameset(in, CR2RES_OBS_NODDING_OTHER_RAW) ;
1839 if (out == NULL) {
1840 out = cr2res_extract_frameset(in, CR2RES_OBS_NODDING_JITTER_RAW) ;
1841 }
1842 if (out != NULL) {
1843 if (type != NULL) *type = 1 ;
1844 } else {
1845 out = cr2res_extract_frameset(in, CR2RES_CAL_NODDING_OTHER_RAW) ;
1846 if (out == NULL) {
1847 out = cr2res_extract_frameset(in, CR2RES_CAL_NODDING_JITTER_RAW) ;
1848 }
1849 if (out != NULL) {
1850 if (type != NULL) *type = 2 ;
1851 } else {
1852 out = cr2res_extract_frameset(in, CR2RES_OBS_ASTROMETRY_OTHER_RAW) ;
1853 if (out == NULL) {
1854 out = cr2res_extract_frameset(in,
1855 CR2RES_OBS_ASTROMETRY_JITTER_RAW) ;
1856 }
1857 if (out != NULL) {
1858 if (type != NULL) *type = 3 ;
1859 }
1860 }
1861 }
1862 if (out == NULL) {
1863 if (type != NULL) *type = 0 ;
1864 }
1865 return out ;
1866}
1867
1868/*----------------------------------------------------------------------------*/
1875/*----------------------------------------------------------------------------*/
1876static int cr2res_obs_nodding_astrometry_compare(
1877 const cpl_frame * frame1,
1878 const cpl_frame * frame2)
1879{
1880 int comparison ;
1881 cpl_propertylist * plist1 ;
1882 cpl_propertylist * plist2 ;
1883 double dval1, dval2 ;
1884
1885 /* Test entries */
1886 if (frame1==NULL || frame2==NULL) return -1 ;
1887
1888 /* Get property lists */
1889 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1890 cpl_msg_error(__func__, "getting header from reference frame");
1891 return -1 ;
1892 }
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) ;
1896 return -1 ;
1897 }
1898
1899 /* Test status */
1900 if (cpl_error_get_code()) {
1901 cpl_propertylist_delete(plist1) ;
1902 cpl_propertylist_delete(plist2) ;
1903 return -1 ;
1904 }
1905
1906 comparison = 1 ;
1907
1908 /* Compare the DROT angle used */
1909 dval1 = cr2res_pfits_get_drot_posang(plist1) ;
1910 dval2 = cr2res_pfits_get_drot_posang(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) ;
1915 return -1 ;
1916 }
1917 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
1918
1919 cpl_propertylist_delete(plist1) ;
1920 cpl_propertylist_delete(plist2) ;
1921 return comparison ;
1922}
1923
1924
hdrl_imagelist * cr2res_calib_imagelist(const hdrl_imagelist *in, int chip, int clean_bad, int subtract_nolight_rows, int subtract_interorder_column, int cosmics_corr, const cpl_frame *flat, const cpl_frame *dark, const cpl_frame *bpm, const cpl_frame *detlin, const cpl_vector *dits, const cpl_vector *ndits)
The images calibration routine for a given chip on a list.
Definition: cr2res_calib.c:71
cpl_error_code cr2res_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: cr2res_dfs.c:53
int cr2res_extract_traces(const hdrl_image *img, const cpl_table *traces, const cpl_table *slit_func_in, const cpl_table *blaze_table_in, float blaze_norm, int reduce_order, int reduce_trace, cr2res_extr_method extr_method, int extr_height, int swath_width, int oversample, double pclip, double smooth_slit, double smooth_spec, int niter, double kappa, double error_factor, int display, int disp_order_idx, int disp_trace, cpl_table **extracted, cpl_table **slit_func, hdrl_image **model_master)
Extracts all the passed traces at once.
int cr2res_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.
Definition: cr2res_idp.c:98
cpl_table * cr2res_io_load_EXTRACT_1D(const char *filename, int detector)
Load a table from a EXTRACT_1D.
Definition: cr2res_io.c:1296
const cpl_frame * cr2res_io_find_BPM(const cpl_frameset *in)
Get the first CR2RES_BPM_DRSTYPE frame from a frameset.
Definition: cr2res_io.c:369
int cr2res_io_save_SLIT_MODEL(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, hdrl_image **data, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_MODEL.
Definition: cr2res_io.c:1823
const cpl_frame * cr2res_io_find_TRACE_WAVE(const cpl_frameset *in)
Get the first CR2RES_TW_DRSTYPE frame from a frameset.
Definition: cr2res_io.c:231
int cr2res_io_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_TRACE_WAVE(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a TRACE_WAVE.
Definition: cr2res_io.c:1670
cpl_vector * cr2res_io_read_dits(const cpl_frameset *in)
Get the DITS from a frame set.
Definition: cr2res_io.c:432
int cr2res_io_save_EXTRACT_1D(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **tables, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a 1D extracted spectrum.
Definition: cr2res_io.c:1732
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
Definition: cr2res_io.c:808
cpl_table * cr2res_io_get_eop_table()
Get the eop_table.
Definition: cr2res_io.c:120
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.
Definition: cr2res_io.c:1762
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
int cr2res_io_save_SLIT_FUNC(const char *filename, cpl_frameset *allframes, cpl_frameset *inframes, const cpl_parameterlist *parlist, cpl_table **slit_func, const cpl_propertylist *qc_list, cpl_propertylist **ext_plist, const char *procatg, const char *recipe)
Save a SLIT_FUNC.
Definition: cr2res_io.c:1792
int cr2res_io_save_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.
Definition: cr2res_io.c:1854
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
Definition: cr2res_io.c:1109
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
Definition: cr2res_io.c:462
const char * cr2res_pfits_get_wlen_id(const cpl_propertylist *plist)
find out the Setting
Definition: cr2res_pfits.c:137
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: cr2res_pfits.c:199
double cr2res_pfits_get_dec(const cpl_propertylist *plist)
find out the DEC
Definition: cr2res_pfits.c:150
double cr2res_pfits_get_drot_posang(const cpl_propertylist *plist)
find out the DROT POSANG value
Definition: cr2res_pfits.c:174
double cr2res_pfits_get_nodthrow(const cpl_propertylist *plist)
find out the NODTHROW value
Definition: cr2res_pfits.c:186
double cr2res_pfits_get_ra(const cpl_propertylist *plist)
find out the RA
Definition: cr2res_pfits.c:162
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.
Definition: cr2res_qc.c:1290
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.
Definition: cr2res_qc.c:1103
double cr2res_qc_obs_nodding_signal(const cpl_table *extracted)
Computes the integrated flux over part of the spectrum.
Definition: cr2res_qc.c:845
double cr2res_qc_obs_nodding_standard_flux(const cpl_table *extracted, char *setting)
Computes the standard flux over part of the spectrum.
Definition: cr2res_qc.c:892
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.
Definition: cr2res_qc.c:1010
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.
Definition: cr2res_qc.c:1208
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.
Definition: cr2res_trace.c:431
int cr2res_format_setting(char *setting_id)
Format the setting.
Definition: cr2res_utils.c:152
int cr2res_order_idx_to_real(int order_idx, int order_zp)
Convert the order_idx into order_real.
Definition: cr2res_utils.c:89
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.
Definition: cr2res_utils.c:278
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
Definition: hdrl_image.c:379
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
cpl_size hdrl_imagelist_get_size(const hdrl_imagelist *himlist)
Get the number of images in the imagelist.
cpl_error_code hdrl_imagelist_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.