MOONS Pipeline Reference Manual 0.13.2
moo_calib_flux.c
1/*
2 * This file is part of the MOONS Pipeline
3 * Copyright (C) 2002-2016 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27#include <math.h>
28#include <string.h>
29#include <cpl.h>
30
31#include "moo_compute_resp.h"
32#include "moo_fibres_table.h"
33#include "moo_fits.h"
34#include "moo_pfits.h"
35#include "moo_badpix.h"
36#include "moo_utils.h"
37
38/*----------------------------------------------------------------------------*/
43/*----------------------------------------------------------------------------*/
44
47/*-----------------------------------------------------------------------------
48 Function codes
49 -----------------------------------------------------------------------------*/
50
51static moo_spline *
52_get_atm_spline(moo_atm *atm, double airm)
53{
54 moo_spline *res = NULL;
55 cpl_table *atm_flux = moo_atm_convert_mag_to_flux(atm, airm);
56
57 int nrow = cpl_table_get_nrow(atm_flux);
58 double *x = cpl_table_get_data_double(atm_flux, MOO_ATM_WAVE);
59 double *y = cpl_table_get_data_double(atm_flux, MOO_ATM_FLUX);
60
61 cpl_vector *vx = cpl_vector_wrap(nrow, x);
62 cpl_vector *vy = cpl_vector_wrap(nrow, y);
63 cpl_bivector *bv = cpl_bivector_wrap_vectors(vx, vy);
64
65 res = moo_spline_create(bv);
66
67 cpl_bivector_unwrap_vectors(bv);
68 cpl_vector_unwrap(vx);
69 cpl_vector_unwrap(vy);
70 cpl_table_delete(atm_flux);
71 return res;
72}
73
74static moo_spline *
75_get_resp_spline(cpl_table *resp, const char *resp_colname)
76{
77 moo_spline *res = NULL;
78 cpl_vector *vx = NULL;
79 cpl_vector *vy = NULL;
80 cpl_bivector *bv = NULL;
81 cpl_table *sel = NULL;
82
83 cpl_ensure(resp != NULL, CPL_ERROR_NULL_INPUT, NULL);
84 cpl_ensure(resp_colname != NULL, CPL_ERROR_NULL_INPUT, NULL);
85
86 int nrow = cpl_table_get_nrow(resp);
87 cpl_table_unselect_all(resp);
88
89 double *ya = cpl_table_get_data_double(resp, resp_colname);
90 for (int i = 0; i < nrow; i++) {
91 if (!isnan(ya[i])) {
92 cpl_table_select_row(resp, i);
93 }
94 }
95 sel = cpl_table_extract_selected(resp);
96 int size = cpl_table_get_nrow(sel);
97 moo_try_assure(size > 0, CPL_ERROR_NULL_INPUT,
98 "No data for building response %s", resp_colname);
99 double *x = cpl_table_get_data_double(sel, MOO_RESP_WAVE);
100 double *y = cpl_table_get_data_double(sel, resp_colname);
101
102 vx = cpl_vector_wrap(size, x);
103 vy = cpl_vector_wrap(size, y);
104 bv = cpl_bivector_wrap_vectors(vx, vy);
105
106 res = moo_spline_create(bv);
107
108moo_try_cleanup:
109 cpl_bivector_unwrap_vectors(bv);
110 cpl_vector_unwrap(vx);
111 cpl_vector_unwrap(vy);
112 cpl_table_delete(sel);
113
114 return res;
115}
116
117static cpl_error_code
118_moo_update_primary_header(cpl_propertylist *primary_header)
119{
120 cpl_error_code status = CPL_ERROR_NONE;
121 status = moo_pfits_set_fluxcal(primary_header, MOO_PFITS_FLUXCAL_ABSOLUTE);
122
123 return status;
124}
125/*----------------------------------------------------------------------------*/
141/*----------------------------------------------------------------------------*/
142cpl_error_code
143moo_calib_flux(moo_rbn *rbn, moo_atm *atm, moo_resp *resp)
144{
145 cpl_ensure_code(rbn != NULL, CPL_ERROR_NULL_INPUT);
146 cpl_ensure_code(atm != NULL, CPL_ERROR_NULL_INPUT);
147 cpl_ensure_code(resp != NULL, CPL_ERROR_NULL_INPUT);
148 moo_spline *atm_spline = NULL;
149 moo_spline *resp_spline = NULL;
150
151 cpl_errorstate prestate = cpl_errorstate_get();
152 cpl_msg_info(__func__, "Apply flux calibration");
153
154 int badpix_level = MOO_BADPIX_OUTSIDE_DATA_RANGE;
155 cpl_table *fibre_table = moo_rbn_get_fibre_table(rbn);
156 cpl_propertylist *primary_header = moo_rbn_get_primary_header(rbn);
157 _moo_update_primary_header(primary_header);
158
159 int ntarget = cpl_table_get_nrow(fibre_table);
160 int *idrbnt =
161 cpl_table_get_data_int(fibre_table, MOO_FIBRES_TABLE_INDEXRBN);
162 const int *spectrot =
163 cpl_table_get_data_int_const(fibre_table, MOO_FIBRES_TABLE_SPECTRO);
164 double airm_start = moo_pfits_get_tel_airm_start(rbn->primary_header);
165 double airm_end = moo_pfits_get_tel_airm_end(rbn->primary_header);
166 double airm = (airm_start + airm_end) / 2.;
167 moo_try_check(atm_spline = _get_atm_spline(atm, airm), " ");
168
169 const char *trans_colnames[] = { MOO_FIBRES_TABLE_TRANS_RI,
170 MOO_FIBRES_TABLE_TRANS_YJ,
171 MOO_FIBRES_TABLE_TRANS_H };
172
173 for (int i = 0; i < 3; i++) {
174 moo_rbn_single *rbn_single = moo_rbn_load_single(rbn, i, badpix_level);
175
176 if (rbn_single != NULL) {
177 const char *trans_colname = trans_colnames[i];
178
179 float *transt =
180 cpl_table_get_data_float(fibre_table, trans_colname);
181 cpl_table *response = moo_resp_get_table(resp, i);
182 cpl_propertylist *header = moo_rbn_single_get_header(rbn_single);
183 double cd1_1 = moo_pfits_get_cd1_1(header);
184 double crpix1 = moo_pfits_get_crpix1(header);
185 double crval1 = moo_pfits_get_crval1(header);
186 double exptime = NAN;
187 if (i == 0) {
188 exptime = moo_pfits_get_exptime(rbn->primary_header);
189 }
190 else {
191 double dit = moo_pfits_get_dit(header);
192 double ndit = moo_pfits_get_ndit(header);
193 exptime = dit * ndit;
194 }
195 hdrl_image *himg = moo_rbn_single_get_image(rbn_single);
196 cpl_image *img = hdrl_image_get_image(himg);
197 cpl_image *err = hdrl_image_get_error(himg);
198 int nx = cpl_image_get_size_x(img);
199 double entranceLoss = 1;
200 for (int t = 0; t < ntarget; t++) {
201 int idrbn = idrbnt[t];
202 double trans = transt[t];
203 int spectro = spectrot[t];
204
205 if (!isnan(trans) && trans > 0) {
206 const char *resp_colname =
207 moo_resp_get_colname(resp, idrbn, spectro);
208 moo_try_check(resp_spline =
209 _get_resp_spline(response, resp_colname),
210 "Response search for %s idrbn %d",
211 rbn_single->extname, idrbn);
212
213 double div = cd1_1 * exptime / entranceLoss;
214
215 for (int j = 1; j <= nx; j++) {
216 int rej;
217 double w = (j - crpix1) * cd1_1 + crval1;
218 double e = cpl_image_get(err, j, idrbn, &rej);
219 double f = cpl_image_get(img, j, idrbn, &rej);
220 double respval = moo_spline_eval(resp_spline, w);
221 double atmval = moo_spline_eval(atm_spline, w);
222
223 if (rej == 0) {
224 double cf = f / atmval / div / respval;
225 double ce = e / atmval / div / respval;
226 cpl_image_set(img, j, idrbn, cf);
227 cpl_image_set(err, j, idrbn, ce);
228 }
229 else {
230 cpl_image_set(img, j, idrbn, NAN);
231 cpl_image_set(err, j, idrbn, NAN);
232 }
233 }
234 moo_spline_delete(resp_spline);
235 resp_spline = NULL;
236 }
237 }
238 }
239 }
240
241moo_try_cleanup:
242 moo_spline_delete(atm_spline);
243 if (!cpl_errorstate_is_equal(prestate)) {
244 cpl_msg_error(__func__, "Error in calibrate flux");
245 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
246 if (resp_spline != NULL) {
247 moo_spline_delete(resp_spline);
248 }
249 }
250 return CPL_ERROR_NONE;
251}
cpl_table * moo_atm_convert_mag_to_flux(moo_atm *self, double airm)
Get the extinction table with additonal column FLUX.
Definition: moo_atm.c:122
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
hdrl_image * moo_rbn_single_get_image(moo_rbn_single *self)
Get image of RBN_SINGLE.
cpl_propertylist * moo_rbn_single_get_header(moo_rbn_single *self)
Get header of rbn single.
moo_rbn_single * moo_rbn_load_single(moo_rbn *self, moo_detector_type type, unsigned int level)
Load the type part in RBN and return it.
Definition: moo_rbn.c:360
cpl_propertylist * moo_rbn_get_primary_header(moo_rbn *self)
Get the PRIMARY HEADER in RBN.
Definition: moo_rbn.c:512
cpl_table * moo_rbn_get_fibre_table(moo_rbn *self)
Get the FIBRE TABLE in RBN.
Definition: moo_rbn.c:397
cpl_table * moo_resp_get_table(moo_resp *self, moo_detector_type type)
Get a reponse table from RESP.
Definition: moo_resp.c:124
const char * moo_resp_get_colname(moo_resp *self, int idrbn, int fspectro)
Get the name of the response colname for a given indexrbn.
Definition: moo_resp.c:454
cpl_error_code moo_calib_flux(moo_rbn *rbn, moo_atm *atm, moo_resp *resp)
Apply the relative flux calibration to 1D rebinned spectra.
double moo_pfits_get_tel_airm_end(const cpl_propertylist *plist)
find out the TEL.AIRM.END value
Definition: moo_pfits.c:1315
int moo_pfits_get_ndit(const cpl_propertylist *plist)
find out the ESO DET NDIT value
Definition: moo_pfits.c:382
double moo_pfits_get_cd1_1(const cpl_propertylist *plist)
find out the CD1_1 value
Definition: moo_pfits.c:1256
double moo_pfits_get_tel_airm_start(const cpl_propertylist *plist)
find out the TEL.AIRM.START value
Definition: moo_pfits.c:1295
double moo_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: moo_pfits.c:362
double moo_pfits_get_crval1(const cpl_propertylist *plist)
find out the CRVAL1 value
Definition: moo_pfits.c:1176
double moo_pfits_get_crpix1(const cpl_propertylist *plist)
find out the CRPIX1 value
Definition: moo_pfits.c:1196
cpl_error_code moo_pfits_set_fluxcal(cpl_propertylist *plist, const char *val)
Set the FLUXCAL Keyword.
Definition: moo_pfits.c:1640
double moo_pfits_get_exptime(const cpl_propertylist *plist)
find out the EXPTIME value
Definition: moo_pfits.c:1039