MOONS Pipeline Reference Manual 0.13.1
moo_compute_resp.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_fits.h"
33#include "moo_pfits.h"
34#include "moo_badpix.h"
35#include "moo_utils.h"
36/*----------------------------------------------------------------------------*/
41/*----------------------------------------------------------------------------*/
42
45/*-----------------------------------------------------------------------------
46 Function codes
47 -----------------------------------------------------------------------------*/
48
49
50static cpl_error_code
51_moo_response_fit1d(cpl_table *fit_table,
52 int degree,
53 int niter,
54 double max_frac,
55 double kappa_lo,
56 double kappa_up)
57{
58 double wmin =
59 cpl_table_get_column_min(fit_table, MOO_COMPUTE_RESP_FIT_WAVE);
60 double wmax =
61 cpl_table_get_column_max(fit_table, MOO_COMPUTE_RESP_FIT_WAVE);
62
63 cpl_size fit_table_size =
64 cpl_table_and_selected_int(fit_table, MOO_COMPUTE_RESP_FIT_IS_USED,
65 CPL_EQUAL_TO, 1);
66 if (fit_table_size > degree) {
67 int total_rejected = 0;
68 moo_tcheby_polynomial *poly = NULL;
69
70 cpl_array *seltab = cpl_table_where_selected(fit_table);
71
72 double *fluxes =
73 cpl_table_get_data_double(fit_table, MOO_COMPUTE_RESP_FIT_FLUX);
74 double *wave =
75 cpl_table_get_data_double(fit_table, MOO_COMPUTE_RESP_FIT_WAVE);
76 int *isused =
77 cpl_table_get_data_int(fit_table, MOO_COMPUTE_RESP_FIT_IS_USED);
78
79 cpl_bivector *data = cpl_bivector_new(fit_table_size);
80 cpl_vector *vx = cpl_bivector_get_x(data);
81 cpl_vector *vy = cpl_bivector_get_y(data);
82 for (int i = 0; i < fit_table_size; i++) {
83 int idx = cpl_array_get_cplsize(seltab, i, NULL);
84 double f = fluxes[idx];
85 double w = wave[idx];
86 cpl_vector_set(vx, i, w);
87 cpl_vector_set(vy, i, f);
88 }
89
90 poly = moo_tcheby_polynomial_fit(data, degree, wmin, wmax);
91 cpl_size size = fit_table_size;
92
93 for (int i = 1; i <= niter; i++) {
94 cpl_msg_info(__func__,
95 "iter %d / %d with %" CPL_SIZE_FORMAT
96 " data (total rejected %d)",
97 i, niter, size, total_rejected);
98 cpl_vector *vdiff = cpl_vector_new(size);
99
100 for (int j = 0; j < size; j++) {
101 double x = cpl_vector_get(vx, j);
102 double y = cpl_vector_get(vy, j);
103 double t = moo_tcheby_polynomial_eval(poly, x);
104 double diff = y - t;
105 cpl_vector_set(vdiff, j, diff);
106 }
107
108 double stdev = cpl_vector_get_stdev(vdiff);
109 int nb_rejected = 0;
110
111 for (int j = 0; j < size; j++) {
112 double diff = cpl_vector_get(vdiff, j);
113 if ((diff >= kappa_lo * stdev) || (diff <= -kappa_up * stdev)) {
114 int idx = cpl_array_get_cplsize(seltab, j, NULL);
115 isused[idx] = 2;
116 nb_rejected++;
117 }
118 }
119 cpl_vector_delete(vdiff);
120
121 if (nb_rejected == size || nb_rejected == 0) {
122 break;
123 }
124 double frac =
125 (double)(nb_rejected + total_rejected) / (double)fit_table_size;
126 if (frac > max_frac) {
127 break;
128 }
129 /* OK to reject points and delete old solution */
130 total_rejected += nb_rejected;
131 moo_tcheby_polynomial_delete(poly);
132 cpl_array_delete(seltab);
133
134 cpl_table_select_all(fit_table);
135 size = cpl_table_and_selected_int(fit_table,
136 MOO_COMPUTE_RESP_FIT_IS_USED,
137 CPL_EQUAL_TO, 2);
138 seltab = cpl_table_where_selected(fit_table);
139 for (int j = 0; j < size; j++) {
140 int idx = cpl_array_get_cplsize(seltab, j, NULL);
141 isused[idx] = 0;
142 }
143 cpl_array_delete(seltab);
144 cpl_table_select_all(fit_table);
145 size = cpl_table_and_selected_int(fit_table,
146 MOO_COMPUTE_RESP_FIT_IS_USED,
147 CPL_EQUAL_TO, 1);
148 seltab = cpl_table_where_selected(fit_table);
149
150 cpl_bivector_delete(data);
151 data = cpl_bivector_new(size);
152 vx = cpl_bivector_get_x(data);
153 vy = cpl_bivector_get_y(data);
154 for (int j = 0; j < size; j++) {
155 int idx = cpl_array_get_cplsize(seltab, j, NULL);
156 cpl_vector_set(vx, j, wave[idx]);
157 cpl_vector_set(vy, j, fluxes[idx]);
158 }
159 poly = moo_tcheby_polynomial_fit(data, degree, wmin, wmax);
160 }
161
162 cpl_array_delete(seltab);
163 cpl_table_select_all(fit_table);
164
165 size =
166 cpl_table_and_selected_int(fit_table, MOO_COMPUTE_RESP_FIT_IS_USED,
167 CPL_EQUAL_TO, 2);
168 seltab = cpl_table_where_selected(fit_table);
169 for (int j = 0; j < size; j++) {
170 int idx = cpl_array_get_cplsize(seltab, j, NULL);
171 isused[idx] = 1;
172 }
173
174 int nrow = cpl_table_get_nrow(fit_table);
175
176 for (int i = 0; i < nrow; i++) {
177 double w = cpl_table_get_double(fit_table,
178 MOO_COMPUTE_RESP_FIT_WAVE, i, NULL);
179 double fit = moo_tcheby_polynomial_eval(poly, w);
180 cpl_table_set_double(fit_table, MOO_COMPUTE_RESP_FIT_FIT, i, fit);
181 }
182
183 moo_tcheby_polynomial_delete(poly);
184 cpl_bivector_delete(data);
185 cpl_array_delete(seltab);
186 }
187 return cpl_error_get_code();
188}
189
190static moo_spline *
191_get_atm_spline(moo_atm *atm, double airm)
192{
193 moo_spline *res = NULL;
194 cpl_table *atm_flux = moo_atm_convert_mag_to_flux(atm, airm);
195
196 int nrow = cpl_table_get_nrow(atm_flux);
197 double *x = cpl_table_get_data_double(atm_flux, MOO_ATM_WAVE);
198 double *y = cpl_table_get_data_double(atm_flux, MOO_ATM_FLUX);
199
200 cpl_vector *vx = cpl_vector_wrap(nrow, x);
201 cpl_vector *vy = cpl_vector_wrap(nrow, y);
202 cpl_bivector *bv = cpl_bivector_wrap_vectors(vx, vy);
203
204 res = moo_spline_create(bv);
205
206 cpl_bivector_unwrap_vectors(bv);
207 cpl_vector_unwrap(vx);
208 cpl_vector_unwrap(vy);
209 cpl_table_delete(atm_flux);
210 return res;
211}
212
213static moo_spline *
214_get_flx_spline(moo_flx *flx, const char *targname)
215{
216 moo_spline *flx_spline = NULL;
217 cpl_table *std_spec = moo_flx_get_obj(flx, targname);
218 int nrow = cpl_table_get_nrow(std_spec);
219
220 double *x = cpl_table_get_data_double(std_spec, MOO_FLX_SPECTRUM_WAVE);
221 double *y = cpl_table_get_data_double(std_spec, MOO_FLX_SPECTRUM_FLUX);
222
223 cpl_vector *vx = cpl_vector_wrap(nrow, x);
224 cpl_vector *vy = cpl_vector_wrap(nrow, y);
225 cpl_bivector *bv = cpl_bivector_wrap_vectors(vx, vy);
226
227 flx_spline = moo_spline_create(bv);
228
229 cpl_bivector_unwrap_vectors(bv);
230 cpl_vector_unwrap(vx);
231 cpl_vector_unwrap(vy);
232
233 cpl_table_delete(std_spec);
234
235 return flx_spline;
236}
237/*----------------------------------------------------------------------------*/
255/*----------------------------------------------------------------------------*/
256moo_resp *
257moo_compute_resp(moo_scilist *scilist,
258 moo_atm *atm,
259 moo_flx *flx,
260 moo_compute_resp_params *params)
261{
262 moo_resp *resp = NULL;
263
264 cpl_ensure(scilist != NULL, CPL_ERROR_NULL_INPUT, NULL);
265 cpl_ensure(atm != NULL, CPL_ERROR_NULL_INPUT, NULL);
266 cpl_ensure(flx != NULL, CPL_ERROR_NULL_INPUT, NULL);
267 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
268
269 int size = moo_scilist_get_size(scilist);
270 unsigned int badpix_level = MOO_BADPIX_OUTSIDE_DATA_RANGE |
273
274 resp = moo_resp_create(scilist, badpix_level);
275
276 cpl_msg_info(__func__, "Compute response using %d frames", size);
277
278 for (int il = 0; il < size; il++) {
279 const char *response_colname =
280 cpl_table_get_string(resp->response_table, MOO_RESP_TABLE_RESPONSE,
281 il);
282 moo_sci *sci = moo_scilist_get(scilist, il);
283 moo_target_table *target_table = moo_sci_get_target_table(sci);
284
285 if (target_table->table != NULL) {
286 const char *targname = moo_target_table_get_std_name(target_table);
287 moo_spline *flx_spline = _get_flx_spline(flx, targname);
288 double airm_start =
289 moo_pfits_get_tel_airm_start(sci->primary_header);
290 double airm_end = moo_pfits_get_tel_airm_end(sci->primary_header);
291 double airm = (airm_start + airm_end) / 2.;
292
293 moo_spline *atm_spline = _get_atm_spline(atm, airm);
294 int tidx = moo_target_table_find_index(target_table, targname);
295 const char *colnames[] = { MOO_TARGET_TABLE_EXPTIMERI,
296 MOO_TARGET_TABLE_EXPTIMEYJ,
297 MOO_TARGET_TABLE_EXPTIMEH };
298
299 for (int i = 0; i < 3; i++) {
300 int degree = params->degree[i];
301 double frac = params->frac;
302 double kappa_lo = params->kappa_lo;
303 double kappa_up = params->kappa_up;
304 int niter = params->niter;
305 moo_sci_single *sci_single = moo_sci_get_single(sci, i);
306 if (sci_single != NULL) {
307 int win_hsize = params->filter_winhsize[i];
308
309 cpl_propertylist *header =
310 moo_sci_single_get_header(sci_single);
311 double cd1_1 = moo_pfits_get_cd1_1(header);
312 double exptime =
313 cpl_table_get_double(target_table->table, colnames[i],
314 tidx, NULL);
315 double entranceLoss = 1;
316 double div = cd1_1 * exptime * entranceLoss;
317
318 cpl_table *response = moo_resp_get_table(resp, i);
319
320 int nrow = cpl_table_get_nrow(response);
321 double *data =
322 cpl_table_get_data_double(response, response_colname);
323 double *waves =
324 cpl_table_get_data_double(response, MOO_RESP_WAVE);
325
326 cpl_vector *init_data = cpl_vector_wrap(nrow, data);
327 cpl_vector *filter_data =
328 moo_median_filter(init_data, win_hsize);
329
330 cpl_vector_unwrap(init_data);
331 for (int j = 0; j < nrow; j++) {
332 double w = waves[j];
333 double flxval = moo_spline_eval(flx_spline, w);
334 double atmval = moo_spline_eval(atm_spline, w);
335 double fval = cpl_vector_get(filter_data, j);
336
337#if MOO_DEBUG_RESP
338 {
339 char *flx_colname =
340 cpl_sprintf("%s_%s", response_colname,
341 MOO_RESP_FLX);
342 char *atm_colname =
343 cpl_sprintf("%s_%s", response_colname,
344 MOO_RESP_ATM);
345 char *fluxfilter_colname =
346 cpl_sprintf("%s_%s", response_colname,
347 MOO_RESP_SPECFLUXFILTER);
348 cpl_table_set_double(response, fluxfilter_colname,
349 j, fval);
350 cpl_table_set_double(response, atm_colname, j,
351 atmval);
352 cpl_table_set_double(response, flx_colname, j,
353 flxval);
354 cpl_free(flx_colname);
355 cpl_free(atm_colname);
356 cpl_free(fluxfilter_colname);
357 }
358#endif
359
360 if (!isnan(fval)) {
361 data[j] = flxval / (fval / div / atmval);
362 }
363 else {
364 cpl_table_set_column_invalid(response,
365 response_colname, j,
366 1);
367 }
368 }
369 cpl_table *fit_table = cpl_table_new(nrow);
370 cpl_table_duplicate_column(fit_table,
371 MOO_COMPUTE_RESP_FIT_WAVE,
372 response, MOO_RESP_WAVE);
373 cpl_table_duplicate_column(fit_table,
374 MOO_COMPUTE_RESP_FIT_FLUX,
375 response, response_colname);
376 cpl_table_new_column(fit_table,
377 MOO_COMPUTE_RESP_FIT_IS_USED,
378 CPL_TYPE_INT);
379 cpl_table_new_column(fit_table, MOO_COMPUTE_RESP_FIT_FIT,
380 CPL_TYPE_DOUBLE);
381 for (int k = 0; k < nrow; k++) {
382 int val = 0;
383 if (cpl_table_is_valid(fit_table,
384 MOO_COMPUTE_RESP_FIT_FLUX, k)) {
385 val = 1;
386 }
387 cpl_table_set_int(fit_table,
388 MOO_COMPUTE_RESP_FIT_IS_USED, k, val);
389 }
390 _moo_response_fit1d(fit_table, degree, niter, frac,
391 kappa_lo, kappa_up);
392
393#if MOO_DEBUG_RESPONSE_FIT
394 {
395 char *resname =
396 cpl_sprintf("COMPUTE_RESP_TABLE_%s_%d.fits",
397 sci_single->extname, il);
398 cpl_table_save(fit_table, NULL, NULL, resname,
399 CPL_IO_CREATE);
400 cpl_free(resname);
401 }
402#endif
403 for (int j = 0; j < nrow; j++) {
404 double fit =
405 cpl_table_get_double(fit_table,
406 MOO_COMPUTE_RESP_FIT_FIT, j,
407 NULL);
408 cpl_table_set(response, response_colname, j, 1 / fit);
409 }
410 cpl_table_delete(fit_table);
411 cpl_vector_delete(filter_data);
412 }
413 }
414 moo_spline_delete(flx_spline);
415 moo_spline_delete(atm_spline);
416 }
417 }
418
419 cpl_table_erase_invalid_rows(resp->response_table);
420
421 return resp;
422}
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_LOW_QE
Definition: moo_badpix.h:45
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
#define MOO_BADPIX_CALIB_DEFECT
Definition: moo_badpix.h:48
#define MOO_BADPIX_HOT
Definition: moo_badpix.h:51
#define MOO_BADPIX_COSMETIC
Definition: moo_badpix.h:57
cpl_table * moo_flx_get_obj(moo_flx *self, const char *objname)
Find the TABLE for a given object name.
Definition: moo_flx.c:165
cpl_table * moo_resp_get_table(moo_resp *self, moo_detector_type type)
Get a reponse table from RESP.
Definition: moo_resp.c:124
moo_resp * moo_resp_create(moo_scilist *scilist, int badpix_level)
Prepare RESP for SCI frame.
Definition: moo_resp.c:158
cpl_propertylist * moo_sci_single_get_header(moo_sci_single *self)
Get header of sci single.
moo_sci_single * moo_sci_get_single(moo_sci *self, moo_detector_type type)
Get the type part in SCI and return it.
Definition: moo_sci.c:351
moo_target_table * moo_sci_get_target_table(moo_sci *self)
Get the target table of SCI file.
Definition: moo_sci.c:284
moo_sci * moo_scilist_get(moo_scilist *self, int i)
Get the SCI at the position i in the list.
Definition: moo_scilist.c:384
cpl_size moo_scilist_get_size(const moo_scilist *self)
Get the number of SCI in the scilist.
Definition: moo_scilist.c:198
int moo_target_table_find_index(moo_target_table *self, const char *targname)
find target indexspec in TARGET_TABLE
moo_resp * moo_compute_resp(moo_scilist *scilist, moo_atm *atm, moo_flx *flx, moo_compute_resp_params *params)
Compute instrumental response.
double moo_pfits_get_tel_airm_end(const cpl_propertylist *plist)
find out the TEL.AIRM.END value
Definition: moo_pfits.c:1315
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
moo_tcheby_polynomial * moo_tcheby_polynomial_fit(cpl_bivector *data, int degree, double xmin, double xmax)
Computes Tchebitchev transformation of data.
Definition: moo_utils.c:573
cpl_vector * moo_median_filter(cpl_vector *v, int winhsize)
Apply a median filter to a vector.
Definition: moo_utils.c:1730
FLX format.
Definition: moo_flx.h:43
the different type of detectors