IIINSTRUMENT Pipeline Reference Manual 4.6.2
visir_spc_photom.c
1/* $Id: visir_spc_photom.c,v 1.64 2013-03-04 09:00:00 jtaylor Exp $
2 *
3 * This file is part of the VISIR Pipeline
4 * Copyright (C) 2002,2003 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-03-04 09:00:00 $
24 * $Revision: 1.64 $
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
36#include <string.h>
37#include <math.h>
38#include <assert.h>
39
40#include "irplib_framelist.h"
41
42#include "visir_spc_photom.h"
43
44#include "visir_parameter.h"
45#include "visir_utils.h"
46#include "visir_pfits.h"
47#include "visir_spc_distortion.h"
48
49/*-----------------------------------------------------------------------------
50 Private Function prototypes
51 -----------------------------------------------------------------------------*/
52
53static cpl_bivector * visir_spc_phot_model_from_cat(const char *, double,
54 double);
55static int visir_spc_phot_model_rebin(const cpl_bivector *, cpl_table *);
56
57static cpl_error_code visir_spc_sens_stat(const visir_spc_config *,
58 const visir_spc_resol,
59 double *, double *, double *,
60 const cpl_table *);
61
62static cpl_error_code visir_spc_phot_qc(cpl_propertylist *, cpl_propertylist *,
63 const char *, double, double, double,
64 double, double);
65
66/*----------------------------------------------------------------------------*/
70/*----------------------------------------------------------------------------*/
71
72/*-----------------------------------------------------------------------------
73 Defines
74 -----------------------------------------------------------------------------*/
75
76/* For QC wavelenghts less than this one are ignored */
77#ifndef VISIR_WAVELEN_QC_MIN
78#define VISIR_WAVELEN_QC_MIN 8e-6
79#endif
80/* For QC wavelenghts greater than this one are ignored */
81#ifndef VISIR_WAVELEN_QC_MAX
82#define VISIR_WAVELEN_QC_MAX 13e-6
83#endif
84
85/* Minimum number of spectral values to ignore, from each end */
86#ifndef VISIR_WAVELEN_QC_IGNORE
87#define VISIR_WAVELEN_QC_IGNORE 3
88#endif
89
93/*----------------------------------------------------------------------------*/
108/*----------------------------------------------------------------------------*/
109cpl_error_code
110visir_spc_phot_sensit(const irplib_framelist * rawframes,
111 const visir_spc_config * cfg,
112 const cpl_propertylist * plist,
113 const char * star_cat,
114 cpl_image ** pweight2d,
115 cpl_propertylist * qclist,
116 cpl_table * spc_table,
117 const visir_spc_resol resol,
118 const char * dit_key)
119
120{
121 cpl_errorstate cleanstate = cpl_errorstate_get();
122 cpl_bivector * flux_model = NULL;
123 double * ext_array;
124 double * spc_array;
125 double * err_array;
126 double sens_median = -1.0; /* Avoid (false) uninit warning */
127 double sens_mean = -1.0; /* Avoid (false) uninit warning */
128 double sens_stdev = -1.0; /* Ditto */
129 double exptime, factor, exectime = -1.;
130 /* Get RA / DEC */
131 const double ra = visir_pfits_get_ra(plist);
132 const double dec = visir_pfits_get_dec(plist);
133 const char * star_name;
134
135 skip_if (0);
136
137 /* DIT must be present every where */
138 skip_if(irplib_framelist_contains(rawframes, dit_key,
139 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
140 if(irplib_framelist_contains(rawframes, dit_key,
141 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5)) {
142 /* Allow 0.1 ms difference - or warn */
143 /* FIXME: The recipe does not properly handle non-uniform DITSs */
144 visir_error_reset("DIT differs by more than %g", 1e-5);
145 }
146
147 /* FIXME: Verify the angular distance */
148 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_RA,
149 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
150
151 /* FIXME: Allow 1 degree difference */
152 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DEC,
153 CPL_TYPE_DOUBLE, CPL_TRUE, 1.0));
154
155 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
156 CPL_TYPE_INT, CPL_TRUE, 0.0));
157
158 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NDIT,
159 CPL_TYPE_INT, CPL_TRUE, 0.0));
160
161 if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_STARNAME,
162 CPL_TYPE_STRING, CPL_TRUE, 0.0)) {
163 visir_error_reset("Rawframe(s) missing standard star name");
164 }
165
166 if (cpl_propertylist_has(plist, "ESO QC EXPTIME"))
167 exptime = cpl_propertylist_get_double(plist, "ESO QC EXPTIME");
168 else {
169 const int nnod = irplib_framelist_get_size(rawframes);
170 exptime = visir_utils_get_exptime(nnod, plist);
171 }
172 cpl_msg_info(cpl_func, "Exposure time: %.3f", exptime);
173 if (cpl_propertylist_has(plist, "ESO QC EXECTIME"))
174 exectime = cpl_propertylist_get_double(plist, "ESO QC EXECTIME");
175
176 skip_if (exptime <= 0.0);
177
178 factor = sqrt(exptime)/6.0; /* sqrt(exptime/3600) * 10; */
179
180 /* Get the standard star name */
181 star_name = visir_pfits_get_starname(plist);
182 if (star_name == NULL) visir_error_reset("Could not get standard star name");
183
184 /* Get the flux model from the catalog */
185 if ((flux_model=visir_spc_phot_model_from_cat(star_cat, ra, dec)) == NULL) {
186 cpl_msg_error(cpl_func, "Cannot retrieve the flux model from the cat.");
187 skip_if(1);
188 }
189
190 /* Extract the interesting part of the flux model and rebin it */
191 if (visir_spc_phot_model_rebin(flux_model, spc_table) == -1) {
192 cpl_msg_error(cpl_func, "Cannot rebin the flux model");
193 skip_if(1);
194 }
195 cpl_bivector_delete(flux_model);
196 flux_model = NULL;
197
198 /* Compute the sensitivity */
199 /* Sensitivity = model * error * 10 * sqrt(DIT*NDIT*NFILES*NCHOP*2)
200 / extracted */
201 cpl_table_duplicate_column(spc_table, "SENSITIVITY", spc_table,
202 "STD_STAR_MODEL");
203 cpl_table_set_column_unit(spc_table, "SENSITIVITY", "mJy");
204
205 ext_array = cpl_table_get_data_double(spc_table, "SENSITIVITY");
206 spc_array = cpl_table_get_data_double(spc_table, "SPC_EXTRACTED");
207 err_array = cpl_table_get_data_double(spc_table, "SPC_ERROR");
208
209 for (cpl_size i = 0; i < cpl_table_get_nrow(spc_table); i++) {
210 ext_array[i] *= factor * err_array[i];
211 if (ext_array[i] < 0 || spc_array[i] <= 0) {
212 cpl_msg_warning(cpl_func, "Setting non-physical sensitivity in row %d "
213 "to 0: %g/%g", (int)i+1, ext_array[i], spc_array[i]);
214 ext_array[i] = 0;
215 } else {
216 ext_array[i] /= spc_array[i];
217 }
218 }
219
220 skip_if(visir_spc_sens_stat(cfg, resol, &sens_median, &sens_mean,
221 &sens_stdev, spc_table));
222
223 /* This column is not part of the product */
224 skip_if (cpl_table_erase_column(spc_table, "SPC_EMISSIVITY"));
225
226 skip_if (visir_spc_phot_qc(qclist, cfg->phu, star_name, exptime, exectime,
227 sens_median, sens_mean, sens_stdev));
228
229 /* Plot the results */
230 if (cfg->plot) {
231 visir_table_plot("", "t 'Extracted spectrum' w lines", "", spc_table,
232 "WLEN", "SPC_EXTRACTED");
233 visir_table_plot("", "t 'Extracted spectrum error' w lines", "",
234 spc_table, "WLEN", "SPC_ERROR");
235 visir_table_plot("", "t 'Standard star model' w lines", "", spc_table,
236 "WLEN", "STD_STAR_MODEL");
237 visir_table_plot("set grid;", "t 'Sensitivity (mJy)' w lines", "",
238 spc_table, "WLEN", "SENSITIVITY");
239 visir_image_plot("", "t 'The weight map'", "", *pweight2d);
240 }
241
242 end_skip;
243 cpl_bivector_delete(flux_model);
244
245 return cpl_error_get_code();
246}
247
248/*----------------------------------------------------------------------------*/
269/*----------------------------------------------------------------------------*/
270cpl_table *
272 const irplib_framelist * rawframes,
273 const visir_spc_config * pconfig,
274 const char * star_cat,
275 const char * spc_cal_lines,
276 const char * spc_cal_qeff,
277 cpl_image ** pweight2d,
278 cpl_propertylist * qclist,
279 cpl_boolean do_ech,
280 double wlen,
281 double slitw,
282 double temp,
283 double fwhm,
284 const visir_spc_resol resol,
285 const char * dit_key)
286{
287 const cpl_propertylist * plist;
288 const cpl_frame * frm = NULL;
289 cpl_imagelist * hcycle = NULL;
290 cpl_image * imhcycle = NULL;
291 cpl_image * flipped = NULL;
292 cpl_image * comorder = NULL;
293 cpl_image * order = NULL;
294 cpl_table * spc_table = NULL;
295 visir_data_type dtype;
296
297 *pweight2d = NULL;
298
299 skip_if (rawframes == NULL);
300
301 /* Get the first frame */
302 plist = irplib_framelist_get_propertylist_const(rawframes, 0);
303 frm = irplib_framelist_get_const(rawframes, 0);
304
305 skip_if (visir_get_data_type(frm, plist, &dtype, NULL));
306
307 /* Get the HCYCLE frame */
308 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
309 skip_if (0);
310
311 skip_if (pconfig->do_fixcombi &&
312 visir_spc_det_fix(combined, 1, CPL_TRUE,
313 wlen, resol,
314 pconfig->phi,
315 pconfig->ksi,
316 pconfig->eps,
317 pconfig->delta,
318 pconfig->plot));
319
320
321 imhcycle = cpl_imagelist_unset(hcycle, 0);
322 skip_if (0);
323
324 skip_if (visir_spc_det_fix(&imhcycle, 1, CPL_FALSE,
325 wlen, resol,
326 pconfig->phi,
327 pconfig->ksi,
328 pconfig->eps,
329 pconfig->delta,
330 pconfig->plot));
331
332 /* Convert the combined image */
333 bool rev;
334 flipped = visir_spc_flip(*combined, wlen, resol, dtype, &rev);
335 skip_if (0);
336 cpl_image_delete(*combined);
337 *combined = flipped;
338 flipped = NULL;
339
340 /* Convert the half cycle image */
341 flipped = visir_spc_flip(imhcycle, wlen, resol, dtype, NULL);
342 skip_if (0);
343 cpl_image_delete(imhcycle);
344 imhcycle = flipped;
345 flipped = NULL;
346
347 const int ncomb = visir_get_ncombine(rawframes);
348 skip_if (!ncomb);
349
350 int lcol = -1, rcol = -1;
351 skip_if(visir_spc_extract_order(&order, &comorder, &lcol, &rcol, *combined,
352 imhcycle, wlen, pconfig, do_ech,
353 visir_data_is_aqu(dtype)));
354 skip_if(visir_qc_append_background(qclist, rawframes,
355 do_ech ? lcol : 0,
356 do_ech ? rcol : 0));
357
358 int const ident = -1; // neg ident: use old extract alg
359 visir_apdefs * const aps = visir_apdefs_new(1, ident, 'O', 0);
360 aps->limits[0] = (visir_aplimits){ lcol, rcol };
361
362 /* Extract the spectrum */
363 skip_if (visir_spc_extract_wcal(comorder, order, lcol, rcol, wlen, slitw,
364 temp, fwhm, resol, pconfig, spc_cal_lines,
365 spc_cal_qeff, visir_data_is_aqu(dtype), aps,
366 ncomb, rev, &spc_table, pweight2d, qclist));
367
368
369 visir_spc_phot_sensit(rawframes, pconfig, plist, star_cat, pweight2d,
370 qclist, spc_table, resol, dit_key);
371
372 cpl_imagelist_delete(hcycle);
373 hcycle = NULL;
374
375
376 end_skip;
377
378 cpl_imagelist_delete(hcycle);
379
380 cpl_image_delete(flipped);
381 cpl_image_delete(imhcycle);
382 cpl_image_delete(order);
383 cpl_image_delete(comorder);
384
385 if (cpl_error_get_code()) {
386 cpl_table_delete(spc_table);
387 spc_table = NULL;
388 cpl_image_delete(*pweight2d);
389 *pweight2d = NULL;
390 }
391
392 return spc_table;
393}
394
397/*----------------------------------------------------------------------------*/
409/*----------------------------------------------------------------------------*/
410static cpl_bivector * visir_spc_phot_model_from_cat(const char * star_cat,
411 double ra,
412 double dec)
413{
414 const double max_radius = VISIR_STAR_MAX_RADIUS;
415 const cpl_table * catalog = NULL; /* Flux model for all stars */
416 int nb_stars;
417 const double * dd;
418 const cpl_array * da;
419 cpl_vector * v_ra = NULL;
420 cpl_vector * v_dec = NULL;
421 int min_dist_ind;
422 cpl_bivector * model = NULL;
423 cpl_vector * model_x = NULL;
424 cpl_vector * model_y = NULL;
425 const double conv_mJy = 3.33E8; /* FIXME: 1e8/3 ? */
426 double star_dist;
427 int nb_vals;
428
429
430 bug_if (0);
431
432 /* Open the star catalog */
433 catalog = cpl_table_load(star_cat, 1, 0);
434 if (catalog == NULL) {
435 cpl_msg_error(cpl_func, "Could not open the star catalog: %s",
436 star_cat ? star_cat : "<NULL>");
437 skip_if(1);
438 }
439
440 nb_stars = cpl_table_get_nrow(catalog);
441
442 skip_if(nb_stars < 1);
443
444 /* Get the RA and DEC columns */
445 dd = cpl_table_get_data_double_const(catalog, "RA");
446 skip_if (dd == NULL);
447 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
448 v_ra = cpl_vector_wrap(nb_stars, (double*)dd); /* v_ra is _not_ modified */
449 IRPLIB_DIAG_PRAGMA_POP;
450 bug_if( v_ra == NULL);
451
452 dd = cpl_table_get_data_double_const(catalog, "DEC");
453 skip_if (dd == NULL);
454 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
455 v_dec = cpl_vector_wrap(nb_stars, (double*)dd); /* v_dec is _not_ modified */
456 IRPLIB_DIAG_PRAGMA_POP;
457 bug_if( v_dec == NULL);
458
459 /* Find the star closest to the given ra, dec */
460 min_dist_ind = visir_star_find(v_ra, v_dec, ra, dec, max_radius, &star_dist);
461
462 skip_if (min_dist_ind < 0);
463
464 cpl_msg_info(cpl_func, "The standard star closest to (RA,DEC)=(%g,%g) is "
465 "no. %d, '%s' at (RA,DEC)=(%g,%g) with the distance [degree]: "
466 "%g", ra, dec, 1+min_dist_ind,
467 cpl_table_get_string(catalog, "STARS", min_dist_ind),
468 cpl_table_get_double(catalog, "RA", min_dist_ind, NULL),
469 cpl_table_get_double(catalog, "DEC", min_dist_ind, NULL),
470 star_dist);
471
472 /* Get the wavelengths of the star model */
473 da = cpl_table_get_array(catalog, "WAVELENGTHS", min_dist_ind);
474 skip_if (da == NULL);
475 dd = cpl_array_get_data_double_const(da);
476 skip_if (dd == NULL);
477
478 nb_vals = cpl_array_get_size(da);
479
480 model_x = cpl_vector_new(nb_vals);
481 memcpy(cpl_vector_get_data(model_x), dd, nb_vals * sizeof(double));
482
483 /* Get the corresponding fluxes of the star model */
484 da = cpl_table_get_array(catalog, "MODEL_FLUX", min_dist_ind);
485 skip_if (da == NULL);
486 dd = cpl_array_get_data_double_const(da);
487 skip_if (dd == NULL);
488
489 skip_if (nb_vals != cpl_array_get_size(da));
490
491 model_y = cpl_vector_new(nb_vals);
492 memcpy(cpl_vector_get_data(model_y), dd, nb_vals * sizeof(double));
493
494 /* Convert from W/m2/m to mJy with * 3.33 * 10^8 * lamda * lamda */
495 bug_if (cpl_vector_multiply_scalar(model_y, conv_mJy));
496 bug_if (cpl_vector_multiply(model_y, model_x));
497 bug_if (cpl_vector_multiply(model_y, model_x));
498
499 /* Convert from microns to meters */
500 bug_if (cpl_vector_multiply_scalar(model_x, 1e-6));
501
502 model = cpl_bivector_wrap_vectors(model_x, model_y);
503
504 bug_if (model == NULL);
505
506 end_skip;
507
508 (void)cpl_vector_unwrap(v_ra);
509 (void)cpl_vector_unwrap(v_dec);
510 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
511 cpl_table_delete((cpl_table*)catalog);
512 IRPLIB_DIAG_PRAGMA_POP;
513
514 if (cpl_error_get_code()) {
515 /* At this point model is certain to be NULL */
516 cpl_vector_delete(model_x);
517 cpl_vector_delete(model_y);
518 }
519
520 return model;
521}
522
523/*----------------------------------------------------------------------------*/
529/*----------------------------------------------------------------------------*/
530static int visir_spc_phot_model_rebin(
531 const cpl_bivector * model,
532 cpl_table * spec_tab)
533{
534 cpl_vector * bounds = NULL;
535 cpl_vector * spec = NULL;
536 double bin_pos;
537 const int nrow = cpl_table_get_nrow(spec_tab);
538 int i;
539
540
541 skip_if (0);
542
543 /* Create bounds */
544 bounds = cpl_vector_new(nrow + 1);
545 for (i=1 ; i<cpl_vector_get_size(bounds) - 1 ; i++) {
546 bin_pos = (cpl_table_get(spec_tab, "WLEN", i-1, NULL) +
547 cpl_table_get(spec_tab, "WLEN", i, NULL)) / 2.0;
548 cpl_vector_set(bounds, i, bin_pos);
549 }
550 bin_pos = cpl_table_get(spec_tab, "WLEN", 0, NULL) -
551 ((cpl_table_get(spec_tab, "WLEN", 1, NULL) -
552 cpl_table_get(spec_tab, "WLEN", 0, NULL)) / 2.0);
553 cpl_vector_set(bounds, 0, bin_pos);
554 bin_pos =
555 cpl_table_get(spec_tab, "WLEN", nrow-1, NULL) +
556 ((cpl_table_get(spec_tab,"WLEN", 1, NULL) -
557 cpl_table_get(spec_tab, "WLEN", 0, NULL)) / 2.0);
558 cpl_vector_set(bounds, cpl_vector_get_size(bounds)-1, bin_pos);
559
560 /* Create the interpolated spectrum */
561 spec = cpl_vector_new(nrow);
562
563 /* Interpolate the spectrum */
564 if (visir_vector_resample(spec, bounds, model)) {
565 cpl_msg_error(cpl_func, "Cannot rebin the spectrum");
566 skip_if(1);
567 }
568
569 /* Add the result in spec_tab */
570 cpl_table_new_column(spec_tab, "STD_STAR_MODEL", CPL_TYPE_DOUBLE);
571 cpl_table_set_column_unit(spec_tab, "STD_STAR_MODEL", "mJy");
572 for (i=0 ; i<nrow ; i++) {
573 cpl_table_set_double(spec_tab, "STD_STAR_MODEL", i,
574 cpl_vector_get(spec, i));
575 }
576
577 end_skip;
578
579 cpl_vector_delete(spec);
580 cpl_vector_delete(bounds);
581
582 return cpl_error_get_code();
583}
584
585/*----------------------------------------------------------------------------*/
595/*----------------------------------------------------------------------------*/
596static cpl_error_code visir_spc_wl_start_end(const cpl_table * self,
597 cpl_size * pstart, cpl_size * pend)
598{
599 const cpl_size npix = cpl_table_get_nrow(self);
600 cpl_vector * vwave = NULL;
601
602 /* FIXME: Use cpl_table_select() */
603 /* vwave will _not_ be modified */
604 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
605 vwave = cpl_vector_wrap(npix, (double*)
606 cpl_table_get_data_double_const(self, "WLEN"));
607 IRPLIB_DIAG_PRAGMA_POP;
608
609 assert(VISIR_WAVELEN_QC_MIN < VISIR_WAVELEN_QC_MAX);
610
611 cpl_size l = visir_lower_bound(vwave, VISIR_WAVELEN_QC_MIN);
612 cpl_size u = visir_upper_bound(vwave, VISIR_WAVELEN_QC_MAX);
613
614 l = CPL_MAX(l, VISIR_WAVELEN_QC_IGNORE);
615 u = CPL_MIN(u, npix - VISIR_WAVELEN_QC_IGNORE);
616
617 if (u - l <= 0) {
618 (void)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
619 "For QC the calibrated wavelength range "
620 "(%g, %g) does not intersect with the "
621 "required (%g, %g) [m]",
622 cpl_vector_get(vwave, l),
623 cpl_vector_get(vwave, u),
624 VISIR_WAVELEN_QC_MIN, VISIR_WAVELEN_QC_MAX);
625 } else {
626 *pstart = l;
627 *pend = u;
628 }
629
630 cpl_vector_unwrap(vwave);
631
632 return cpl_error_get_code();
633}
634
635
636/*----------------------------------------------------------------------------*/
647/*----------------------------------------------------------------------------*/
648static cpl_error_code visir_spc_sens_stat(const visir_spc_config * pconfig,
649 const visir_spc_resol resol,
650 double * psens_median,
651 double * psens_mean,
652 double * psens_stdev,
653 const cpl_table * spc_table)
654{
655
656 cpl_vector * sens_ignore = NULL;
657 cpl_vector * sens_mini = NULL;
658 double emis_min, emis_max;
659 cpl_size npix_start = 0;
660 cpl_size npix_end = 0;
661 cpl_size nuse;
662 int iok;
663
664 skip_if(0);
665
666 skip_if(pconfig == NULL);
667
668 if (resol == VISIR_SPC_R_LRP || resol == VISIR_SPC_R_LR) {
669 skip_if(visir_spc_wl_start_end(spc_table, &npix_start, &npix_end));
670 } else {
671 npix_start = VISIR_WAVELEN_QC_IGNORE;
672 npix_end = cpl_table_get_nrow(spc_table) - VISIR_WAVELEN_QC_IGNORE;
673 }
674
675 nuse = npix_end - npix_start;
676
677 cpl_msg_info(cpl_func, "QC computed from %lld spectral values in the range "
678 "(%g, %g) [m]", (long long)nuse, VISIR_WAVELEN_QC_MIN,
679 VISIR_WAVELEN_QC_MAX);
680
681 /* Compute mean and stdev of the sensitivity signal
682 - using the selected range of elements */
683 /* FIXME: Use cpl_table_select() */
684 /* sens_ignore will _not_ be modified */
685 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
686 sens_ignore = cpl_vector_wrap( nuse, (double*)
687 cpl_table_get_data_double_const(spc_table,
688 "SENSITIVITY") + npix_start);
689 IRPLIB_DIAG_PRAGMA_POP;
690 skip_if(0);
691
692 if (pconfig->plot)
693 visir_vector_plot("set grid;","t 'Truncated Sensitivity (mJy)' w lines",
694 "", sens_ignore);
695
696 sens_mini = cpl_vector_duplicate(sens_ignore);
697 skip_if(0);
698
699 emis_min = cpl_table_get_column_min(spc_table, "SPC_EMISSIVITY");
700 emis_max = cpl_table_get_column_max(spc_table, "SPC_EMISSIVITY");
701 skip_if(0);
702
703 emis_max = emis_min + pconfig->phot_emis_tol * (emis_max - emis_min);
704
705 iok = 0;
706 for (cpl_size i=0; i < nuse; i++) {
707 const double emis = cpl_table_get(spc_table, "SPC_EMISSIVITY",
708 i + npix_start, NULL);
709
710 skip_if(0);
711
712 if (emis > emis_max) continue;
713
714 if (i > iok)
715 skip_if(cpl_vector_set(sens_mini, iok, cpl_vector_get(sens_mini, i)));
716
717 iok++;
718
719 }
720
721 assert( iok > 0);
722
723 skip_if(cpl_vector_set_size(sens_mini, iok));
724
725 *psens_mean = cpl_vector_get_mean(sens_mini);
726
727 if (iok == 1) {
728 cpl_msg_warning(cpl_func, "Sensitivity computed on only 1 wavelength "
729 "with emissivity %f", emis_max);
730 *psens_stdev = 0;
731 } else {
732 cpl_msg_info(cpl_func, "Sensitivity computed on %d wavelengths with "
733 "emissivity at most %f", iok, emis_max);
734
735 *psens_stdev = cpl_vector_get_stdev(sens_mini);
736
737 }
738
739 *psens_median = cpl_vector_get_median(sens_mini);
740
741 end_skip;
742
743 cpl_vector_unwrap(sens_ignore);
744 cpl_vector_delete(sens_mini);
745
746 return cpl_error_get_code();
747
748}
749
750
751/*----------------------------------------------------------------------------*/
765/*----------------------------------------------------------------------------*/
766static cpl_error_code visir_spc_phot_qc(cpl_propertylist * qclist,
767 cpl_propertylist * phu_qclist,
768 const char * star_name,
769 double exptime,
770 double exectime,
771 double sens_median,
772 double sens_mean,
773 double sens_stdev)
774{
775
776 bug_if (cpl_propertylist_append_double(phu_qclist, "ESO QC EXPTIME", exptime));
777 if (exectime > 0) {
778 bug_if (cpl_propertylist_append_double(phu_qclist, "ESO QC EXECTIME",
779 exectime));
780 }
781 bug_if (cpl_propertylist_append_double(qclist, "ESO QC SENS MEDIAN",
782 sens_median));
783 bug_if (cpl_propertylist_append_double(qclist, "ESO QC SENS MEAN", sens_mean));
784 bug_if (cpl_propertylist_append_double(qclist, "ESO QC SENS STDEV",
785 sens_stdev));
786 /* FIXME: Verify that this is the correct behaviour */
787 bug_if (cpl_propertylist_append_string(phu_qclist, "ESO QC STARNAME",
788 star_name ? star_name : ""));
789
790 end_skip;
791
792 return cpl_error_get_code();
793
794}
cpl_imagelist * visir_load_imagelist(const irplib_framelist *rawframes, int pos, cpl_boolean is_interm)
Load either a INTERM or Half-Cycle cube from a VISIR file.
double visir_pfits_get_ra(const cpl_propertylist *self)
The RA.
Definition: visir_pfits.c:742
double visir_pfits_get_dec(const cpl_propertylist *self)
The DEC.
Definition: visir_pfits.c:313
const char * visir_pfits_get_starname(const cpl_propertylist *self)
The std star name.
Definition: visir_pfits.c:808
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.
cpl_table * visir_spc_phot_sensit_from_image(cpl_image **combined, const irplib_framelist *rawframes, const visir_spc_config *pconfig, const char *star_cat, const char *spc_cal_lines, const char *spc_cal_qeff, cpl_image **pweight2d, cpl_propertylist *qclist, cpl_boolean do_ech, double wlen, double slitw, double temp, double fwhm, const visir_spc_resol resol, const char *dit_key)
Extract spectrum from image and compute sensitivity.