IIINSTRUMENT Pipeline Reference Manual 4.6.1
visir_spc_obs.c
1/* $Id: visir_spc_obs.c,v 1.111 2013-05-13 16:04:49 jtaylor Exp $
2 *
3 * This file is part of the VISIR Pipeline
4 * Copyright (C) 2002,2003,2012 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-05-13 16:04:49 $
24 * $Revision: 1.111 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35#include "cxlist.h"
36
37#include "visir_inputs.h"
38#include "visir_recipe.h"
39#include "visir_spectro.h"
40#include "visir_spc_distortion.h"
41#include "visir_spc_photom.h"
42
43
44/*-----------------------------------------------------------------------------
45 Defines
46 -----------------------------------------------------------------------------*/
47
48#define RECIPE_STRING "visir_old_spc_obs"
49/* still used by chain recipe internally, so keep name for output */
50#define RECIPE_SAVE_STRING "visir_spc_obs"
51
52/* FITS keys to be loaded for all raw files */
53#define RECIPE_KEYS_REGEXP_ALL \
54 VISIR_PFITS_REGEXP_IMG_RECOMBINE \
55 "|" VISIR_PFITS_REGEXP_SPC_GET_RES_WL
56
57/* FITS keys to be loaded for first raw file */
58#define RECIPE_KEYS_REGEXP \
59 RECIPE_KEYS_REGEXP_ALL \
60 "|" VISIR_PFITS_REGEXP_CAPA \
61 "|" VISIR_PFITS_REGEXP_SPC_WCAL_PAF
62
63/* FITS keys to be loaded for first raw file, in case WCS is used */
64#define RECIPE_KEYS_REGEXP_WCS \
65 RECIPE_KEYS_REGEXP \
66 "|" IRPLIB_PFITS_WCS_REGEXP
67
68#define IS_PREPROCESSED 1
69#define IS_PHOT 2
70#define IS_ECH 4
71#define RAW_INPUT 0
72#define PREPROCESSED_INPUT IS_PREPROCESSED
73#define RAW_PHOT_INPUT IS_PHOT
74#define PREPROCESSED_PHOT_INPUT (IS_PHOT | IS_PREPROCESSED)
75
76/* the number of orders we try to extract */
77#define MAX_ORDERS 9
78
79/* a flag value used to indicate an unused order in the data structures */
80#define UNUSED_ORDER 99
81
82#define MSG_WARN(...) cpl_msg_warning(cpl_func, __VA_ARGS__)
83#define MSG_INFO(...) cpl_msg_info(cpl_func, __VA_ARGS__)
84#define MSG_ERR(...) cpl_msg_error(cpl_func, __VA_ARGS__)
85#define MSG_DBG(...) cpl_msg_debug(cpl_func, __VA_ARGS__)
86
87/*-----------------------------------------------------------------------------
88 Typedefs
89 -----------------------------------------------------------------------------*/
90/* possibly more than 1 of these per order */
91typedef struct {
92 int extract; /* The extraction status (UNUSED_ORDER =
93 * failed, anything else = succeeded) */
94 cpl_image * weight2d; /* The 2D weight images */
95 cpl_table * spc_tbl; /* The extracted spectrum */
96 cpl_propertylist * qclist; /* The QC properties */
97 visir_apdefs * aps; /* The matching aperture definition */
98} match;
99
100typedef struct {
101 size_t sz; /* The number of items in the list */
102 match* data; /* The list of items */
103} matchlist;
104
105static void match_delete(match m);
106static matchlist* matchlist_new(size_t sz);
107static void matchlist_delete(matchlist * ml);
108
109typedef struct {
110 int cutout; /* The order offset, which is +/-4 from the
111 * central order, doubling as cutout status
112 * (UNUSED_ORDER = failed, anything else =
113 * succeeded) */
114 cpl_image * comnarrow; /* The saved image cutout, per order */
115 matchlist * matches;
116 visir_aplist * aplist;
117} order;
118
119typedef struct {
120 size_t sz; /* The number of items in the list */
121 order* data; /* The list of items */
122} orderlist;
123
124static void order_delete(order o);
125static orderlist* orderlist_new(size_t sz);
126static void orderlist_delete(orderlist * ol);
127
128/*-----------------------------------------------------------------------------
129 Private Functions prototypes
130 -----------------------------------------------------------------------------*/
131static cpl_error_code visir_spc_obs_save(cpl_frameset *,
132 const cpl_parameterlist *,
133 cpl_propertylist *,
134 cpl_propertylist *,
135 const cpl_propertylist *,
136 const cpl_image *,
137 const cpl_table *,
138 const cpl_image *,
139 const char *,
140 const int, const int, const size_t);
141
142static cpl_error_code visir_spc_obs_extend(cpl_propertylist *,
143 const cpl_image *,
144 const cpl_table *,
145 const cpl_image *,
146 const int, const int, const size_t);
147
148static cpl_error_code visir_spc_obs_extend_combined(const cpl_image *);
149
150static cpl_error_code visir_spc_qc_summarise(cpl_propertylist *, orderlist *,
151 const char *);
152
153#ifdef VISIR_CHAIN
154#define cpl_plugin_get_info visir_old_spc_obs_get_info
155#endif
156VISIR_RECIPE_DEFINE(visir_old_spc_obs,
157 VISIR_PARAM_EMIS_TOL |
158 VISIR_PARAM_REFINE | VISIR_PARAM_XCORR |
159 VISIR_PARAM_OFFSETS | VISIR_PARAM_OBJECTS |
160 VISIR_PARAM_NODPOS | VISIR_PARAM_AUTOBPM |
161 VISIR_PARAM_GLITCH | VISIR_PARAM_PURGE |
162 VISIR_PARAM_UNION | VISIR_PARAM_REJECT |
163 VISIR_PARAM_STRIPITE | VISIR_PARAM_STRIPMOR |
164 VISIR_PARAM_PLOT | VISIR_PARAM_SLITSKEW |
165 VISIR_PARAM_SPECSKEW | VISIR_PARAM_VERTARC |
166 VISIR_PARAM_REJLEFT | VISIR_PARAM_REJRIGHT |
167 VISIR_PARAM_HORIARC | VISIR_PARAM_FIXCOMBI |
168 VISIR_PARAM_BKG_CORRECT | VISIR_PARAM_APERT_FILE |
169 VISIR_PARAM_GAIN | VISIR_PARAM_RONOISE |
170 VISIR_PARAM_OXSIGMA | VISIR_PARAM_OXNITER |
171 VISIR_PARAM_OXSMOOTH | VISIR_PARAM_OXKERNEL |
172 VISIR_PARAM_RESPCAL,
173 "Old DRS detector: Spectroscopic Observation recipe",
174 "This recipe estimates the dispersion relation using the "
175 "atmospheric spectrum\n"
176 "in a long-slit spectroscopy half-cycle frame.\n"
177 "It also extracts the spectrum of an observed object using "
178 "a combined frame.\n"
179 "The files listed in the Set Of Frames (sof-file) "
180 "must be tagged:\n"
181 "VISIR-Long-Slit-Spectroscopy-file.fits "
182 VISIR_SPC_OBS_RAW "\n"
183 "VISIR-Quantum-Efficiency-Calibration-file.fits "
184 VISIR_CALIB_QEFF_SPC "\n"
185 "VISIR-Atmospheric-Emission-Lines-Calibration-file.fits "
186 VISIR_CALIB_LINES_SPC
187 "\n"
188 MAN_VISIR_CALIB_BPM_SPC);
189
190/*-----------------------------------------------------------------------------
191 Static variables
192 -----------------------------------------------------------------------------*/
193
194/*----------------------------------------------------------------------------*/
198/*----------------------------------------------------------------------------*/
199
200/*-----------------------------------------------------------------------------
201 Functions code
202 -----------------------------------------------------------------------------*/
203
204static void biimage_delete(cpl_image ** bi)
205{
206 if (!bi) return;
207 cpl_image_delete(bi[0]);
208 cpl_image_delete(bi[1]);
209 cpl_free(bi);
210}
211
212static void match_delete(match m)
213{
214 cpl_propertylist_delete(m.qclist);
215 // original algorithm apertures (with negative ident) are the only ones
216 // owned, hence are the only ones that need to be freed: the rest are just
217 // references into other owning structs
218 if (m.aps->ident < 0) visir_apdefs_delete(m.aps);
219 cpl_table_delete(m.spc_tbl);
220 cpl_image_delete(m.weight2d);
221}
222
223static matchlist* matchlist_new(size_t sz)
224{
225 matchlist* ml = cpl_malloc(sizeof(matchlist));
226 ml->sz = sz;
227 ml->data = cpl_calloc(sz, sizeof(match));
228 return ml;
229}
230
231static void matchlist_delete(matchlist * ml)
232{
233 if (!ml) return;
234 for (size_t i = 0; i < ml->sz; ++i) {
235 match_delete(ml->data[i]);
236 }
237 cpl_free(ml->data);
238 cpl_free(ml);
239}
240
241static void order_delete(order o)
242{
243 cpl_image_delete(o.comnarrow);
244 visir_aplist_delete(o.aplist); // free list only (elems are just refs)
245 matchlist_delete(o.matches);
246}
247
248static orderlist* orderlist_new(size_t sz)
249{
250 orderlist* ol = cpl_malloc(sizeof(orderlist));
251 ol->sz = sz;
252 ol->data = cpl_calloc(sz, sizeof(order));
253 return ol;
254}
255
256static void orderlist_delete(orderlist * ol)
257{
258 if (!ol) return;
259 for (size_t i = 0; i < ol->sz; ++i) {
260 order_delete(ol->data[i]);
261 }
262 cpl_free(ol->data);
263 cpl_free(ol);
264}
265
266/*----------------------------------------------------------------------------*/
273/*----------------------------------------------------------------------------*/
274static const char * pn(const int oo)
275{
276 static char buf[80]; // FIXME: don't use static vars
277 const char * sign = oo ? (oo > 0 ? "+" : "-") : "";
278 snprintf(buf, sizeof(buf), "%s%d", sign, abs(oo));
279 return buf;
280}
281
282/*----------------------------------------------------------------------------*/
289/*----------------------------------------------------------------------------*/
290static void * visir_old_spc_obs_(cpl_frameset * framelist,
291 const cpl_parameterlist * parlist)
292{
293 cpl_propertylist* phu = NULL;
294 visir_aplist* aplist = NULL;
295 cpl_image* combined = NULL;
296 cpl_image* imhcycle = NULL;
297 cpl_image** combinedpair = NULL;
298 cpl_propertylist* paflist = NULL;
299 orderlist* orders = NULL;
300 irplib_framelist* raws = NULL;
301 irplib_framelist* all = NULL;
302
303 visir_spc_config spc_config;
304 spc_config.recipename = RECIPE_STRING;
305 spc_config.parlist = parlist;
306 spc_config.phot_emis_tol = 1.0;
307
308 /* Initialise the QC property lists */
309 phu = cpl_propertylist_new();
310 spc_config.phu = phu;
311
312 /* Retrieve input parameters */
313 spc_config.plot = visir_parameterlist_get_int(
314 parlist, RECIPE_STRING, VISIR_PARAM_PLOT);
315 spc_config.phi = visir_parameterlist_get_double(
316 parlist, RECIPE_STRING, VISIR_PARAM_SLITSKEW);
317 spc_config.ksi = visir_parameterlist_get_double(
318 parlist, RECIPE_STRING, VISIR_PARAM_SPECSKEW);
319 spc_config.eps = visir_parameterlist_get_double(
320 parlist, RECIPE_STRING, VISIR_PARAM_VERTARC);
321 spc_config.delta = visir_parameterlist_get_double(
322 parlist, RECIPE_STRING, VISIR_PARAM_HORIARC);
323 spc_config.gain = visir_parameterlist_get_double(
324 parlist, RECIPE_STRING, VISIR_PARAM_GAIN);
325 spc_config.ron = visir_parameterlist_get_double(
326 parlist, RECIPE_STRING, VISIR_PARAM_RONOISE);
327 spc_config.ox_sigma = visir_parameterlist_get_double(
328 parlist, RECIPE_STRING, VISIR_PARAM_OXSIGMA);
329 spc_config.ox_niters = visir_parameterlist_get_int(
330 parlist, RECIPE_STRING, VISIR_PARAM_OXNITER);
331 spc_config.ox_smooth = visir_parameterlist_get_int(
332 parlist, RECIPE_STRING, VISIR_PARAM_OXSMOOTH);
333 spc_config.ox_kernel = visir_parameterlist_get_int(
334 parlist, RECIPE_STRING, VISIR_PARAM_OXKERNEL);
335 spc_config.do_fixcombi = visir_parameterlist_get_bool(
336 parlist, RECIPE_STRING, VISIR_PARAM_FIXCOMBI);
337 spc_config.phot_emis_tol = visir_parameterlist_get_double(
338 parlist, RECIPE_STRING, VISIR_PARAM_EMIS_TOL);
339 spc_config.bkgcorrect = visir_parameterlist_get_bool(
340 parlist, RECIPE_STRING, VISIR_PARAM_BKG_CORRECT);
341 spc_config.respcal = visir_parameterlist_get_string(
342 parlist, RECIPE_STRING, VISIR_PARAM_RESPCAL);
343
344 skip_if (0);
345
346 char const * const apfile = visir_parameterlist_get_string(
347 parlist, RECIPE_STRING, VISIR_PARAM_APERT_FILE);
348 // re-enable this if it is an error to extract without sky-subtraction
349 //if (!visir_str_par_is_empty(apfile) && !spc_config.bkgcorrect)
350 // return ERR(CPL_ERROR_INCOMPATIBLE_INPUT,
351 // "--bkgcorrect must be true when using --apfile=...");
352
353 // parse apfile into a list of apertures
354 if (visir_str_par_is_empty(apfile))
355 aplist = visir_aplist_new();
356 else {
357 aplist = visir_aplist_new_from_file(apfile);
358 }
359
360 skip_if (0);
361
366 //FOR_EACH_T(visir_apdefs const * const aps, aplist->o) {
367 // SET(line, char, v, cpl_free) = visir_apdefs_dump _(aps);
368 // SET(key, char, v, cpl_free) = cpl_sprintf _("ESO DRS APDEF%d", aps->ident);
369 // cpl_propertylist_append_string _(phu->o, key->o, line->o);
370 //}
371
372 /* Identify the RAW and CALIB frames in the input frameset */
373 visir_dfs_set_groups(framelist);
374
375 skip_if (0);
376
377 /* Objects observation */
378 all = irplib_framelist_cast(framelist);
379 char const * const inraw = "Input: raw %s frame (%s)";
380 char const * const inprep = "Input: preprocessed %s frame (%s)";
381
382 int input_mode;
383 const char * rawtag;
384 if (irplib_frameset_find_file(framelist, VISIR_SPC_OBS_PP)) {
385 raws = irplib_framelist_extract(all, VISIR_SPC_OBS_PP);
386 rawtag = VISIR_SPC_OBS_PP;
387 MSG_INFO(inprep, "observation", VISIR_SPC_OBS_PP);
388 input_mode = PREPROCESSED_INPUT;
389 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_PHOT_PP)) {
390 raws = irplib_framelist_extract(all, VISIR_SPC_PHOT_PP);
391 rawtag = VISIR_SPC_PHOT_PP;
392 MSG_INFO(inprep, "photometric", VISIR_SPC_PHOT_PP);
393 input_mode = PREPROCESSED_PHOT_INPUT;
394 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_OBS_ECH_PP)) {
395 raws = irplib_framelist_extract(all, VISIR_SPC_OBS_ECH_PP);
396 rawtag = VISIR_SPC_OBS_ECH_PP;
397 MSG_INFO(inprep, "observation echelle", VISIR_SPC_OBS_ECH_PP);
398 input_mode = PREPROCESSED_INPUT | IS_ECH;
399 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_PHOT_ECH_PP)) {
400 raws = irplib_framelist_extract(all, VISIR_SPC_PHOT_ECH_PP);
401 rawtag = VISIR_SPC_PHOT_ECH_PP;
402 MSG_INFO(inprep, "photometric echelle", VISIR_SPC_PHOT_ECH_PP);
403 input_mode = PREPROCESSED_PHOT_INPUT | IS_ECH;
404 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_OBS_RAW)) {
405 raws = irplib_framelist_extract(all, VISIR_SPC_OBS_RAW);
406 rawtag = VISIR_SPC_OBS_RAW;
407 MSG_INFO(inraw, "observation", VISIR_SPC_OBS_RAW);
408 input_mode = RAW_INPUT;
409 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_PHOT_RAW)) {
410 raws = irplib_framelist_extract(all, VISIR_SPC_PHOT_RAW);
411 rawtag = VISIR_SPC_PHOT_RAW;
412 MSG_INFO(inraw, "photometric", VISIR_SPC_PHOT_RAW);
413 input_mode = RAW_PHOT_INPUT;
414 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_OBS_ECH_RAW)) {
415 raws = irplib_framelist_extract(all, VISIR_SPC_OBS_ECH_RAW);
416 rawtag = VISIR_SPC_OBS_ECH_RAW;
417 MSG_INFO(inraw, "observation echelle", VISIR_SPC_OBS_ECH_RAW);
418 input_mode = RAW_INPUT | IS_ECH;
419 } else if (irplib_frameset_find_file(framelist, VISIR_SPC_PHOT_ECH_RAW)) {
420 raws = irplib_framelist_extract(all, VISIR_SPC_PHOT_ECH_RAW);
421 rawtag = VISIR_SPC_PHOT_ECH_RAW;
422 MSG_INFO(inraw, "photometric echelle", VISIR_SPC_PHOT_ECH_RAW);
423 input_mode = RAW_PHOT_INPUT | IS_ECH;
424 } else {
425 cpl_msg_error(cpl_func, "Input frame set must contain "
426 "frame(s) tagged as one of: " VISIR_SPC_OBS_RAW ", "
427 VISIR_SPC_PHOT_RAW ", " VISIR_SPC_OBS_PP ","
428 VISIR_SPC_PHOT_PP "," VISIR_SPC_OBS_ECH_RAW ","
429 VISIR_SPC_OBS_ECH_PP "," VISIR_SPC_PHOT_ECH_RAW ","
430 VISIR_SPC_PHOT_ECH_PP);
431 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
432 }
433
434 skip_if (0);
435
436 cpl_size const nframes = irplib_framelist_get_size(raws);
437
438 irplib_framelist_load_propertylist_all(raws, 0, "^("
439 VISIR_PFITS_REGEXP_SPC_SENSIT
440 "|" RECIPE_KEYS_REGEXP_ALL
441 "|" RECIPE_KEYS_REGEXP_WCS
442 "|" VISIR_PFITS_REGEXP_DIT
443 "|" VISIR_PFITS_DOUBLE_WLEN
444 "|" VISIR_PFITS_DOUBLE_PWLEN
445 "|" "ESO DRS .*"
446 "|" "ESO PRO DATANCOM"
447 "|" "ESO QC EXPTIME"
448 "|" "ESO QC EXECTIME"
449 "|" "ESO QC BACKGD MEAN"
450 ")$", CPL_FALSE);
451
453
454 skip_if (0);
455
456 cpl_propertylist const * const pl =
457 irplib_framelist_get_propertylist_const(raws, 0);
458 int const has_seq = cpl_propertylist_has(pl, VISIR_PFITS_DOUBLE_SEQ1_DIT);
459 char const * const dit_key = has_seq ? VISIR_PFITS_DOUBLE_SEQ1_DIT
460 : VISIR_PFITS_DOUBLE_DIT;
461
462 /* Standard star catalog */
463 char const * const star_cat =
464 irplib_frameset_find_file(framelist, VISIR_CALIB_STDSTAR_SPC);
465 if ((input_mode & IS_PHOT) && star_cat == NULL) {
466 cpl_msg_error(cpl_func, "Frame set with a photometric frame (%s) "
467 "must include a standard star catalogue ("
468 VISIR_CALIB_STDSTAR_SPC ")", rawtag);
469 cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
470 }
471
472 skip_if (0);
473
474 visir_data_type data_type;
475 cpl_frame const * const frm = irplib_framelist_get_const(raws, 0);
476 visir_get_data_type(frm, pl, &data_type, NULL);
477
478 skip_if (0);
479
480 if (visir_data_is_drs(data_type)) {
481 /* if parameters are (aqu) defaults and drs data use old parameters */
482 double tmp;
483 cpl_parameter const * par = cpl_parameterlist_find_const(
484 parlist, PACKAGE "." RECIPE_STRING ".ksi");
485 tmp = cpl_parameter_get_default_double(par);
486 if (spc_config.ksi == tmp * CPL_MATH_RAD_DEG)
487 spc_config.ksi = VISIR_DRS_DIST_KSI;
488
489 par = cpl_parameterlist_find_const(
490 parlist, PACKAGE "." RECIPE_STRING ".eps");
491 tmp = cpl_parameter_get_default_double(par);
492 if (spc_config.eps == tmp) spc_config.eps = VISIR_DRS_DIST_EPS;
493
494 par = cpl_parameterlist_find_const(
495 parlist, PACKAGE "." RECIPE_STRING ".delta");
496 tmp = cpl_parameter_get_default_double(par);
497 if (spc_config.delta == tmp) spc_config.delta = VISIR_DRS_DIST_DELTA;
498
499 par = cpl_parameterlist_find_const(
500 parlist, PACKAGE "." RECIPE_STRING ".phi");
501 tmp = cpl_parameter_get_default_double(par);
502 if (spc_config.phi == tmp * CPL_MATH_RAD_DEG)
503 spc_config.phi = VISIR_DRS_DIST_PHI;
504 }
505
506 skip_if (0);
507
508 /* Quantum efficiency file */
509 char const * const spc_cal_qeff =
510 irplib_frameset_find_file(framelist, VISIR_CALIB_QEFF_SPC);
511
512 /* Spectral lines calibration file */
513 char const * const spc_cal_lines =
514 irplib_frameset_find_file(framelist, VISIR_CALIB_LINES_SPC);
515
516 /* Bad pixels calibration file */
517 char const * const badpix =
518 irplib_frameset_find_file(framelist, VISIR_CALIB_BPM);
519
520 /* Flatfield calibration file */
521 char const * const flat =
522 irplib_frameset_find_file(framelist, VISIR_CALIB_FLAT);
523
524 /* Get Resolution and Central Wavelength */
525 double wlen, slitw, temp, fwhm;
526 visir_spc_resol resol = visir_spc_get_res_wl(raws, &wlen, &slitw,
527 &temp, &fwhm, visir_data_is_aqu(data_type));
528
529 skip_if (0);
530
531 /* The number of orders currently in use */
532 int n_orders = 1;
533 if (resol == VISIR_SPC_R_GHR) {
534 if (!(input_mode & IS_ECH) && !(input_mode & IS_PREPROCESSED)) {
535 cpl_msg_error(cpl_func, "Will not reduce echelle data "
536 "tagged as long slit data");
537 cpl_error_set(cpl_func, CPL_ERROR_TYPE_MISMATCH);
538 }
539 n_orders = MAX_ORDERS; // try to extract all orders
540 } else {
541 MSG_WARN("Reducing non-HR Grism data as main order");
542 }
543
544 skip_if (0);
545
546 cpl_boolean drop_wcs;
547
548 if (input_mode & IS_PREPROCESSED) {
549 const cpl_propertylist** plists = cpl_malloc(
550 nframes * sizeof(cpl_propertylist *));
551 double bg_sum = 0;
552
553 cpl_imagelist* imagelist = cpl_imagelist_new();
554 for (cpl_size i = 0; i < nframes; i++) {
555 cpl_frame const * const frame = irplib_framelist_get(raws, i);
556 char const * const fname = cpl_frame_get_filename(frame);
557 cpl_size const next = cpl_fits_count_extensions(fname);
558
559 plists[i] = irplib_framelist_get_propertylist_const(raws,i);
560 if (cpl_propertylist_has(plists[i], "ESO QC BACKGD MEAN")) {
561 bg_sum += cpl_propertylist_get_double(plists[i],
562 "ESO QC BACKGD MEAN");
563 }
564
565 cpl_imagelist* tmplist = cpl_imagelist_new();
566 for (cpl_size j = 0; j < 1 + next; j++) {
567 cpl_image* img = cpl_image_load(fname,
568 CPL_TYPE_UNSPECIFIED, 0, j);
569 if (cpl_error_get_code()) {
570 cpl_error_reset();
571 cpl_msg_info(cpl_func, "No image in extension %d", (int)j);
572 cpl_image_delete(img);
573 continue;
574 }
575 cpl_image_reject_value(img, CPL_VALUE_NAN);
576 cpl_size const lsz = cpl_imagelist_get_size(tmplist);
577 cpl_imagelist_set(tmplist, img, lsz);
578 }
579 if (cpl_imagelist_get_size(tmplist)) {
580 cpl_image* tmp = cpl_imagelist_collapse_create(tmplist);
581 cpl_size const lsz = cpl_imagelist_get_size(imagelist);
582 cpl_imagelist_set(imagelist, tmp, lsz);
583 }
584 cpl_imagelist_delete(tmplist);
585 }
586
587 combinedpair = visir_img_recombine_list(RECIPE_STRING, parlist,
588 imagelist, plists, CPL_GEOM_FIRST, &drop_wcs);
589
590 cpl_propertylist_append_double(phu, "ESO QC BACKGD MEAN",
591 bg_sum / nframes);
592 cpl_imagelist_delete(imagelist); imagelist = NULL;
593 cpl_free(plists); plists = NULL;
594
595 {
596 irplib_framelist* skys = irplib_framelist_extract(
597 all, VISIR_SPC_OBS_SKYFRAME);
598 if (cpl_error_get_code()) {
599 cpl_msg_error(cpl_func,
600 "Frame set with a preprocessed frame (%s) must include a "
601 "sky frame (" VISIR_SPC_OBS_SKYFRAME ")", rawtag);
602 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
603 } else {
604 /* FIXME: make use of multiple skyframes */
605 cpl_frame const * const frame = irplib_framelist_get(skys, 0);
606 char const * const fname = cpl_frame_get_filename(frame);
607 imhcycle = cpl_image_load(fname, CPL_TYPE_UNSPECIFIED,0,0);
608 cpl_image_reject_value(imhcycle, CPL_VALUE_NAN);
609 }
610 }
611
612 } else {
613 combinedpair = visir_img_recombine(RECIPE_STRING, parlist,
614 raws, badpix, flat, CPL_GEOM_FIRST, &drop_wcs,
615 !spc_config.do_fixcombi, wlen, resol);
616
617 /* Get the hcycle image from the reference file */
618 cpl_imagelist* hcycle = visir_load_hcycle(raws, 0);
619 imhcycle = cpl_imagelist_unset(hcycle, 0);
620
621 visir_spc_det_fix(&imhcycle, 1, CPL_FALSE, wlen, resol,
622 spc_config.phi, spc_config.ksi,
623 spc_config.eps, spc_config.delta,
624 spc_config.plot);
625
626 visir_qc_append_background(phu, raws, 0, 0);
627 }
628
629 skip_if (0);
630
631 if (combinedpair) { /* FIXME: Redundant guard ? */
632 combined = cpl_image_cast(combinedpair[0], CPL_TYPE_DOUBLE);
633 cpl_image_delete(combinedpair[0]);
634 cpl_image_delete(combinedpair[1]);
635 cpl_free(combinedpair);
636 combinedpair = NULL;
637 }
638
639 bool rev = false;
640 if (!(input_mode & IS_PREPROCESSED)) {
641 /* Convert the combined image
642 * unpreprocessed mode only works with drs data */
643 cpl_image* tmp = visir_spc_flip(combined, wlen, resol,
644 VISIR_DATA_CUBE2, &rev);
645 if (combined) {
646 cpl_image_delete(combined);
647 }
648 combined = tmp;
649
650 /* Convert the half cycle image */
651 tmp = visir_spc_flip(imhcycle, wlen, resol,
652 VISIR_DATA_CUBE2, NULL);
653 if (imhcycle) {
654 cpl_image_delete(imhcycle);
655 }
656 imhcycle = tmp;
657 }
658
659 int const ncomb = visir_get_ncombine(raws);
660
661 if (spc_config.do_fixcombi && !(input_mode & IS_PREPROCESSED)) {
662 visir_spc_det_fix(&combined, 1, CPL_TRUE, wlen, resol,
663 spc_config.phi, spc_config.ksi,
664 spc_config.eps, spc_config.delta,
665 spc_config.plot);
666 }
667
668 visir_optmod ins_settings;
669 visir_spc_optmod_init(resol, wlen, &ins_settings,
670 visir_data_is_aqu(data_type));
671
672 MSG_DBG("resol = %d, input_mode = %d", resol, input_mode);
673 paflist = cpl_propertylist_new();
674
675 const int default_orders[] = {0, 1, -1, 2, -2, 3, -3, 4, -4};
676 orders = orderlist_new(n_orders);
677 for (size_t i = 0; i < n_orders; ++i) {
678 orders->data[i].cutout = default_orders[i];
679 }
680
681 // for each order; this loop sets 'cutout' to 99 upon failure, over-writing
682 // the order offset (0, -1, +1, -2, etc...)
683 for (size_t i = 0; i < orders->sz; ++i) {
684 order * const oi = &orders->data[i];
685 char pfx[80] = "";
686 if (input_mode & IS_ECH) snprintf(pfx, sizeof(pfx), "Echelle order %2d: "
687 "offset %s: ", oi->cutout + visir_spc_optmod_get_echelle_order(
688 &ins_settings), pn(oi->cutout));
689 MSG_INFO("%sattempting extraction", pfx);
690
691 int lcol = -1, rcol = -1;
692 spc_config.orderoffset = oi->cutout;
693 cpl_image* imhcyclenarrow = NULL;
694 visir_spc_extract_order(&imhcyclenarrow, &oi->comnarrow, &lcol, //no_
695 &rcol, combined, imhcycle, wlen,
696 &spc_config, (input_mode & IS_ECH) == IS_ECH,
697 visir_data_is_aqu(data_type));
698 if (cpl_error_get_code()) {
699 cpl_msg_warning(cpl_func, "%scutout failed", pfx);
700 cpl_error_reset();
701 oi->cutout = UNUSED_ORDER;
702 if (imhcyclenarrow) {
703 cpl_image_delete(imhcyclenarrow);
704 }
705 continue;
706 }
707
708 MSG_INFO("%scutout success", pfx);
709 MSG_DBG("extents mapping:\t[raw] =>\t[relative (to cutout)]");
710 MSG_DBG("=======================================================");
711 MSG_DBG(" cutout:\t\t[%d;%d] =>\t[%d;%d]", lcol, rcol,
712 lcol - lcol + 1, rcol - lcol + 1);
713
714 /* find matching apfile lines for this order */
715 oi->aplist = visir_aplist_new();
716 int const ncol = rcol - lcol + 1;
717 FOR_EACH_T(visir_apdefs const * const aps, aplist) {
718 bool matched = false;
719 int const l = visir_norm_coord(rev, -0.0, lcol, rcol, aps);
720 int const r = visir_norm_coord(rev, +0.0, lcol, rcol, aps);
721 if (1 <= l && l <= ncol && 1 <= r && r <= ncol) {
722 matched = true;
723 visir_aplist_push_back(oi->aplist, aps); // shallow copy
724 }
725 MSG_DBG("%capfile entry %d:\t[%d;%d] =>\t[%d;%d]",
726 matched ? '*' : ' ', aps->ident, aps->limits[0].l,
727 aps->limits[0].r, l, r);
728 }
729
730 /* form the list of extraction/match combos to iterate over later */
731 cxsize const nmatches = visir_aplist_size(oi->aplist);
732 if (nmatches > 0) {
733 size_t j = 0;
734 oi->matches = matchlist_new(nmatches);
735 FOR_EACH_T(visir_apdefs * const aps, oi->aplist) {
736 cpl_propertylist * const pl = cpl_propertylist_new();
737 oi->matches->data[j++] = (match){ oi->cutout, 0, 0, pl, aps };
738 }
739 } else {
740 /* extraction proceeds using defaults even if no apfile line
741 * matches, so still need space for at least one result */
742 int const ident = -(i+1); // neg ident: use old extract alg
743 visir_apdefs * const aps = visir_apdefs_new(1, ident, 'O', 0);
744 aps->limits[0] = (visir_aplimits){ lcol, rcol };
745 cpl_propertylist * const pl = cpl_propertylist_new();
746 oi->matches = matchlist_new(1);
747 oi->matches->data[0] = (match){ oi->cutout, 0, 0, pl, aps };
748 }
749
750 // for each extraction requested (potentially >1 if multiple apfile
751 // lines matched); this loop sets 'extract' to 99 upon failure, over-
752 // writing the order offset (0, -1, +1, -2, etc...)
753 for (size_t j = 0; j < oi->matches->sz; ++j) {
754 match * const mj = &oi->matches->data[j]; // alias
755
756 cpl_propertylist_update_int(mj->qclist, "ESO DRS APDEF",
757 mj->aps->ident);
758
759 if (visir_aplist_size(aplist) && nmatches < 1) {
760 MSG_WARN("%sextraction %ld: no apdefs matched", pfx, j);
761 mj->extract = UNUSED_ORDER;
762 /* skip this order if no aperture defintions provided */
763 continue;
764 }
765
766 spc_config.extract = j;
767 visir_spc_extract_wcal(oi->comnarrow, imhcyclenarrow, // no_
768 lcol, rcol, wlen, slitw, temp, fwhm, resol, &spc_config,
769 spc_cal_lines, spc_cal_qeff, visir_data_is_aqu(data_type),
770 mj->aps, ncomb, rev, &mj->spc_tbl, &mj->weight2d, mj->qclist);
771 if (cpl_error_get_code()) {
772 cpl_msg_warning(cpl_func, "%sextraction %ld: wlen calib failed",
773 pfx, j);
774 // spot #1 where EMISSIVITY (not part of the product) is removed
775 cpl_table_erase_column(mj->spc_tbl, "SPC_EMISSIVITY");
776 mj->extract = UNUSED_ORDER;
777 cpl_error_reset();
778 continue;
779 }
780 MSG_INFO("%sextraction %ld: success", pfx, j);
781
782 visir_spectro_qc(mj->qclist, paflist, drop_wcs, raws, NULL,
783 "^(" VISIR_PFITS_REGEXP_SPC_WCAL_PAF ")$");
784
785 if (star_cat) {
786 if (!(input_mode & IS_PHOT))
787 MSG_INFO("The frame set contains observation frame(s) "
788 "(%s) together with a standard star catalogue ("
789 VISIR_CALIB_STDSTAR_SPC "), attempting to "
790 "perform a photometric calibration", rawtag);
791
792 // spot #2 where EMISSIVITY (not part of the product) is removed
793 visir_spc_phot_sensit(raws, &spc_config, pl, star_cat, // no_
794 &mj->weight2d, mj->qclist, mj->spc_tbl,
795 resol, dit_key);
796 if (cpl_error_get_code()) {
797 // photometry failed
798 if (input_mode & IS_PHOT) {
799 // Break out of the loop and use the subsequent skip_if to
800 // exit this function
801 break;
802 } else {
803 cpl_error_reset();
804 cpl_msg_warning(cpl_func,
805 "The frame set contains observation frame(s) (%s) "
806 "together with a standard star catalogue ("
807 VISIR_CALIB_STDSTAR_SPC ") but the photometric "
808 "calibration failed", rawtag);
809 }
810 } else {
811 input_mode |= IS_PHOT;
812 }
813 } else {
814 // spot #3 where EMISSIVITY (not part of the product) is removed
815 cpl_table_erase_column(mj->spc_tbl, "SPC_EMISSIVITY");
816 cpl_error_reset();
817 }
818 }
819 cpl_image_delete(imhcyclenarrow); imhcyclenarrow = NULL;
820 }
821
822 skip_if (0);
823
824 /* Summarise the relevant QC headers from multiple orders
825 * into the primary header */
826 visir_spc_qc_summarise(phu, orders, "ESO QC BACKGD SIGMA");
827 visir_spc_qc_summarise(phu, orders, "ESO QC GAUSSFIT FWHM");
828 visir_spc_qc_summarise(phu, orders, "ESO QC GAUSSFIT FWHM_ERR");
829 visir_spc_qc_summarise(phu, orders, "ESO QC GAUSSFIT PEAK");
830 visir_spc_qc_summarise(phu, orders, "ESO QC GAUSSFIT PEAK_ERR");
831 visir_spc_qc_summarise(phu, orders, "ESO QC XFWHM");
832 visir_spc_qc_summarise(phu, orders, "ESO QC SENS MEDIAN");
833 visir_spc_qc_summarise(phu, orders, "ESO QC SENS MEAN");
834 visir_spc_qc_summarise(phu, orders, "ESO QC SENS STDEV");
835
836 /* PRO.CATG */
837 cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
838 VISIR_SPC_OBS_COMBINED_PROCATG);
839
840 char const * const procat = input_mode & IS_PHOT ? (input_mode & IS_ECH ?
841 VISIR_SPC_PHOT_ECH_TAB_PROCATG : VISIR_SPC_PHOT_TAB_PROCATG) : (
842 input_mode & IS_ECH ? VISIR_SPC_OBS_ECH_TAB_PROCATG :
843 VISIR_SPC_OBS_TAB_PROCATG);
844
845 bool first = true;
846 // loop only executes once for non-echelle
847 for (size_t i = 0; i < orders->sz; ++i) {
848 order const * const oi = &orders->data[i]; // alias
849 if (oi->cutout == UNUSED_ORDER) continue; // skip cutout failures
850
851 char pfx[80] = "";
852 if (input_mode & IS_ECH) snprintf(pfx, sizeof(pfx), "Echelle order %2d: "
853 "offset %s: ", oi->cutout + visir_spc_optmod_get_echelle_order(
854 &ins_settings), pn(oi->cutout));
855 for (size_t j = 0; j < oi->matches->sz; ++j) {
856 match const * const mj = &oi->matches->data[j]; // alias
857 if (mj->extract == UNUSED_ORDER) continue; // skip extract failures
858
859 MSG_INFO("%sextraction %ld: saving", pfx, j);
860 if (first) {
861 first = false;
862 visir_spc_obs_save(framelist, parlist, phu, mj->qclist,
863 paflist, mj->weight2d, mj->spc_tbl,
864 oi->comnarrow, procat, input_mode,
865 oi->cutout, j);
866 } else {
867 visir_spc_obs_extend(mj->qclist, mj->weight2d, mj->spc_tbl,
868 oi->comnarrow, input_mode, oi->cutout,
869 j);
870 }
871 }
872 }
873
874 if (!first) {
875 visir_spc_obs_extend_combined(combined);
876 }
877
878 end_skip;
879
880 cpl_propertylist_delete(phu);
881 visir_aplist_delete(aplist);
882 cpl_image_delete(combined);
883 cpl_image_delete(imhcycle);
884 if (combinedpair) {
885 cpl_image_delete(combinedpair[0]);
886 cpl_image_delete(combinedpair[1]);
887 cpl_free(combinedpair);
888 combinedpair = NULL;
889 }
890 cpl_propertylist_delete(paflist);
891 orderlist_delete(orders);
892 irplib_framelist_delete(raws);
893 irplib_framelist_delete(all);
894
895 return NULL;
896}
897
898/*----------------------------------------------------------------------------*/
905/*----------------------------------------------------------------------------*/
906static int visir_old_spc_obs(cpl_frameset * framelist,
907 const cpl_parameterlist * parlist)
908{
909 visir_old_spc_obs_(framelist, parlist);
910 return cpl_error_get_code();
911}
912
913
914/*----------------------------------------------------------------------------*/
929/*----------------------------------------------------------------------------*/
930static cpl_error_code visir_spc_obs_save(cpl_frameset * set,
931 const cpl_parameterlist * parlist,
932 cpl_propertylist * phu_qclist,
933 cpl_propertylist * qclist,
934 const cpl_propertylist * paflist,
935 const cpl_image * weight2d,
936 const cpl_table * table,
937 const cpl_image * comnarrow,
938 const char * tab_procatg,
939 const int input_mode,
940 const int ord, const size_t extract)
941{
942 char offset[8] = "";
943 char msgbuf[32];
944 bug_if (0);
945
946 if (input_mode & IS_ECH) snprintf(offset, sizeof(offset), "%s:", pn(ord));
947
948 /* THE TABLE */
949 cpl_propertylist * plist = cpl_propertylist_new();
950 snprintf(msgbuf, sizeof(msgbuf), "TAB_SPECTRUM_%s%ld", offset, extract);
951 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
952 cpl_propertylist_append(plist, qclist);
953 // Put current qclist into plist instead, and then have the primary qclist
954 // as the new qclist.
955 skip_if (irplib_dfs_save_table(set, parlist, set, table, plist,
956 RECIPE_SAVE_STRING, tab_procatg,
957 phu_qclist, NULL, visir_pipe_id,
958 RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS));
959 cpl_propertylist_delete(plist);
960
961 plist = cpl_propertylist_new();
962 /* save in single file with extensions for consistency with imaging */
963 snprintf(msgbuf, sizeof(msgbuf), "IMG_WEIGHT_%s%ld", offset, extract);
964 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
965 skip_if(cpl_image_save(weight2d, RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS,
966 CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND));
967 snprintf(msgbuf, sizeof(msgbuf), "IMG_%s%ld", offset, extract);
968 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
969 skip_if(cpl_image_save(comnarrow, RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS,
970 CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND));
971 cpl_propertylist_delete(plist);
972
973#ifdef VISIR_SAVE_PAF
974 /* THE PAF FILE FOR QC PARAMETERS */
975
976 skip_if (cpl_dfs_save_paf("VISIR", RECIPE_SAVE_STRING, paflist,
977 RECIPE_SAVE_STRING CPL_DFS_PAF));
978#else
979 bug_if(paflist == NULL);
980#endif
981
982 end_skip;
983
984 return cpl_error_get_code();
985
986}
987
988/*----------------------------------------------------------------------------*/
997/*----------------------------------------------------------------------------*/
998static cpl_error_code visir_spc_obs_extend(cpl_propertylist * qclist,
999 const cpl_image * weight2d,
1000 const cpl_table * table,
1001 const cpl_image * comnarrow,
1002 const int input_mode,
1003 const int ord, const size_t extract)
1004{
1005 char offset[8] = "";
1006 char msgbuf[32];
1007 bug_if (0);
1008
1009 if (input_mode & IS_ECH) snprintf(offset, sizeof(offset), "%s:", pn(ord));
1010
1011 /* THE TABLE */
1012 cpl_propertylist * plist = cpl_propertylist_duplicate(qclist);
1013 snprintf(msgbuf, sizeof(msgbuf), "TAB_SPECTRUM_%s%ld", offset, extract);
1014 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
1015 skip_if (cpl_table_save(table, NULL, plist, RECIPE_SAVE_STRING "_tab"
1016 CPL_DFS_FITS, CPL_IO_EXTEND));
1017 cpl_propertylist_delete(plist);
1018
1019 plist = cpl_propertylist_new();
1020 snprintf(msgbuf, sizeof(msgbuf), "IMG_WEIGHT_%s%ld", offset, extract);
1021 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
1022 skip_if(cpl_image_save(weight2d, RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS,
1023 CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND));
1024 snprintf(msgbuf, sizeof(msgbuf), "IMG_%s%ld", offset, extract);
1025 cpl_propertylist_update_string(plist, "EXTNAME", msgbuf);
1026 skip_if(cpl_image_save(comnarrow, RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS,
1027 CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND));
1028 cpl_propertylist_delete(plist);
1029
1030 end_skip;
1031
1032 return cpl_error_get_code();
1033}
1034
1035/*----------------------------------------------------------------------------*/
1041/*----------------------------------------------------------------------------*/
1042static cpl_error_code visir_spc_obs_extend_combined(const cpl_image * combined)
1043{
1044 bug_if (0);
1045
1046 cpl_propertylist * plist = cpl_propertylist_new();
1047 cpl_propertylist_update_string(plist, "EXTNAME", "IMG_COMBINED");
1048 skip_if(cpl_image_save(combined, RECIPE_SAVE_STRING "_tab" CPL_DFS_FITS,
1049 CPL_TYPE_FLOAT, plist, CPL_IO_EXTEND));
1050 cpl_propertylist_delete(plist);
1051
1052 end_skip;
1053
1054 return cpl_error_get_code();
1055}
1056
1057/*----------------------------------------------------------------------------*/
1067/*----------------------------------------------------------------------------*/
1068static cpl_error_code visir_spc_qc_summarise(cpl_propertylist * phu_qclist,
1069 orderlist * orders,
1070 const char * key)
1071{
1072 double sum = 0.0;
1073 int count = 0;
1074 for (size_t i = 0; i < orders->sz; ++i) {
1075 order const * const oi = &orders->data[i]; // alias
1076 if (oi->cutout == UNUSED_ORDER) continue; // skip cutout failures
1077
1078 for (size_t j = 0; oi->matches && j < oi->matches->sz; ++j) {
1079 match const * const mj = &oi->matches->data[j]; // alias
1080 if (mj->extract == UNUSED_ORDER) continue; // skip extract failures
1081
1082 double const val = cpl_propertylist_get_double(mj->qclist, key);
1083 if (cpl_error_get_code()) cpl_error_reset();
1084 else {
1085 count++;
1086 sum += val;
1087 break; // only need one from this order (they're all the same)
1088 }
1089 }
1090 }
1091 if (count > 0) {
1092 cpl_propertylist_append_double(phu_qclist, key, sum / count);
1093 return CPL_ERROR_NONE;
1094 }
1095 return CPL_ERROR_DATA_NOT_FOUND;
1096}
1097
cpl_error_code visir_dfs_check_framelist_tag(const irplib_framelist *self)
Check the tags in a frameset (group raw only)
Definition: visir_dfs.c:234
int visir_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: visir_dfs.c:72
cpl_image ** visir_img_recombine_list(const char *recipename, const cpl_parameterlist *parlist, cpl_imagelist *nodded, const cpl_propertylist **plists, cpl_geom_combine combine_mode, cpl_boolean *pdid_resize)
The VISIR imaging combination using cross correlation.
cpl_imagelist * visir_load_hcycle(const irplib_framelist *rawframes, int pos)
Load the HCYCLE images from a VISIR file.
cpl_image ** visir_img_recombine(const char *recipename, const cpl_parameterlist *parlist, const irplib_framelist *rawframes, const char *badpix, const char *flat, cpl_geom_combine combine_mode, cpl_boolean *pdid_resize, cpl_boolean do_spc_fix, double wlen, visir_spc_resol resol)
The VISIR imaging combination using cross correlation.
visir_aplist * visir_aplist_new_from_file(const char *apfile)
Load the user-supplied apertures definition file.
int visir_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR integer parameter.
const char * visir_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR string parameter.
double visir_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR parameter of type double.
cpl_boolean visir_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR boolean parameter.
cpl_error_code visir_spc_phot_sensit(const irplib_framelist *rawframes, const visir_spc_config *cfg, const cpl_propertylist *plist, const char *star_cat, cpl_image **pweight2d, cpl_propertylist *qclist, cpl_table *spc_table, const visir_spc_resol resol, const char *dit_key)
Compute the sensitivity from an extracted spectrum.