CR2RE Pipeline Reference Manual 1.7.0
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 "Horne", 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", 800);
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_vector * ndsamples ;
1194 cpl_table * trace_wave ;
1195 // cpl_table * trace_wave_corrected ;
1196 cpl_table * trace_wave_a ;
1197 cpl_table * trace_wave_b ;
1198 cpl_table * blaze_table ;
1199 cpl_array * slit_frac_a ;
1200 cpl_array * slit_frac_b ;
1201 cpl_table * extracted_a ;
1202 cpl_table * extracted_b ;
1203 cpl_table * extracted_combined ;
1204 cpl_table * slit_func_a ;
1205 cpl_table * slit_func_b ;
1206 hdrl_image * model_master_a ;
1207 hdrl_image * model_master_b ;
1208 cpl_propertylist * plist ;
1209 cpl_size nframes, i ;
1210 char * key_name ;
1211 const char * first_fname ;
1212 double slit_length, extr_width_frac, slit_frac_a_bot,
1213 slit_frac_a_mid, slit_frac_a_top, slit_frac_b_bot,
1214 slit_frac_b_mid, slit_frac_b_top, nod_throw,
1215 gain, error_factor ;
1216 double qc_signal_a, qc_signal_b, qc_fwhm_a,
1217 qc_fwhm_b, qc_standard_flux_a,
1218 qc_standard_flux_b, qc_fwhm_med, blaze_norm ;
1219 cpl_array * fwhm_a_array ;
1220 cpl_array * fwhm_b_array ;
1221 char * cur_setting ;
1222 int * order_idx_values ;
1223 int * order_idx_values_der ;
1224 double * qc_snrs ;
1225 double * qc_der_snrs ;
1226 int nb_order_idx_values,
1227 nb_order_idx_values_der,
1228 order_zp, order_idx, order_idxp ;
1229
1230 /* Check Inputs */
1231 if (combineda == NULL || combinedb == NULL ||
1232 twa == NULL || twb == NULL ||
1233 slitfunca == NULL || slitfuncb == NULL ||
1234 modela == NULL || modelb == NULL ||
1235 extracta == NULL || extractb == NULL || extractc == NULL ||
1236 ext_plist == NULL || rawframes == NULL || trace_wave_frame == NULL)
1237 return -1 ;
1238
1239 /* Get the Gain */
1240 if (reduce_det == 1) gain = CR2RES_GAIN_CHIP1 ;
1241 else if (reduce_det == 2) gain = CR2RES_GAIN_CHIP2 ;
1242 else if (reduce_det == 3) gain = CR2RES_GAIN_CHIP3 ;
1243 else {
1244 cpl_msg_error(__func__, "Failed to get the Gain value") ;
1245 return -1 ;
1246 }
1247
1248 /* Check raw frames consistency */
1249 if (cr2res_obs_nodding_check_inputs_validity(rawframes) != 1) {
1250 cpl_msg_error(__func__, "Invalid Inputs") ;
1251 return -1 ;
1252 }
1253
1254 /* Initialise */
1255 nframes = cpl_frameset_get_size(rawframes) ;
1256 first_fname = cpl_frame_get_filename(
1257 cpl_frameset_get_position_const(rawframes, 0)) ;
1258
1259 /* Get the order zeropoint */
1260 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(trace_wave_frame),
1261 0)) == NULL) {
1262 cpl_msg_error(__func__, "Cannot read the ORDER_ZP from the input TW") ;
1263 return -1 ;
1264 }
1265 order_zp = cr2res_pfits_get_order_zp(plist) ;
1266 cpl_propertylist_delete(plist) ;
1267 if (cpl_error_get_code()) {
1268 cpl_msg_error(__func__, "Missing ORDER_ZP in the header - Skip") ;
1269 cpl_error_reset() ;
1270 /* Negative Zerop to log the fact that it is missing */
1271 order_zp = -100 ;
1272 }
1273
1274 /* Get the Nodding positions */
1275 cpl_msg_info(__func__, "Get the Nodding positions") ;
1276 cpl_msg_indent_more() ;
1277 nod_positions = cr2res_nodding_read_positions(rawframes) ;
1278 for (i=0 ; i<nframes ; i++) {
1279 cpl_msg_info(__func__, "Frame %s - Nodding %c",
1280 cpl_frame_get_filename(
1281 cpl_frameset_get_position_const(rawframes, i)),
1282 cr2res_nodding_position_char(nod_positions[i])) ;
1283 }
1284 cpl_msg_indent_less() ;
1285
1286 /* Load the DITs if necessary */
1287 dits = cr2res_io_read_dits(rawframes) ;
1288 //if (master_dark_frame != NULL) dits = cr2res_io_read_dits(rawframes) ;
1289 //else dits = NULL ;
1290 if (cpl_msg_get_level() == CPL_MSG_DEBUG && dits != NULL)
1291 cpl_vector_dump(dits, stdout) ;
1292
1293 /*Load the NDITs */
1294 ndits = cr2res_io_read_ndits(rawframes);
1295 if (cpl_msg_get_level() == CPL_MSG_DEBUG && ndits != NULL)
1296 cpl_vector_dump(ndits, stdout) ;
1297
1298 /* Load image list */
1299 cpl_msg_info(__func__, "Load the image list") ;
1300 if ((in = cr2res_io_load_image_list_from_set(rawframes,
1301 reduce_det)) == NULL) {
1302 cpl_msg_error(__func__, "Cannot load images") ;
1303 cpl_free(nod_positions) ;
1304 if (dits != NULL) cpl_vector_delete(dits) ;
1305 return -1 ;
1306 }
1307 if (hdrl_imagelist_get_size(in) != cpl_frameset_get_size(rawframes)) {
1308 cpl_msg_error(__func__, "Inconsistent number of loaded images") ;
1309 cpl_free(nod_positions) ;
1310 if (dits != NULL) cpl_vector_delete(dits) ;
1312 return -1 ;
1313 }
1314
1315 /* Calibrate the images */
1316 cpl_msg_info(__func__, "Apply the Calibrations") ;
1317 cpl_msg_indent_more() ;
1318 ndsamples = cr2res_io_read_ndsamples(rawframes) ;
1319 in_calib = cr2res_calib_imagelist(in, reduce_det, 0,
1320 subtract_nolight_rows, subtract_interorder_column, cosmics,
1321 master_flat_frame, master_dark_frame, bpm_frame, detlin_frame, dits,
1322 ndits, ndsamples) ;
1323 cpl_vector_delete(ndsamples) ;
1324 if (in_calib == NULL) {
1325 cpl_msg_error(__func__, "Failed to apply the calibrations") ;
1326 cpl_msg_indent_less() ;
1327 cpl_free(nod_positions) ;
1328 if (dits != NULL) cpl_vector_delete(dits) ;
1329 if (ndits != NULL) cpl_vector_delete(ndits) ;
1331 return -1 ;
1332 }
1334 cpl_msg_indent_less() ;
1335
1336 /* Flat and dark errors are common to all frames: remove them here. */
1337 /* The flat term is re-added after the collapse, the dark cancels in A-B */
1338 hdrl_image * mflat = NULL ;
1339 cpl_image * flat_relerr2 = NULL ;
1340 if (master_flat_frame != NULL) {
1342 cpl_frame_get_filename(master_flat_frame), reduce_det) ;
1343 if (mflat == NULL) {
1344 cpl_msg_error(__func__, "Cannot load the master flat") ;
1345 cpl_free(nod_positions) ;
1346 if (dits != NULL) cpl_vector_delete(dits) ;
1347 cpl_vector_delete(ndits) ;
1348 hdrl_imagelist_delete(in_calib) ;
1349 return -1 ;
1350 }
1351 flat_relerr2 = cr2res_calib_flat_relerr2(mflat) ;
1352 for (i=0 ; i<hdrl_imagelist_get_size(in_calib) ; i++)
1354 flat_relerr2, -1.0) ;
1355 }
1356 if (master_dark_frame != NULL && dits != NULL &&
1357 cr2res_calib_dark_var(in_calib, master_dark_frame,
1358 reduce_det, mflat, dits, -1.0)) {
1359 cpl_msg_error(__func__, "Cannot remove the master dark errors") ;
1360 cpl_free(nod_positions) ;
1361 cpl_vector_delete(dits) ;
1362 cpl_vector_delete(ndits) ;
1363 hdrl_imagelist_delete(in_calib) ;
1364 if (mflat != NULL) hdrl_image_delete(mflat) ;
1365 if (flat_relerr2 != NULL) cpl_image_delete(flat_relerr2) ;
1366 return -1 ;
1367 }
1368 if (mflat != NULL) hdrl_image_delete(mflat) ;
1369 if (dits != NULL) cpl_vector_delete(dits) ;
1370
1371 /* Split the image lists */
1372 cpl_msg_info(__func__, "Split the images in A and B lists") ;
1373 cpl_msg_indent_more() ;
1374 if (cr2res_combine_nodding_split(in_calib, nod_positions, &in_a,
1375 &in_b)) {
1376 cpl_msg_error(__func__, "Failed to split the nodding positions") ;
1377 cpl_msg_indent_less() ;
1378 cpl_free(nod_positions) ;
1379 hdrl_imagelist_delete(in_calib) ;
1380 cpl_vector_delete(ndits) ;
1381 return -1 ;
1382 }
1383
1384 /* error factor is gain * ndit *nexp */
1385 if (error_method == CR2RES_EXTRACT_ERROR_HORNE) {
1386 error_factor = -1.0;
1387 }
1388 else {
1389 error_factor = gain * cpl_vector_get(ndits, 0) *
1391 }
1392
1393 for (i=0; i<cpl_vector_get_size(ndits); i++){
1394 if (cpl_vector_get(ndits,i) != cpl_vector_get(ndits, 0))
1395 cpl_msg_warning(__func__, "Raw frames have different NDIT! "
1396 "Error spectrum will likely be scaled incorrectly.");
1397 }
1398 cpl_vector_delete(ndits) ;
1399 cpl_free(nod_positions) ;
1400 hdrl_imagelist_delete(in_calib) ;
1401 cpl_msg_indent_less() ;
1402
1403 /* Check the sizes of A/B image lists */
1405 || hdrl_imagelist_get_size(in_a) == 0) {
1406 cpl_msg_error(__func__, "Inconsistent A / B number of images") ;
1407 hdrl_imagelist_delete(in_a) ;
1408 hdrl_imagelist_delete(in_b) ;
1409 return -1 ;
1410 }
1411
1412 /* Compute diff_a = in_a - in_b and diff_b = in_b - in_a */
1413 cpl_msg_info(__func__, "Compute difference image lists A-B and B-A") ;
1414 diff_a = hdrl_imagelist_duplicate(in_a) ;
1415 hdrl_imagelist_sub_imagelist(diff_a, in_b) ;
1416 diff_b = hdrl_imagelist_duplicate(in_b) ;
1417 hdrl_imagelist_sub_imagelist(diff_b, in_a) ;
1418 hdrl_imagelist_delete(in_a) ;
1419 hdrl_imagelist_delete(in_b) ;
1420
1421 /* Collapse A-B and B-A */
1422 cpl_msg_info(__func__, "Collapse image lists A-B and B-A") ;
1423 cpl_msg_indent_more() ;
1424 if (hdrl_imagelist_collapse_mean(diff_a, &collapsed_a, &contrib_a) !=
1425 CPL_ERROR_NONE) {
1426 cpl_msg_error(__func__, "Failed to Collapse A-B") ;
1427 hdrl_imagelist_delete(diff_a) ;
1428 hdrl_imagelist_delete(diff_b) ;
1429 cpl_msg_indent_less() ;
1430 return -1 ;
1431 }
1432 cpl_image_delete(contrib_a) ;
1433 hdrl_imagelist_delete(diff_a) ;
1434 if (hdrl_imagelist_collapse_mean(diff_b, &collapsed_b, &contrib_b) !=
1435 CPL_ERROR_NONE) {
1436 cpl_msg_error(__func__, "Failed to Collapse B-A") ;
1437 hdrl_imagelist_delete(diff_b) ;
1438 hdrl_image_delete(collapsed_a) ;
1439 cpl_msg_indent_less() ;
1440 return -1 ;
1441 }
1442 cpl_image_delete(contrib_b) ;
1443 hdrl_imagelist_delete(diff_b) ;
1444 cpl_msg_indent_less() ;
1445
1446 /* Apply flat field relative error to collapsed images */
1447 if (flat_relerr2 != NULL) {
1448 cr2res_calib_flat_var(collapsed_a, flat_relerr2, 1.0) ;
1449 cr2res_calib_flat_var(collapsed_b, flat_relerr2, 1.0) ;
1450 cpl_image_delete(flat_relerr2) ;
1451 }
1452
1453 /* Load the trace wave */
1454 cpl_msg_info(__func__, "Load the TRACE WAVE") ;
1455 if ((trace_wave = cr2res_io_load_TRACE_WAVE(cpl_frame_get_filename(
1456 trace_wave_frame), reduce_det)) == NULL) {
1457 cpl_msg_error(__func__, "Failed to Load the traces file") ;
1458 hdrl_image_delete(collapsed_a) ;
1459 hdrl_image_delete(collapsed_b) ;
1460 return -1 ;
1461 }
1462
1463 /* Correct trace_wave with some provided raw flats */
1464 cpl_msg_warning(__func__, "TRACE ADJUST NOT YET IMPLEMENTED") ;
1465 /*if (raw_flat_frames != NULL) {
1466 cpl_msg_info(__func__, "Try to correct the reproducibility error") ;
1467 cpl_msg_indent_more() ;
1468 trace_wave_corrected = cr2res_trace_adjust(trace_wave, raw_flat_frames,
1469 reduce_det) ;
1470 if (trace_wave_corrected != NULL) {
1471 cpl_table_delete(trace_wave) ;
1472 trace_wave = trace_wave_corrected ;
1473 trace_wave_corrected = NULL ;
1474 }
1475 cpl_msg_indent_less() ;
1476 }*/
1477
1478 /* Compute the slit fractions for A and B positions extraction */
1479 cpl_msg_info(__func__, "Compute the slit fractions for A and B positions");
1480 cpl_msg_indent_more() ;
1481 /*
1482 The assumption is made here that :
1483 - The slit center is exactly in the middle of A and B positions
1484 - The nodthrow is the distance in arcseconds between A and B
1485 - The slit size is 10 arcseconds
1486 - The B position is above the A position (--nodding-invert=false)
1487 */
1488 slit_length = 10 ;
1489 if ((plist = cpl_propertylist_load(first_fname, 0)) == NULL) {
1490 cpl_msg_error(__func__, "Cannot read the NODTHROW in the input files") ;
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 nod_throw = cr2res_pfits_get_nodthrow(plist) ;
1498 cpl_propertylist_delete(plist) ;
1499 if (nod_throw < slit_length / 2.0) {
1500 extr_width_frac = nod_throw/slit_length ;
1501 if (nodding_invert == 1) {
1502 slit_frac_a_bot = 0.5 ;
1503 slit_frac_a_mid = slit_frac_a_bot + extr_width_frac/2.0 ;
1504 slit_frac_a_top = slit_frac_a_bot + extr_width_frac ;
1505 slit_frac_b_top = 0.5 ;
1506 slit_frac_b_mid = slit_frac_b_top - extr_width_frac/2.0 ;
1507 slit_frac_b_bot = slit_frac_b_top - extr_width_frac ;
1508 } else {
1509 slit_frac_a_top = 0.5 ;
1510 slit_frac_a_mid = slit_frac_a_top - extr_width_frac/2.0 ;
1511 slit_frac_a_bot = slit_frac_a_top - extr_width_frac ;
1512 slit_frac_b_bot = 0.5 ;
1513 slit_frac_b_mid = slit_frac_b_bot + extr_width_frac/2.0 ;
1514 slit_frac_b_top = slit_frac_b_bot + extr_width_frac ;
1515 }
1516 } else if (nod_throw <= slit_length) {
1517 extr_width_frac = (slit_length - nod_throw)/slit_length ;
1518 if (nodding_invert == 1) {
1519 slit_frac_a_top = 1.0 ;
1520 slit_frac_a_mid = slit_frac_a_top - extr_width_frac/2.0 ;
1521 slit_frac_a_bot = slit_frac_a_top - extr_width_frac ;
1522 slit_frac_b_bot = 0.0 ;
1523 slit_frac_b_mid = slit_frac_b_bot + extr_width_frac/2.0 ;
1524 slit_frac_b_top = slit_frac_b_bot + extr_width_frac ;
1525 } else {
1526 slit_frac_a_bot = 0.0 ;
1527 slit_frac_a_mid = slit_frac_a_bot + extr_width_frac/2.0 ;
1528 slit_frac_a_top = slit_frac_a_bot + extr_width_frac ;
1529 slit_frac_b_top = 1.0 ;
1530 slit_frac_b_mid = slit_frac_b_top - extr_width_frac/2.0 ;
1531 slit_frac_b_bot = slit_frac_b_top - extr_width_frac ;
1532 }
1533 } else {
1534 cpl_msg_error(__func__, "NODTHROW > slit length (%g>%g)- abort",
1535 nod_throw, slit_length) ;
1536 cpl_msg_indent_less() ;
1537 hdrl_image_delete(collapsed_a) ;
1538 hdrl_image_delete(collapsed_b) ;
1539 cpl_table_delete(trace_wave) ;
1540 return -1 ;
1541 }
1542 cpl_msg_info(__func__, "Nod Throw : %g arcsecs", nod_throw) ;
1543 cpl_msg_info(__func__, "Nodding A extraction: Slit fraction %g - %g",
1544 slit_frac_a_bot, slit_frac_a_top) ;
1545 cpl_msg_info(__func__, "Nodding B extraction: Slit fraction %g - %g",
1546 slit_frac_b_bot, slit_frac_b_top) ;
1547
1548 slit_frac_a = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1549 cpl_array_set(slit_frac_a, 0, slit_frac_a_bot) ;
1550 cpl_array_set(slit_frac_a, 1, slit_frac_a_mid) ;
1551 cpl_array_set(slit_frac_a, 2, slit_frac_a_top) ;
1552
1553 slit_frac_b = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1554 cpl_array_set(slit_frac_b, 0, slit_frac_b_bot) ;
1555 cpl_array_set(slit_frac_b, 1, slit_frac_b_mid) ;
1556 cpl_array_set(slit_frac_b, 2, slit_frac_b_top) ;
1557 cpl_msg_indent_less() ;
1558
1559 /* Recompute the traces for the new slit fractions */
1560 cpl_msg_info(__func__, "Recompute the traces for the A slit fraction") ;
1561 if ((trace_wave_a = cr2res_trace_new_slit_fraction(trace_wave,
1562 slit_frac_a)) == NULL) {
1563 cpl_msg_error(__func__,
1564 "Failed to compute the traces for extraction of A") ;
1565 hdrl_image_delete(collapsed_a) ;
1566 hdrl_image_delete(collapsed_b) ;
1567 cpl_table_delete(trace_wave) ;
1568 cpl_array_delete(slit_frac_a) ;
1569 cpl_array_delete(slit_frac_b) ;
1570 return -1 ;
1571 }
1572 cpl_array_delete(slit_frac_a) ;
1573
1574 cpl_msg_info(__func__, "Recompute the traces for the B slit fraction") ;
1575 if ((trace_wave_b = cr2res_trace_new_slit_fraction(trace_wave,
1576 slit_frac_b)) == NULL) {
1577 cpl_msg_error(__func__,
1578 "Failed to compute the traces for extraction of B") ;
1579 hdrl_image_delete(collapsed_a) ;
1580 hdrl_image_delete(collapsed_b) ;
1581 cpl_table_delete(trace_wave) ;
1582 cpl_table_delete(trace_wave_a) ;
1583 cpl_array_delete(slit_frac_b) ;
1584 return -1 ;
1585 }
1586 cpl_array_delete(slit_frac_b) ;
1587
1588 /* Load Blaze */
1589 blaze_table = NULL ;
1590 blaze_norm = 0;
1591 if (blaze_frame != NULL) {
1592 cpl_msg_info(__func__, "Load the BLAZE") ;
1593 if ((blaze_table = cr2res_io_load_EXTRACT_1D(cpl_frame_get_filename(
1594 blaze_frame), reduce_det)) == NULL) {
1595 cpl_msg_error(__func__, "Failed to Load the Blaze file") ;
1596 hdrl_image_delete(collapsed_a) ;
1597 hdrl_image_delete(collapsed_b) ;
1598 cpl_table_delete(trace_wave) ;
1599 cpl_table_delete(trace_wave_a) ;
1600 cpl_table_delete(trace_wave_b) ;
1601 return -1 ;
1602 }
1603 cpl_propertylist * blaze_plist ;
1604 blaze_plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(
1605 blaze_frame),0,CR2RES_HEADER_QC_BLAZE_NORM,0);
1606 if(cpl_propertylist_get_size(blaze_plist)>0){
1607 blaze_norm = cpl_propertylist_get_double(blaze_plist, CR2RES_HEADER_QC_BLAZE_NORM);
1608 }
1609 else {
1610 blaze_norm = -1;
1611 cpl_msg_warning(__func__, "QC BLAZE NORM value not found, reverting to per trace normalization") ;
1612 }
1613 if(blaze_plist!=NULL){
1614 cpl_propertylist_delete(blaze_plist);
1615 }
1616 }
1617
1618 /* Execute the extraction */
1619 cpl_msg_info(__func__, "A position Spectra Extraction") ;
1620 cpl_msg_indent_more() ;
1621 if (cr2res_extract_traces(collapsed_a, trace_wave_a, NULL, blaze_table, blaze_norm, -1,
1622 -1, CR2RES_EXTR_OPT_CURV, extract_height, extract_swath_width,
1623 extract_oversample, extract_pclip, extract_smooth_slit, extract_smooth_spec,
1624 extract_niter, extract_kappa, error_factor,
1625 disp_det==reduce_det, disp_order_idx, disp_trace,
1626 &extracted_a, &slit_func_a, &model_master_a) == -1) {
1627 cpl_msg_error(__func__, "Failed to extract A");
1628 cpl_msg_indent_less() ;
1629 hdrl_image_delete(collapsed_a) ;
1630 hdrl_image_delete(collapsed_b) ;
1631 cpl_table_delete(trace_wave_a) ;
1632 cpl_table_delete(trace_wave_b) ;
1633 cpl_table_delete(trace_wave) ;
1634 return -1 ;
1635 }
1636 cpl_msg_indent_less() ;
1637
1638 cpl_msg_info(__func__, "B position Spectra Extraction") ;
1639 cpl_msg_indent_more() ;
1640 if (cr2res_extract_traces(collapsed_b, trace_wave_b, NULL, blaze_table, blaze_norm, -1,
1641 -1, CR2RES_EXTR_OPT_CURV, extract_height, extract_swath_width,
1642 extract_oversample, extract_pclip, extract_smooth_slit, extract_smooth_spec,
1643 extract_niter, extract_kappa, error_factor,
1644 disp_det==reduce_det, disp_order_idx, disp_trace,
1645 &extracted_b, &slit_func_b, &model_master_b) == -1) {
1646 cpl_msg_error(__func__, "Failed to extract B");
1647 cpl_msg_indent_less() ;
1648 cpl_table_delete(extracted_a) ;
1649 cpl_table_delete(slit_func_a) ;
1650 hdrl_image_delete(model_master_a) ;
1651 hdrl_image_delete(collapsed_a) ;
1652 hdrl_image_delete(collapsed_b) ;
1653 cpl_table_delete(trace_wave_a) ;
1654 cpl_table_delete(trace_wave_b) ;
1655 cpl_table_delete(trace_wave) ;
1656 return -1 ;
1657 }
1658 cpl_msg_indent_less() ;
1659
1660 if (blaze_table != NULL) cpl_table_delete(blaze_table) ;
1661
1662 /* Combine both a and b extracted spectra together */
1663 cpl_msg_info(__func__, "A and B spectra combination") ;
1664 cpl_msg_indent_more() ;
1665 extracted_combined = cr2res_combine_extracted(extracted_a, extracted_b) ;
1666 cpl_msg_indent_less() ;
1667
1668 /* Get the Setting */
1669 plist = cpl_propertylist_load(first_fname, 0) ;
1670 cur_setting = cpl_strdup(cr2res_pfits_get_wlen_id(plist)) ;
1671 cr2res_format_setting(cur_setting) ;
1672 cpl_propertylist_delete(plist) ;
1673
1674 /* Store the extension header for product saving */
1675 plist = cpl_propertylist_load(first_fname,
1676 cr2res_io_get_ext_idx(first_fname, reduce_det, 1)) ;
1677
1678 /* QC - Signal and FWHM */
1679 cpl_msg_info(__func__, "QC parameters computation") ;
1680 qc_signal_a = cr2res_qc_obs_nodding_signal(extracted_a) ;
1681 qc_signal_b = cr2res_qc_obs_nodding_signal(extracted_b) ;
1682 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SIGNAL,
1683 (qc_signal_a+qc_signal_b)/2.0) ;
1684
1685 /* QC STANDARD FLUX */
1686 qc_standard_flux_a =
1687 cr2res_qc_obs_nodding_standard_flux(extracted_a, cur_setting) ;
1688 qc_standard_flux_b =
1689 cr2res_qc_obs_nodding_standard_flux(extracted_b, cur_setting) ;
1690 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_STANDARD_FLUX,
1691 (qc_standard_flux_a+qc_standard_flux_b)/2.0) ;
1692 cpl_free(cur_setting) ;
1693
1694 /* QC - SNR on nodding A position */
1695 qc_snrs = cr2res_qc_snr(trace_wave_a, extracted_a, &order_idx_values,
1696 &nb_order_idx_values) ;
1697 qc_der_snrs = cr2res_qc_der_snr(trace_wave_a, extracted_a, &order_idx_values_der,
1698 &nb_order_idx_values_der) ;
1699 for (i=0 ; i<nb_order_idx_values ; i++) {
1700 order_idx = order_idx_values[i] ;
1701 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
1702 key_name = cpl_sprintf(CR2RES_HEADER_QC_SNR, order_idxp) ;
1703 cpl_propertylist_append_double(plist, key_name, qc_snrs[i]) ;
1704 cpl_free(key_name) ;
1705 key_name = cpl_sprintf(CR2RES_HEADER_QC_DER_SNR, order_idxp) ;
1706 cpl_propertylist_append_double(plist, key_name, qc_der_snrs[i]) ;
1707 cpl_free(key_name) ;
1708 }
1709 cpl_free(order_idx_values) ;
1710 cpl_free(order_idx_values_der) ;
1711 cpl_free(qc_snrs) ;
1712 cpl_free(qc_der_snrs) ;
1713
1714 /* Get the order numbers from the TW rows */
1715 order_idx_values = cr2res_trace_get_order_idx_values(trace_wave,
1716 &nb_order_idx_values);
1717
1718 /* QC - SLIT FWHM */
1719 fwhm_a_array = cpl_array_new(nb_order_idx_values, CPL_TYPE_DOUBLE);
1720 fwhm_b_array = cpl_array_new(nb_order_idx_values, CPL_TYPE_DOUBLE);
1721 for (i=0 ; i<nb_order_idx_values ; i++) {
1722 order_idx = order_idx_values[i] ;
1723 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
1724 qc_fwhm_a = cr2res_qc_obs_slit_psf(slit_func_a, order_idxp,
1725 extract_oversample);
1726 qc_fwhm_b = cr2res_qc_obs_slit_psf(slit_func_b, order_idxp,
1727 extract_oversample);
1728
1729 key_name = cpl_sprintf(CR2RES_HEADER_QC_SLITFWHM_ORDER, order_idxp) ;
1730 cpl_propertylist_append_double(plist, key_name,
1731 (qc_fwhm_a+qc_fwhm_b)/2.0) ;
1732 cpl_free(key_name) ;
1733 cpl_array_set(fwhm_a_array, i, qc_fwhm_a) ;
1734 cpl_array_set(fwhm_b_array, i, qc_fwhm_b) ;
1735 }
1736 qc_fwhm_a = cpl_array_get_median(fwhm_a_array);
1737 qc_fwhm_b = cpl_array_get_median(fwhm_b_array);
1738 qc_fwhm_med = (qc_fwhm_a+qc_fwhm_b)/2.0 ;
1739 cpl_propertylist_append_double(plist, CR2RES_HEADER_QC_SLITFWHM_MED,
1740 qc_fwhm_med) ;
1741 if (qc_fwhm_med < 3.5) {
1742 cpl_msg_warning(__func__, "Median FWHM of the PSF along the slit "
1743 "is %gpix, i.e. below the slit width. This means the slit "
1744 "is likely not evenly filled with light "
1745 "in the spectral direction. This can result in a "
1746 "wavelength offset between A and B nodding positions, and with "
1747 "respect to calibrations."
1748 , qc_fwhm_med);
1749 }
1750 cpl_array_delete(fwhm_a_array) ;
1751 cpl_array_delete(fwhm_b_array) ;
1752
1753 /* QC - Real Orders */
1754 if (order_zp > 0) {
1755 /* Compute the Real Order numbers and store them in QCs */
1756 for (i = 0; i < nb_order_idx_values; i++) {
1757 int order_real;
1758 order_idx = order_idx_values[i] ;
1759 order_idxp = cr2res_io_convert_order_idx_to_idxp(order_idx) ;
1760
1761 order_real = cr2res_order_idx_to_real(order_idx, order_zp) ;
1762 key_name = cpl_sprintf(CR2RES_HEADER_QC_REAL_ORDER, order_idxp) ;
1763 cpl_propertylist_append_int(plist, key_name, order_real) ;
1764 cpl_free(key_name) ;
1765 }
1766 }
1767 cpl_table_delete(trace_wave) ;
1768 cpl_free(order_idx_values) ;
1769
1770 /* Return */
1771 *combineda = collapsed_a ;
1772 *extracta = extracted_a ;
1773 *slitfunca = slit_func_a ;
1774 *modela = model_master_a ;
1775 *twa = trace_wave_a ;
1776
1777 *combinedb = collapsed_b ;
1778 *extractb = extracted_b ;
1779 *slitfuncb = slit_func_b ;
1780 *modelb = model_master_b ;
1781 *twb = trace_wave_b ;
1782
1783 *extractc = extracted_combined ;
1784 *ext_plist = plist ;
1785
1786 return 0 ;
1787}
1788
1789/*----------------------------------------------------------------------------*/
1795/*----------------------------------------------------------------------------*/
1796static int cr2res_obs_nodding_check_inputs_validity(
1797 const cpl_frameset * rawframes)
1798{
1799 cpl_propertylist * plist ;
1800 cr2res_nodding_pos * nod_positions ;
1801 cpl_size nframes, i ;
1802 double nodthrow;
1803 int nb_a, nb_b ;
1804
1805 /* Check Inputs */
1806 if (rawframes == NULL) return -1 ;
1807
1808 /* Need even number of frames */
1809 nframes = cpl_frameset_get_size(rawframes) ;
1810 if (nframes % 2) {
1811 cpl_msg_error(__func__, "Require an even number of raw frames") ;
1812 return 0 ;
1813 }
1814
1815 /* Need same number of A and B positions */
1816 nb_a = nb_b = 0 ;
1817 nod_positions = cr2res_nodding_read_positions(rawframes) ;
1818 if (nod_positions == NULL) return -1 ;
1819 for (i=0 ; i<nframes ; i++) {
1820 if (nod_positions[i] == CR2RES_NODDING_A) nb_a++ ;
1821 if (nod_positions[i] == CR2RES_NODDING_B) nb_b++ ;
1822 }
1823 cpl_free(nod_positions) ;
1824
1825 if (nb_a == 0 || nb_b == 0 || nb_a != nb_b) {
1826 cpl_msg_error(__func__, "Require as many A and B positions") ;
1827 return 0 ;
1828 }
1829
1830 /* Need the same nod throw in all frames */
1831 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(
1832 cpl_frameset_get_position_const(rawframes, 0)),
1833 0)) == NULL) {
1834 return -1;
1835 }
1836 nodthrow = cr2res_pfits_get_nodthrow(plist);
1837 cpl_propertylist_delete(plist) ;
1838 for (i = 1; i < nframes; i++) {
1839 double nodthrow_cur;
1840 if ((plist = cpl_propertylist_load(cpl_frame_get_filename(
1841 cpl_frameset_get_position_const(rawframes, i)),
1842 0)) == NULL) {
1843 return -1;
1844 }
1845 nodthrow_cur = cr2res_pfits_get_nodthrow(plist);
1846 cpl_propertylist_delete(plist) ;
1847
1848 if (fabs(nodthrow_cur-nodthrow) > 1e-3) {
1849 cpl_msg_error(__func__,
1850 "Require constant NOD THROW in the raw frames") ;
1851 return 0 ;
1852 }
1853 }
1854 return 1 ;
1855}
1856
1857/*----------------------------------------------------------------------------*/
1873/*----------------------------------------------------------------------------*/
1874static cpl_frameset * cr2res_obs_nodding_find_RAW(
1875 const cpl_frameset * in,
1876 int * type)
1877{
1878 cpl_frameset * out ;
1879
1880 /* Check entries */
1881 if (in == NULL) return NULL ;
1882
1883 out = cr2res_extract_frameset(in, CR2RES_OBS_NODDING_OTHER_RAW) ;
1884 if (out == NULL) {
1885 out = cr2res_extract_frameset(in, CR2RES_OBS_NODDING_JITTER_RAW) ;
1886 }
1887 if (out != NULL) {
1888 if (type != NULL) *type = 1 ;
1889 } else {
1890 out = cr2res_extract_frameset(in, CR2RES_CAL_NODDING_OTHER_RAW) ;
1891 if (out == NULL) {
1892 out = cr2res_extract_frameset(in, CR2RES_CAL_NODDING_JITTER_RAW) ;
1893 }
1894 if (out != NULL) {
1895 if (type != NULL) *type = 2 ;
1896 } else {
1897 out = cr2res_extract_frameset(in, CR2RES_OBS_ASTROMETRY_OTHER_RAW) ;
1898 if (out == NULL) {
1899 out = cr2res_extract_frameset(in,
1900 CR2RES_OBS_ASTROMETRY_JITTER_RAW) ;
1901 }
1902 if (out != NULL) {
1903 if (type != NULL) *type = 3 ;
1904 }
1905 }
1906 }
1907 if (out == NULL) {
1908 if (type != NULL) *type = 0 ;
1909 }
1910 return out ;
1911}
1912
1913/*----------------------------------------------------------------------------*/
1920/*----------------------------------------------------------------------------*/
1921static int cr2res_obs_nodding_astrometry_compare(
1922 const cpl_frame * frame1,
1923 const cpl_frame * frame2)
1924{
1925 int comparison ;
1926 cpl_propertylist * plist1 ;
1927 cpl_propertylist * plist2 ;
1928 double dval1, dval2 ;
1929
1930 /* Test entries */
1931 if (frame1==NULL || frame2==NULL) return -1 ;
1932
1933 /* Get property lists */
1934 if ((plist1=cpl_propertylist_load(cpl_frame_get_filename(frame1),0))==NULL){
1935 cpl_msg_error(__func__, "getting header from reference frame");
1936 return -1 ;
1937 }
1938 if ((plist2=cpl_propertylist_load(cpl_frame_get_filename(frame2),0))==NULL){
1939 cpl_msg_error(__func__, "getting header from reference frame");
1940 cpl_propertylist_delete(plist1) ;
1941 return -1 ;
1942 }
1943
1944 /* Test status */
1945 if (cpl_error_get_code()) {
1946 cpl_propertylist_delete(plist1) ;
1947 cpl_propertylist_delete(plist2) ;
1948 return -1 ;
1949 }
1950
1951 comparison = 1 ;
1952
1953 /* Compare the DROT angle used */
1954 dval1 = cr2res_pfits_get_drot_posang(plist1) ;
1955 dval2 = cr2res_pfits_get_drot_posang(plist2) ;
1956 if (cpl_error_get_code()) {
1957 cpl_msg_error(__func__, "Cannot get the angle");
1958 cpl_propertylist_delete(plist1) ;
1959 cpl_propertylist_delete(plist2) ;
1960 return -1 ;
1961 }
1962 if (fabs(dval1-dval2) > 1e-3) comparison = 0 ;
1963
1964 cpl_propertylist_delete(plist1) ;
1965 cpl_propertylist_delete(plist2) ;
1966 return comparison ;
1967}
1968
1969
cpl_image * cr2res_calib_flat_relerr2(const hdrl_image *mflat)
Squared relative error of a master flat, (sigma_F/F)^2.
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, const cpl_vector *ndsamples)
The images calibration routine for a given chip on a list.
int cr2res_calib_dark_var(hdrl_imagelist *list, const cpl_frame *master_dark_frame, int chip, const hdrl_image *mflat, const cpl_vector *dits, double sign)
Add or remove the master dark variance of cr2res_calib_image()
void cr2res_calib_flat_var(hdrl_image *ima, const cpl_image *relerr2, double sign)
Add or remove the flat-field variance term of an image.
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:1326
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:1853
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
cpl_vector * cr2res_io_read_ndsamples(const cpl_frameset *in)
Get the NDSAMPLES from a frame set.
Definition cr2res_io.c:492
int cr2res_io_convert_order_idx_to_idxp(int order_idx)
Convert the order_idx to the order_idxp.
Definition cr2res_io.c:613
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:1700
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:1762
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:838
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:1792
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:674
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:1822
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:1884
cpl_table * cr2res_io_load_TRACE_WAVE(const char *filename, int detector)
Load a table from a TRACE_WAVE.
Definition cr2res_io.c:1139
cpl_vector * cr2res_io_read_ndits(const cpl_frameset *in)
Get the NDITs from a frame set.
Definition cr2res_io.c:462
hdrl_image * cr2res_io_load_MASTER_FLAT(const char *filename, int detector)
Load an hdrl image from a MASTER_FLAT.
Definition cr2res_io.c:1096
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.
Definition cr2res_qc.c:1299
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:1105
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:1210
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
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.
hdrl_image * hdrl_imagelist_get(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.