KMOS Pipeline Reference Manual 4.5.10
kmos_molecfit_calctrans.c
1/*
2 * This file is part of the KMOS 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#include <regex.h>
23#endif
24
25/*----------------------------------------------------------------------------*/
29/*----------------------------------------------------------------------------*/
30
31#include "kmos_molecfit.h"
32
33/*----------------------------------------------------------------------------*/
37/*----------------------------------------------------------------------------*/
38
39/*----------------------------------------------------------------------------*/
43/*----------------------------------------------------------------------------*/
44
45typedef struct {
46 kmos_molecfit_parameter mf; /* Generic molecfit parameter */
47 cpl_propertylist *pl_atmos_params; /* Primary property list header in the ATMOS_PARM file */
48 cpl_table *atmprof[N_IFUS]; /* cpl_table in the ATMOS_PARM file (one for each extension DATA executed in kmos_molecfit_model) */
49 cpl_propertylist *pl_best_fit_params; /* Primary property list header in the BEST_FIT_PARM file */
50 cpl_table *res_table[N_IFUS]; /* cpl_table in the BEST_FIT_PARM file (one for each extension DATA executed in kmos_molecfit_model) */
51 mf_calctrans_convolution_results *results[N_IFUS]; /* Results of telluric corrections after execute mf_calctrans_convolution */
52 const char *scale_pwv;
53 double pwv_sci;
54 double pwv_ratio;
55 double h2o_col_mm;
56
57} kmos_molecfit_calctrans_parameter;
58
59
60/*----------------------------------------------------------------------------*/
64/*----------------------------------------------------------------------------*/
65
66/* Fill the internal KMOS configuration file */
67static kmos_molecfit_calctrans_parameter * kmos_molecfit_calctrans_conf(
68 const cpl_parameterlist *list);
69
70/* Use the kmos_molecfit_model output to configure kmos_molecfit_caltrans */
71static cpl_error_code kmos_molecfit_calctrans_frames_conf(
72 kmos_molecfit_calctrans_parameter *conf, cpl_frameset *frameset, const cpl_parameterlist *parlist);
73
74/* Fill the molecfit specific recipe configuration file */
75static cpl_error_code kmos_molecfit_calctrans_mf_conf(
76 kmos_molecfit_calctrans_parameter *conf,
77 double median,
78 mf_parameters_config *config_parameters);
79
80/* Clean variables allocated in the recipe */
81static void kmos_molecfit_calctrans_clean(
82 kmos_molecfit_calctrans_parameter *conf);
83
84/*----------------------------------------------------------------------------*/
88/*----------------------------------------------------------------------------*/
89
90#define RECIPE_NAME KMOS_MOLECFIT_CALCTRANS
91#define CONTEXT "kmos."RECIPE_NAME
92
93static char kmos_molecfit_calctrans_description[] =
94 "This recipe applies the results from kmos_molecfit_model and runs calctrans to calculate the \n"
95 "telluric correction for scientific input data. Scientific input data can have category: \n"
96 " - STAR_SPEC (24 DATA plus 24 NOISE extensions)\n"
97 " - EXTRACT_SPEC (24 DATA extensions, additional 24 NOISE extensions are optional)\n"
98 " - SCIENCE (24 DATA extensions, additional 24 NOISE extensions are optional)\n"
99 " - SCI_RECONSTRUCTED (24 DATA extensions, additional 24 NOISE extensions are optional)\n"
100 "It is not mandatory that all the DATA extension contains data.\n"
101 "It accounts for the difference in airmass between the input model and the input scientific data. \n"
102 "It accounts for different spectral resolutions between the various KMOS IFUs.\n"
103 "\n"
104 "Input files: (It's mandatory to provide 1 file only of type A) \n"
105 "\n"
106 " DO KMOS \n"
107 " category Type required Explanation \n"
108 " -------- ----- -------- ----------- \n"
109 " STAR_SPEC F1I A The science spectrum to compute the telluric correction for (1D spectrum, IMAGE format).\n"
110 " EXTRACT_SPEC F1I A The science spectrum to compute the telluric correction for (1D spectrum, IMAGE format).\n"
111 " SCIENCE F3I A The science spectrum to compute the telluric correction for (3D cube, IMAGE format).\n"
112 " SCI_RECONSTRUCTED F3I A The science spectrum to compute the telluric correction for (3D cube, IMAGE format).\n"
113 " ATMOS_PARM F1L Y Atmospheric model as computed by the recipe kmos_molecfit_model.\n"
114 " BEST_FIT_PARM F1L Y Best fitting model and parameters as computed by the recipe kmos_molecfit_model.\n"
115 " KERNEL_LIBRARY F2I N The kernel library; must be the same grating as the other inputs.\n"
116 "\n"
117 "Output files: \n"
118 "\n"
119 " DO KMOS \n"
120 " category Type Explanation \n"
121 " -------- ----- ----------- \n"
122 " TELLURIC_DATA F1L Telluric correction and intermediate products for each IFU. Output fits file with 48 ext. (24-data and 24-error, in TABLE format).\n"
123 " Each data extension contains the telluric correction for one IFU.\n"
124 " TELLURIC_CORR F1I Telluric correction for each IFU. Output fits file with 48 ext. (24-data and 24-error, in IMAGE format).\n"
125 " Each data extension contains the telluric correction for one IFU.\n"
126 "\n"
127 "----------------------------------------------------------------------------\n"
128 "The input atmospheric model and best fitting parameters (as obtained in the kmos_molecfit_model) for a given IFU.X are used to generate a telluric correction for IFU.Y.\n"
129 "The instrumental spectral resolution of IFU.Y is taken into account if a kernel library is provided.\n"
130 "The mapping between IFU.X and IFU.Y is either specified by the user or automatic.\n"
131 "The difference in airmass between the data used in kmos_molecfit_model and the input data of kmos_molecfit_calctrans are taken into account.\n"
132 "\n";
133
134/* Standard CPL recipe definition */
135cpl_recipe_define( kmos_molecfit_calctrans,
136 KMOS_BINARY_VERSION,
137 "Jose A. Escartin, Yves Jung",
138 "https://support.eso.org/",
139 "2017",
140 "Read the results from kmos_molecfit_model and computes the telluric correction for a scientific input data.",
141 kmos_molecfit_calctrans_description);
142
143
144/*----------------------------------------------------------------------------*/
148/*----------------------------------------------------------------------------*/
149
152/*----------------------------------------------------------------------------*/
156/*----------------------------------------------------------------------------*/
157
158/*----------------------------------------------------------------------------*/
168/*----------------------------------------------------------------------------*/
169static int kmos_molecfit_calctrans(
170 cpl_frameset *frameset, const cpl_parameterlist *parlist)
171{
172 /* Check initial Entries */
173 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
174 return cpl_error_get_code();
175 }
176
177 /* Get initial errorstate */
178 cpl_errorstate initial_errorstate = cpl_errorstate_get();
179
180 /* Extract and verify data in the parameters of the recipe */
181 cpl_msg_info(cpl_func, "Configuring initial parameters in the recipe ...");
182 kmos_molecfit_calctrans_parameter *conf = kmos_molecfit_calctrans_conf(parlist);
183 cpl_error_ensure(conf, CPL_ERROR_ILLEGAL_INPUT,
184 return (int)CPL_ERROR_ILLEGAL_INPUT, "Problems with the configuration parameters");
185
186
187 /* Complete configuration with the ATMOS_PARAM and BEST_FIT_PARM, outputs of the recipe kmos_molecfit_model */
188 if (kmos_molecfit_calctrans_frames_conf(conf, frameset, parlist) != CPL_ERROR_NONE) {
189 if (conf) kmos_molecfit_calctrans_clean(conf);
190 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
191 "Configuration with kmos_calctrans_model output failed!");
192 }
193
194 if (!(conf->mf.fit_wavelenght.fit)) cpl_msg_info(cpl_func, "Not fit wavelenght!");
195 if (!(conf->mf.fit_continuum.fit) ) cpl_msg_info(cpl_func, "Not fit continuum!" );
196
197 /* Loading data spectrums */
198 cpl_error_code err = kmos_molecfit_load_spectrums(frameset, &(conf->mf), RECIPE_NAME);
199 if(err != CPL_ERROR_NONE) {
200 kmos_molecfit_calctrans_clean(conf);
201 return err;
202 }
203
204 /* Loading kernels */
205 const cpl_frame *frmKernel = cpl_frameset_find(frameset, KERNEL_LIBRARY);
206 cpl_error_code sKernels_e;
207 if (frmKernel && conf->mf.use_input_kernel) {
208
209 if (kmos_molecfit_load_kernels(frmKernel, &(conf->mf)) != CPL_ERROR_NONE) {
210 kmos_molecfit_calctrans_clean(conf);
211 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
212 "Loading convolution kernel data in the input frameset failed!");
213 }
214
215 sKernels_e = kmos_molecfit_save(frameset, frameset, parlist, RECIPE_NAME, conf->mf.parms, CALCTRANS_KERNEL_LIBRARY, conf->mf.grating.name, conf->mf.suppress_extension, NULL);
216 if (sKernels_e != CPL_ERROR_NONE){
217 kmos_molecfit_calctrans_clean(conf);
218 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
219 "Saving generic multi-extension output fits file ('%s') failed!",
220 CALCTRANS_KERNEL_LIBRARY);
221 }
222
223 } else {
224
225 if (frmKernel) {
226 cpl_msg_warning(cpl_func, "Kernel is provided, but use_input_kernel = false !");
227 } else if (conf->mf.use_input_kernel){
228 cpl_msg_warning(cpl_func, "Kernel isn't provided, but use_input_kernel = true !");
229 }
230 cpl_msg_info(cpl_func, "Using the default molecfit kernels -> With the values inside BEST_FIT_PARMS!");
231 }
232
233 cpl_msg_info(cpl_func, " +++ All input data loaded successfully! +++");
234
235
236 /* Saving generic multi-extension output *.fits file */
237
238 const char * telcorr_file = "telcorr.fits";
239
240 cpl_msg_info(cpl_func, "Saving generic multi-extension output fits file ('%s','%s') ...", TELLURIC_DATA, TELLURIC);
241 cpl_error_code sTel_data = kmos_molecfit_save(frameset, frameset, parlist, RECIPE_NAME, conf->mf.parms, TELLURIC_DATA, conf->mf.grating.name, conf->mf.suppress_extension, NULL);
242 //cpl_error_code sTel_img = kmos_molecfit_save(frameset, frameset, parlist, RECIPE_NAME, conf->mf.parms, TELLURIC_CORR, conf->mf.grating.name, conf->mf.suppress_extension, NULL);
243 cpl_error_code sTel_img = cpl_propertylist_save(conf->mf.header_spectrums, telcorr_file , CPL_IO_CREATE);
244
245
246 if (sTel_data != CPL_ERROR_NONE || sTel_img != CPL_ERROR_NONE) {
247 kmos_molecfit_calctrans_clean(conf);
248 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
249 "Saving generic multi-extension output fits files ('%s','%s') failed!", TELLURIC_DATA, TELLURIC_CORR);
250 }
251
252
253 /* Constant values in Molecfit executions */
254 const double wlmin = -1.;
255 const double wlmax = -1.;
256
257 /* Get molecules in the grating */
258 cpl_table *molecules = conf->mf.grating.molecules;
259
260 /*** General configuration of Molecfit for LBLRTM and LNFL calls ***/
261
262 /* Initialize mf_configuration structure */
263 mf_configuration *mf_config = mf_configuration_create();
264 if (!mf_config) err = CPL_ERROR_NULL_INPUT;
265
266 /* Update the molecfit configuration with the data primary header */
267 err = mf_parameters_config_update_with_header_keywords(mf_config->parameters, conf->mf.header_spectrums);
268 if (err != CPL_ERROR_NONE) {
269 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
270 "Error updating molecfit parameters with the raw primary header configuration");
271 }
272
273 /* Execute molecfit (lblrtm and convolution) */
274 for (cpl_size n_ifuY = 0; n_ifuY < N_IFUS; n_ifuY++) {
275
276 /* Get specific IFU */
277 kmos_spectrum *ifuY = &(conf->mf.ifus[n_ifuY]);
278
279 cpl_msg_info(cpl_func, "IFU NUMBER : %d", ifuY->num);
280
281 /* Running Molecfit lblrtm only in IFU_Y (when ifuY->num is equal to ifuY->map) */
282 if (ifuY->num == ifuY->map) {
283
284 /* Configuration variables */
285 cpl_msg_info(cpl_func, "Building molecfict configuration variable in %s ...", ifuY->name);
286
287 /* Check previous executions in ifuY */
288 if (conf->results[n_ifuY]) {
289 err = cpl_error_set_message(cpl_func, CPL_ERROR_DUPLICATING_STREAM,
290 "Unexpected error: Molecfit call mf_calctrans_lblrtm(...) already executed in this IFU");
291 }
292
293 /* Building molecfic configuration variable ifuY */
294 if (!err) err = kmos_molecfit_calctrans_mf_conf(conf, ifuY->median, mf_config->parameters);
295
296 //mf_config->parameters->inputs.silent_external_bins = CPL_FALSE;
297 //cpl_table_dump(conf->res_table[n_ifuY], 0, cpl_table_get_nrow(conf->res_table[n_ifuY]), stdout);
298
299 /* CALL Molecfit MF_LBLRTM routine */
300 if (!err) {
301
302 /* Create input molecfit spec format */
303 cpl_table *spec_telluriccorr_lblrtm = mf_spectrum_create(mf_config->parameters, ifuY->data);
304
305 /* CALL MOLECFIT */
306 cpl_msg_info(cpl_func, "Call mf_calctrans_lblrtm(...), in IFU_Y->map=%d),(num=%d,name=%s)", ifuY->map, ifuY->num, ifuY->name);
307 mf_calctrans_lblrtm_results *lblrtm_results;
308 lblrtm_results = mf_calctrans_lblrtm( mf_config, /* mf_configuration *config */
309 spec_telluriccorr_lblrtm, /* const cpl_table *spec_telluriccorr */
310 molecules, /* cpl_table *molectab */
311 wlmin, /* double wl_start */
312 wlmax, /* double wl_end */
313 conf->atmprof[n_ifuY], /* cpl_table *atmprof */
314 conf->res_table[n_ifuY]); /* cpl_table *res_table */
315
316 cpl_table_delete(spec_telluriccorr_lblrtm);
317
318 /* Check call results */
319 err = cpl_error_get_code();
320 if (err != CPL_ERROR_NONE) {
321 cpl_msg_info(cpl_func, "Molecfit call mf_calctrans_lblrtm(...) failed! in %s -> error: %s", ifuY->name, cpl_error_get_message());
322 } else if (!lblrtm_results) {
323 err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
324 "Molecfit call (mf_run_calctrans_lblrtm) doesn't provide error but the results structure is NULL!");
325 } else {
326 cpl_msg_info(cpl_func, "Molecfit call mf_calctrans_lblrtm(...) run successfully! in %s ...", ifuY->name);
327
328 /* Execute molecfit convolution: including ifuX == ifuY */
329 for (cpl_size n_ifuX = 0; n_ifuX < N_IFUS && !err; n_ifuX++) {
330
331 /* Get specifics ifus */
332 kmos_spectrum *ifuX = &(conf->mf.ifus[n_ifuX]);
333
334 /* Running Molecfit convolution in each IFU_X(ifu->num) match with the reference math with IFU_Y (when ifuX->map == ifu->num) */
335 if (ifuX->map == ifuY->num) {
336
337 /* Check previous executions in ifuX */
338 if (conf->results[n_ifuX]) {
339
340 err = cpl_error_set_message(cpl_func, CPL_ERROR_DUPLICATING_STREAM,
341 "Unexpected error: Molecfit call mf_calctrans_convolution(...) already executed in this IFU");
342 } else {
343
344 /* Building molecfic configuration variable */
345 cpl_msg_info(cpl_func, "Building molecfict configuration variable ... ");
346
347 /* Initialize config MF_PARAMETERS structure */
348 mf_parameters_config *config_parameters_ifuX = mf_parameters_config_create();
349 if (!config_parameters_ifuX) err = CPL_ERROR_NONE;
350
351 /* Update the molecfit configuration with the data primary header */
352 err = mf_parameters_config_update_with_header_keywords(config_parameters_ifuX, conf->mf.header_spectrums);
353 if (err != CPL_ERROR_NONE) {
354 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
355 "Error updating molecfit parameters with the raw primary header configuration");
356 }
357
358 /* Building molecfic configuration variable ifuX */
359 if (!err) err = kmos_molecfit_calctrans_mf_conf(conf, ifuY->median, config_parameters_ifuX);
360
361 if (!err) {
362
363 /* Create input molecfit spec format */
364 cpl_table *spec_telluriccorr_convolution = mf_spectrum_create(config_parameters_ifuX, ifuY->data);
365
366 /* CALL MOLECFIT : Convolution of the model transmission spectrum with the kernel */
367 cpl_msg_info(cpl_func, "Call mf_calctrans_convolution(...), in IFU_X->map=%d),(num=%d,name=%s) IFU_Y->map=%d),(num=%d,name=%s)",
368 ifuX->map, ifuX->num, ifuX->name, ifuY->map, ifuY->num, ifuY->name);
369 conf->results[n_ifuX] = mf_calctrans_convolution( config_parameters_ifuX, /* mf_parameters_config *config */
370 lblrtm_results, /* mf_calctrans_lblrtm_results *lblrtm_results */
371 ifuY->header_ext_data, /* const cpl_propertylist *header_spec */
372 spec_telluriccorr_convolution, /* const cpl_table *spec_telluriccorr */
373 ifuX->kernel.header_ext_data, /* const cpl_propertylist *header_kernel */
374 ifuX->kernel.data, /* const cpl_matrix *kernel */
375 wlmin, /* double wl_start */
376 wlmax, /* double wl_end */
377 conf->res_table[n_ifuY]); /* cpl_table *res_table */
378
379 cpl_table_delete(spec_telluriccorr_convolution);
380
381 /* Check call results */
382 err = cpl_error_get_code();
383 if (err != CPL_ERROR_NONE) {
384 cpl_msg_info(cpl_func, "Molecfit call mf_calctrans_convolution(...) failed! in %s -> error: %s", ifuX->name, cpl_error_get_message());
385 } else if (!(conf->results[n_ifuX])) {
386 err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
387 "Molecfit call (mf_run_calctrans_convolution) doesn't provide error but the results structure is NULL!");
388 } else {
389 cpl_msg_info(cpl_func, "Molecfit call mf_calctrans_convolution(...) run successfully! in %s ...", ifuX->name);
390 }
391 }
392
393 /* Cleanup mf_calctrans_lnfl(...) call */
394 if (config_parameters_ifuX) mf_parameters_config_delete(config_parameters_ifuX);
395 }
396 }
397 }
398
399
400 /* Cleanup */
401 mf_calctrans_lblrtm_results_delete(lblrtm_results);
402 }
403 }
404 }
405 }
406
407 /* Cleanup: General configuration of Molecfit for LBLRTM and LNFL calls */
408 if (mf_config) mf_configuration_delete(mf_config);
409
410 /* Check errors in Molecfit calls */
411 if (err != CPL_ERROR_NONE) {
412 kmos_molecfit_calctrans_clean(conf);
413 return cpl_error_set_message(cpl_func, err,
414 "Call to Molecfit (MF_LBLRTM/MF_LNFL) failed, err_str: %s",
415 cpl_error_get_message());
416 }
417
418 /*QC Parameters to be used in kmos_combine*/
419 cpl_propertylist * tel_primary_header = kmclipm_propertylist_load(telcorr_file, 0); //kmo_dfs_load_primary_header(frameset,TELLURIC_CORR);
420 cpl_propertylist * best_fit_header = kmclipm_propertylist_load(
421 cpl_frame_get_filename(cpl_frameset_find(frameset, BEST_FIT_PARM)),0);
422
423 if (cpl_propertylist_has(best_fit_header, "ESO TEL AIRM END")){
424
425 float airm_end = cpl_propertylist_get_double(best_fit_header, "ESO TEL AIRM END");
426 float airm_start = cpl_propertylist_get_double(best_fit_header, "ESO TEL AIRM START");
427 kmclipm_update_property_double(tel_primary_header, QC_PARAM_AIRM_STD,
428 (airm_end+airm_start)/2.0, QC_PARAM_AIRM_STD_TXT);
429 }
430
431 if (cpl_propertylist_has(best_fit_header, QC_PARAM_H2O_AVG)){
432
433 kmclipm_update_property_double(tel_primary_header, QC_PARAM_H2O_AVG,
434 cpl_propertylist_get_double(best_fit_header, QC_PARAM_H2O_AVG),
435 QC_PARAM_H2O_AVG_TXT);
436 }
437
438 if (cpl_propertylist_has(best_fit_header, QC_PARAM_H2O_RMS)){
439
440 kmclipm_update_property_double(tel_primary_header, QC_PARAM_H2O_RMS,
441 cpl_propertylist_get_double(best_fit_header, QC_PARAM_H2O_RMS),
442 QC_PARAM_H2O_RMS_TXT);
443 }
444
445 if (cpl_propertylist_has(best_fit_header, QC_PARAM_MEAS_IWV)){
446
447 float meas_iwv = cpl_propertylist_get_double(best_fit_header, QC_PARAM_MEAS_IWV);
448 kmclipm_update_property_double(tel_primary_header, QC_PARAM_MEAS_IWV, meas_iwv,
449 QC_PARAM_MEAS_IWV_TXT);
450 kmclipm_update_property_double(tel_primary_header, QC_PARAM_H2O_RATIO,
451 cpl_propertylist_get_double(best_fit_header, QC_PARAM_H2O_AVG)/meas_iwv,
452 QC_PARAM_H2O_RATIO_TXT);
453 }
454
455 if (cpl_propertylist_has(best_fit_header, QC_PARAM_MEAS_IWV30D)){
456 kmclipm_update_property_double(tel_primary_header, QC_PARAM_MEAS_IWV30D,
457 cpl_propertylist_get_double(best_fit_header, QC_PARAM_MEAS_IWV30D),
458 QC_PARAM_MEAS_IWV30D_TXT);
459 }
460
461 if (cpl_propertylist_has(best_fit_header, QC_PARAM_H2O_DELTA)){
462 kmclipm_update_property_double(tel_primary_header, QC_PARAM_H2O_DELTA,
463 cpl_propertylist_get_double(best_fit_header, QC_PARAM_H2O_DELTA),
464 QC_PARAM_H2O_DELTA_TXT);
465 }
466
467 /*QC Parameters to be used in kmos_combine --- MOVE TO NEW FUNCTION ---*/
468
469 // CHANGE FOR SUPPRESS-EXTENSION
470 const char * suffix= "";
471
472 if (!conf->mf.suppress_extension) {
473 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, TELLURIC_DATA), TRUE, FALSE);
474 }
475
476
477 //cpl_propertylist_update_string(tel_primary_header, KEY_PRODCATG, "ANCILLARY.TELLCORR") ;
478 cpl_propertylist_update_string(tel_primary_header, KEY_PRODCATG, "ANCILLARY.KMOS.SPECTRUM.TELLURIC") ;
479
480
481 cpl_frame *frame_telluric_corr = kmo_dfs_get_frame(frameset, TELLURIC_DATA);
482 kmo_dfs_save_main_header(frameset, TELLURIC_CORR , suffix, frame_telluric_corr, tel_primary_header, parlist, cpl_func);
483
484
485 /* Save data in each the IFU */
486 for (cpl_size n_ifu = 0; n_ifu < N_IFUS; n_ifu++) {
487
488 /* Get specifics ifus */
489 kmos_spectrum *ifu = &(conf->mf.ifus[n_ifu]);
490
491 cpl_table *telluric_data = (conf->results[n_ifu])->spec_telluriccorr_format;
492 double *data = NULL;
493 cpl_vector *telluric_vec = NULL;
494 if (telluric_data) {
495
496 /* Wrap the data */
497 data = cpl_table_get_data_double(telluric_data, MF_COL_OUT_TELLURIC_CORR);
498 cpl_vector *vAux = cpl_vector_wrap(cpl_table_get_nrow(telluric_data), data);
499 telluric_vec = cpl_vector_duplicate(vAux);
500 cpl_vector_unwrap(vAux);
501
502 double mtrans_max = cpl_vector_get_max(telluric_vec);
503 //cpl_vector_divide_scalar(telluric_vec, mtrans_max);
504 cpl_msg_info(cpl_func, "Saving telluric data and image in IFU=%02d ... (Convolution executed) --> Max_value(%lf)", ifu->num, mtrans_max);
505
506 } else {
507 cpl_msg_info(cpl_func, "Saving data in IFU=%02d ...", ifu->num);
508 }
509
510 cpl_propertylist *header_data;
511 cpl_propertylist *header_noise;
512 if (ifu->num == ifu->map) {
513 header_data = cpl_propertylist_duplicate(ifu->header_ext_data);
514 header_noise = cpl_propertylist_duplicate(ifu->header_ext_noise);
515 } else {
516
517 kmos_spectrum *ifu_ref = &(conf->mf.ifus[ifu->map - 1]);
518 header_data = cpl_propertylist_duplicate(ifu_ref->header_ext_data);
519 header_noise = cpl_propertylist_duplicate(ifu_ref->header_ext_noise);
520
521 char* name_data = cpl_sprintf("IFU.%d.DATA", ifu->num);
522 cpl_propertylist_update_string(header_data, EXTNAME, name_data);
523 cpl_free(name_data);
524
525 char* name_noise = cpl_sprintf("IFU.%d.NOISE", ifu->num);
526 cpl_propertylist_update_string(header_noise, EXTNAME, name_noise);
527 cpl_free(name_noise);
528 }
529
530 cpl_propertylist_erase(header_data, "ESO QC CUBE_UNIT");
531 cpl_propertylist_erase(header_noise, "ESO QC CUBE_UNIT");
532 cpl_propertylist_erase(header_data, "BUNIT");
533 cpl_propertylist_erase(header_noise, "BUNIT");
534
535 if ((telluric_data== NULL) && (telluric_vec==NULL)) {
536 kmos_all_clean_plist(header_data) ;
537 }
538 kmos_all_clean_plist(header_noise) ;
539
540 //cpl_propertylist_dump(header_data, stdout);
541
542 /* Save cpl_table with the data of the mf_convolution execution */
543 sTel_data = kmos_molecfit_save_mf_results(header_data, header_noise,
544 TELLURIC_DATA, conf->mf.grating.name, conf->mf.suppress_extension, NULL, NULL, telluric_data, NULL);
545 if (sTel_data != CPL_ERROR_NONE) {
546 if (telluric_data) cpl_table_delete(telluric_data);
547 if (telluric_vec) cpl_vector_delete(telluric_vec);
548 cpl_propertylist_delete(header_data);
549 cpl_propertylist_delete(header_noise);
550 kmos_molecfit_calctrans_clean(conf);
551 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
552 "Saving Molecfit output fits file ('%s') failed!, ext=%lld", TELLURIC_DATA, n_ifu + 1);
553 }
554
555
556 /* Save data image with the data obtained in the mf_convolution execution */
557
558 sTel_img = kmos_molecfit_save_mf_results(header_data, header_noise,
559 TELLURIC_CORR, conf->mf.grating.name, conf->mf.suppress_extension, NULL, NULL, NULL, telluric_vec);
560 if (sTel_img != CPL_ERROR_NONE) {
561 if (telluric_vec) cpl_vector_delete(telluric_vec);
562 cpl_propertylist_delete(header_data);
563 cpl_propertylist_delete(header_noise);
564 kmos_molecfit_calctrans_clean(conf);
565 return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
566 "Saving Molecfit output fits file ('%s') failed!, ext=%lld", TELLURIC_CORR, n_ifu + 1);
567 }
568
569 /* Save kernel used in Molecfit */
570 if (frmKernel && conf->mf.use_input_kernel) {
571
572 cpl_propertylist *header_kernel_data = ifu->kernel.header_ext_data ? ifu->kernel.header_ext_data : ifu->header_ext_data;
573 cpl_propertylist *header_kernel_noise = ifu->kernel.header_ext_noise ? ifu->kernel.header_ext_noise : ifu->header_ext_noise;
574
575 cpl_matrix *kernel = NULL;
576 if (conf->results[n_ifu]) {
577 if ((conf->results[n_ifu])->kernel_resampled_normalized) kernel = (conf->results[n_ifu])->kernel_resampled_normalized;
578 }
579
580 sKernels_e = kmos_molecfit_save_mf_results(header_kernel_data, header_kernel_noise,
581 CALCTRANS_KERNEL_LIBRARY, conf->mf.grating.name, conf->mf.suppress_extension, NULL, kernel, NULL, NULL);
582
583 if (sKernels_e != CPL_ERROR_NONE) {
584 if (telluric_vec) cpl_vector_delete(telluric_vec);
585 cpl_propertylist_delete(header_data);
586 cpl_propertylist_delete(header_noise);
587 kmos_molecfit_calctrans_clean(conf);
588 err = cpl_error_set_message(cpl_func, cpl_error_get_code(),
589 "Saving Molecfit output fits file ('%s') failed!",
590 CALCTRANS_KERNEL_LIBRARY);
591 }
592 }
593
594
595 /* Cleanup */
596 if (telluric_vec) cpl_vector_delete(telluric_vec);
597 cpl_propertylist_delete(header_data);
598 cpl_propertylist_delete(header_noise);
599 //if (telluric_data) cpl_table_delete(telluric_data);
600 unlink(telcorr_file);
601
602 }
603
604
605 if (conf->pwv_ratio!=1.0){
606
607 const cpl_frame *frmAtmosParm = cpl_frameset_find(frameset, ATMOS_PARM);
608 const char *fileAtmosParm = cpl_frame_get_filename(frmAtmosParm);
609
610 //cpl_msg_info(cpl_func, "We get to this at least. 0.25 - %s", cpl_error_get_message());
611 kmos_molecfit_save(frameset, frameset, parlist, RECIPE_NAME, conf->mf.parms, CALCTRANS_ATMOS_PARM,conf->mf.grating.name, conf->mf.suppress_extension, NULL);
612 //cpl_msg_info(cpl_func, "Error up to now -> %s ", cpl_error_get_message());
613
614 for (cpl_size n_ifu = 1; n_ifu <= N_IFUS; n_ifu++) {
615
616 int j = 2*n_ifu-1;
617 cpl_propertylist *header_atmos_data = cpl_propertylist_load(fileAtmosParm,j);
618 cpl_propertylist *header_atmos_noise = cpl_propertylist_load(fileAtmosParm, j+1);
619 if (conf->atmprof[n_ifu-1]== NULL) {
620 kmos_all_clean_plist(header_atmos_data) ;
621 }
622 kmos_all_clean_plist(header_atmos_noise) ;
623
624 //cpl_table * atmos_tbl_noise = kmclipm_table_load( frmAtmosParm, j, 0 );
625
626 //sKernels_e = kmos_molecfit_save_mf_results(header_atmos_data, header_atmos_noise,
627 // CALCTRANS_ATMOS_PARM, conf->mf.grating.name, conf->mf.suppress_extension, NULL, conf->atmprof[n_ifu-1], NULL, NULL);
628 sKernels_e = kmo_dfs_save_table(conf->atmprof[n_ifu-1], CALCTRANS_ATMOS_PARM, suffix ,header_atmos_data);
629 //sKernels_e = kmo_dfs_save_table(atmos_tbl_noise, CALCTRANS_ATMOS_PARM, suffix ,header_atmos_noise);
630
631 if (sKernels_e != CPL_ERROR_NONE) {
632 cpl_propertylist_delete(header_atmos_data);
633 cpl_propertylist_delete(header_atmos_noise);
634 //cpl_table_delete(atmos_tbl_noise);
635 kmos_molecfit_calctrans_clean(conf);
636 err = cpl_error_set_message(cpl_func, cpl_error_get_code(),
637 "Saving Molecfit output fits file ('%s') failed!",
638 CALCTRANS_ATMOS_PARM);
639 }
640
641 }
642
643
644 }
645
646
647
648 /* Cleanup configuration */
649 cpl_msg_info(cpl_func,"Cleaning variables ...");
650 kmos_molecfit_calctrans_clean(conf);
651
652 /* Check Recipe status and end */
653 if (cpl_errorstate_is_equal(initial_errorstate) && cpl_error_get_code() == CPL_ERROR_NONE ) {
654 cpl_msg_info(cpl_func,"Recipe successfully!");
655 } else {
656 /* Dump the error history since recipe execution start. At this point the recipe cannot recover from the error */
657 cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
658 cpl_msg_info(cpl_func,"Recipe failed!, error(%d)=%s", cpl_error_get_code(), cpl_error_get_message());
659 }
660
661 return (int)cpl_error_get_code();
662}
663
666/*----------------------------------------------------------------------------*/
675/*----------------------------------------------------------------------------*/
676static cpl_error_code kmos_molecfit_calctrans_fill_parameterlist(
677 cpl_parameterlist *self)
678{
679 /* Add the different default parameters to the recipe */
680 cpl_errorstate prestate = cpl_errorstate_get();
681
682 /* Fill the parameters list */
683 cpl_error_code e;
684 cpl_boolean range = CPL_TRUE;
685 const void *dummyMin = NULL;
686 const void *dummyMax = NULL;
687
688
689 /* --KMOS_MOLECFIT_PARAMETER_USE_INPUT_KERNEL */
690 cpl_boolean use_input_kernel = CPL_TRUE;
691 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_USE_INPUT_KERNEL,
692 !range, dummyMin, dummyMax, CPL_TYPE_BOOL, &use_input_kernel,
693 "In order to use kernel library provide by the user.", CPL_FALSE);
694 if (e != CPL_ERROR_NONE) return (int)e;
695
696
697 /*** Mapping IFUS ***/
698 int automatic = -1.;
699
700 /* --KMOS_MOLECFIT_PARAMETER_IFU_1 */
701 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_1,
702 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
703 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 1 .", CPL_FALSE);
704 if (e != CPL_ERROR_NONE) return (int)e;
705
706 /* --KMOS_MOLECFIT_PARAMETER_IFU_2 */
707 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_2,
708 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
709 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 2 .", CPL_FALSE);
710 if (e != CPL_ERROR_NONE) return (int)e;
711
712 /* --KMOS_MOLECFIT_PARAMETER_IFU_3 */
713 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_3,
714 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
715 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 3 .", CPL_FALSE);
716 if (e != CPL_ERROR_NONE) return (int)e;
717
718 /* --KMOS_MOLECFIT_PARAMETER_IFU_4 */
719 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_4,
720 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
721 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 4 .", CPL_FALSE);
722 if (e != CPL_ERROR_NONE) return (int)e;
723
724 /* --KMOS_MOLECFIT_PARAMETER_IFU_5 */
725 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_5,
726 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
727 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 5 .", CPL_FALSE);
728 if (e != CPL_ERROR_NONE) return (int)e;
729
730 /* --KMOS_MOLECFIT_PARAMETER_IFU_6 */
731 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_6,
732 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
733 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 6 .", CPL_FALSE);
734 if (e != CPL_ERROR_NONE) return (int)e;
735
736 /* --KMOS_MOLECFIT_PARAMETER_IFU_7 */
737 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_7,
738 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
739 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 7 .", CPL_FALSE);
740 if (e != CPL_ERROR_NONE) return (int)e;
741
742 /* --KMOS_MOLECFIT_PARAMETER_IFU_8 */
743 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_8,
744 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
745 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 8 .", CPL_FALSE);
746 if (e != CPL_ERROR_NONE) return (int)e;
747
748 /* --KMOS_MOLECFIT_PARAMETER_IFU_9 */
749 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_9,
750 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
751 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 9 .", CPL_FALSE);
752 if (e != CPL_ERROR_NONE) return (int)e;
753
754 /* --KMOS_MOLECFIT_PARAMETER_IFU_10 */
755 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_10,
756 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
757 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 10.", CPL_FALSE);
758 if (e != CPL_ERROR_NONE) return (int)e;
759
760 /* --KMOS_MOLECFIT_PARAMETER_IFU_11 */
761 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_11,
762 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
763 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 11.", CPL_FALSE);
764 if (e != CPL_ERROR_NONE) return (int)e;
765
766 /* --KMOS_MOLECFIT_PARAMETER_IFU_12 */
767 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_12,
768 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
769 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 12.", CPL_FALSE);
770 if (e != CPL_ERROR_NONE) return (int)e;
771
772 /* --KMOS_MOLECFIT_PARAMETER_IFU_13 */
773 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_13,
774 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
775 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 13.", CPL_FALSE);
776 if (e != CPL_ERROR_NONE) return (int)e;
777
778 /* --KMOS_MOLECFIT_PARAMETER_IFU_14 */
779 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_14,
780 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
781 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 14.", CPL_FALSE);
782 if (e != CPL_ERROR_NONE) return (int)e;
783
784 /* --KMOS_MOLECFIT_PARAMETER_IFU_15 */
785 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_15,
786 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
787 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 15.", CPL_FALSE);
788 if (e != CPL_ERROR_NONE) return (int)e;
789
790 /* --KMOS_MOLECFIT_PARAMETER_IFU_16 */
791 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_16,
792 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
793 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 16.", CPL_FALSE);
794 if (e != CPL_ERROR_NONE) return (int)e;
795
796 /* --KMOS_MOLECFIT_PARAMETER_IFU_17 */
797 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_17,
798 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
799 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 17.", CPL_FALSE);
800 if (e != CPL_ERROR_NONE) return (int)e;
801
802 /* --KMOS_MOLECFIT_PARAMETER_IFU_18 */
803 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_18,
804 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
805 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 18.", CPL_FALSE);
806 if (e != CPL_ERROR_NONE) return (int)e;
807
808 /* --KMOS_MOLECFIT_PARAMETER_IFU_19 */
809 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_19,
810 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
811 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 19.", CPL_FALSE);
812 if (e != CPL_ERROR_NONE) return (int)e;
813
814 /* --KMOS_MOLECFIT_PARAMETER_IFU_20 */
815 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_20,
816 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
817 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 20.", CPL_FALSE);
818 if (e != CPL_ERROR_NONE) return (int)e;
819
820 /* --KMOS_MOLECFIT_PARAMETER_IFU_21 */
821 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_21,
822 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
823 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 21.", CPL_FALSE);
824 if (e != CPL_ERROR_NONE) return (int)e;
825
826 /* --KMOS_MOLECFIT_PARAMETER_IFU_22 */
827 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_22,
828 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
829 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 22.", CPL_FALSE);
830 if (e != CPL_ERROR_NONE) return (int)e;
831
832 /* --KMOS_MOLECFIT_PARAMETER_IFU_23 */
833 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_23,
834 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
835 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 23.", CPL_FALSE);
836 if (e != CPL_ERROR_NONE) return (int)e;
837
838 /* --KMOS_MOLECFIT_PARAMETER_IFU_24 */
839 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_IFU_24,
840 !range, dummyMin, dummyMax, CPL_TYPE_INT, &automatic,
841 "IFU number in ATMOS_PARM and BEST_FIT_PARM to be used to compute the telluric correction for IFU 24.", CPL_FALSE);
842 if (e != CPL_ERROR_NONE) return (int)e;
843
844 /* --KMOS_MOLECFIT_PARAMETER_SUPPRESS_EXTENSION */
845 cpl_boolean suppress_extension = CPL_FALSE;
846 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_SUPPRESS_EXTENSION,
847 !range, dummyMin, dummyMax, CPL_TYPE_BOOL, &suppress_extension,
848 "Suppress arbitrary filename extension.(TRUE (apply) or FALSE (don't apply).", CPL_FALSE);
849 if (e != CPL_ERROR_NONE) return (int)e;
850
851 /* --KMOS_MOLECFIT_PARAMETER_SCALE_PWV - PIPE-10280 */
852 const char *scale_pwv = "auto";
853 e = kmos_molecfit_fill_parameter(RECIPE_NAME, self, KMOS_MOLECFIT_PARAMETER_SCALE_PWV,
854 !range, dummyMin, dummyMax, CPL_TYPE_STRING, (const void *)scale_pwv,
855 "Value to use when scaling the precipitable water vapor.", CPL_FALSE);
856 if (e != CPL_ERROR_NONE) return (int)e;
857
858 /* Check possible errors */
859 if (!cpl_errorstate_is_equal(prestate)) {
860 return cpl_error_set_message(cpl_func, cpl_error_get_code(),
861 "kmos_molecfit_calctrans_fill_parameterlist failed!");
862 }
863
864 return CPL_ERROR_NONE;
865}
866
867/*----------------------------------------------------------------------------*/
876/*----------------------------------------------------------------------------*/
877static kmos_molecfit_calctrans_parameter * kmos_molecfit_calctrans_conf(
878 const cpl_parameterlist *list)
879{
880 /* Check input */
881 cpl_error_ensure(list, CPL_ERROR_NULL_INPUT,
882 return NULL, "kmos_molecfit_calctrans_fill_conf input list NULL!");
883
884 /* Get preState */
885 cpl_errorstate preState = cpl_errorstate_get();
886 const cpl_parameter *p;
887
888
889 /* Create the configuration parameter */
890 kmos_molecfit_calctrans_parameter *conf = (kmos_molecfit_calctrans_parameter *)cpl_malloc(sizeof(kmos_molecfit_calctrans_parameter));
891 kmos_molecfit_nullify(&(conf->mf));
892 conf->pl_atmos_params = NULL;
893 conf->pl_best_fit_params = NULL;
894 for (cpl_size i = 0; i < N_IFUS; i ++) {
895 conf->atmprof[i] = NULL;
896 conf->res_table[i] = NULL;
897 conf->results[i] = NULL;
898 }
899
900 conf->pwv_ratio = 1.0;
901 conf->pwv_sci = -99.9;
902 conf->h2o_col_mm = -99.9;
903
904 /* Initialize input parameters propertylist */
905 conf->mf.parms = cpl_propertylist_new();
906
907 /* User input kernel ? */
908 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_USE_INPUT_KERNEL);
909 conf->mf.use_input_kernel = cpl_parameter_get_bool(p);
910
911 /* Mapping IFUS in kmos_molecfit_calctrans recipe */
912 int ifu = -1;
913
914 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_1);
915 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
916
917 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_2);
918 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
919
920 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_3);
921 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
922
923 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_4);
924 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
925
926 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_5);
927 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
928
929 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_6);
930 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
931
932 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_7);
933 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
934
935 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_8);
936 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
937
938 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_9);
939 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
940
941 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_10);
942 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
943
944 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_11);
945 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
946
947 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_12);
948 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
949
950 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_13);
951 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
952
953 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_14);
954 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
955
956 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_15);
957 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
958
959 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_16);
960 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
961
962 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_17);
963 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
964
965 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_18);
966 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
967
968 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_19);
969 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
970
971 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_20);
972 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
973
974 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_21);
975 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
976
977 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_22);
978 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
979
980 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_23);
981 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
982
983 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_24);
984 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
985
986 /* suppress_extension */
987 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_SUPPRESS_EXTENSION);
988 conf->mf.suppress_extension = cpl_parameter_get_bool(p);
989
990 /* pwv scaling */
991 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_SCALE_PWV);
992 conf->scale_pwv = cpl_parameter_get_string(p);
993
994 /* Save parameter in the output propertylist */
995 cpl_propertylist_update_bool(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_USE_INPUT_KERNEL, conf->mf.use_input_kernel);
996
997 ifu = -1;
998 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_1, conf->mf.ifus[++ifu].map );
999 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_2, conf->mf.ifus[++ifu].map );
1000 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_3, conf->mf.ifus[++ifu].map );
1001 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_4, conf->mf.ifus[++ifu].map );
1002 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_5, conf->mf.ifus[++ifu].map );
1003 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_6, conf->mf.ifus[++ifu].map );
1004 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_7, conf->mf.ifus[++ifu].map );
1005 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_8, conf->mf.ifus[++ifu].map );
1006 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_9, conf->mf.ifus[++ifu].map );
1007 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_10, conf->mf.ifus[++ifu].map );
1008 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_11, conf->mf.ifus[++ifu].map );
1009 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_12, conf->mf.ifus[++ifu].map );
1010 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_13, conf->mf.ifus[++ifu].map );
1011 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_14, conf->mf.ifus[++ifu].map );
1012 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_15, conf->mf.ifus[++ifu].map );
1013 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_16, conf->mf.ifus[++ifu].map );
1014 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_17, conf->mf.ifus[++ifu].map );
1015 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_18, conf->mf.ifus[++ifu].map );
1016 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_19, conf->mf.ifus[++ifu].map );
1017 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_20, conf->mf.ifus[++ifu].map );
1018 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_21, conf->mf.ifus[++ifu].map );
1019 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_22, conf->mf.ifus[++ifu].map );
1020 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_23, conf->mf.ifus[++ifu].map );
1021 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_IFU_24, conf->mf.ifus[++ifu].map );
1022
1023 cpl_propertylist_update_bool(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_SUPPRESS_EXTENSION, conf->mf.suppress_extension);
1024 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_SCALE_PWV, conf->scale_pwv);
1025
1026 cpl_msg_info(cpl_func, "SCALE_PWV VALUE- '%s'.", conf->scale_pwv);
1027
1028 // TODO: DOUBLE CHECK IF THESE KEYWORDS ARE REQUIRED OR IF OTHER QC PARAMS ARE NEEDED.
1029 /*cpl_propertylist_update_char(conf->pwv_ratio, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_SCALE_PWV, conf->pwv_ratio);
1030 cpl_propertylist_update_char(conf->pwv_sci, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_SCALE_PWV, conf->pwv_sci);*/
1031
1032
1033
1034
1035 /* Check status */
1036 if (!cpl_errorstate_is_equal(preState)) {
1037 /* Configuration failed */
1038 kmos_molecfit_calctrans_clean(conf);
1039 return NULL;
1040 } else {
1041 /* Configuration successfully */
1042 return conf;
1043 }
1044}
1045
1046/*----------------------------------------------------------------------------*/
1056/*----------------------------------------------------------------------------*/
1057static cpl_error_code kmos_molecfit_calctrans_frames_conf(
1058 kmos_molecfit_calctrans_parameter *conf, cpl_frameset *frameset, const cpl_parameterlist *parlist)
1059{
1060 /* Check input */
1061 cpl_error_ensure(conf && frameset, CPL_ERROR_NULL_INPUT,
1062 return CPL_ERROR_NULL_INPUT, "kmos_molecfit_calctrans_recipe_model_conf inputs NULL!");
1063
1064 /* Get preState */
1065 cpl_errorstate initialState = cpl_errorstate_get();
1066
1067 regex_t regex;
1068 int reti;
1069 reti = regcomp(&regex,"[a-zA-Z0-9]",0);
1070 if(reti){
1071 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,"molecfit_calctrans: could not compile regex required to check SCALE_PWV");
1072 return cpl_error_get_code();
1073 }
1074 reti = regexec(&regex, conf->scale_pwv,0,NULL,0);
1075
1076 /*** Get frame, header and check: ATMOS_PARAM ***/
1077 cpl_msg_info(cpl_func, "Loading '%s' header, input from kmos_molecfit_modeL recipe ...", ATMOS_PARM);
1078 const cpl_frame *frmAtmosParm = cpl_frameset_find(frameset, ATMOS_PARM);
1079 cpl_error_ensure(frmAtmosParm, CPL_ERROR_DATA_NOT_FOUND,
1080 return CPL_ERROR_DATA_NOT_FOUND, ATMOS_PARM" not found in input frameset!");
1081 const char *fileAtmosParm = cpl_frame_get_filename(frmAtmosParm);
1082 conf->pl_atmos_params = cpl_propertylist_load(fileAtmosParm, 0);
1083 cpl_error_ensure(conf->pl_atmos_params, cpl_error_get_code(),
1084 return cpl_error_get_code(), "Cannot load ATMOS_PARM primary header propertylist from '%s'!", fileAtmosParm);
1085
1086
1087 /*** Get frame, header and check: BEST_FIT_PARM ***/
1088 cpl_msg_info(cpl_func, "Loading '%s' header, input from kmos_molecfit_model recipe ...", BEST_FIT_PARM);
1089 const cpl_frame *frmBestFitParm = cpl_frameset_find(frameset, BEST_FIT_PARM);
1090 cpl_error_ensure(frmBestFitParm, CPL_ERROR_DATA_NOT_FOUND,
1091 return CPL_ERROR_DATA_NOT_FOUND, BEST_FIT_PARM" not found in input frameset!");
1092 const char *fileBestFitParm = cpl_frame_get_filename(frmBestFitParm);
1093 conf->pl_best_fit_params = cpl_propertylist_load(fileBestFitParm, 0);
1094 cpl_error_ensure(conf->pl_best_fit_params, cpl_error_get_code(),
1095 return cpl_error_get_code(), "Cannot load BEST_FIT_PARM primary header propertylist from '%s'!", fileBestFitParm);
1096
1097
1098 /*** Get frame, header and check: SCIENCE ***/
1099 cpl_msg_info(cpl_func, "Loading the SCIENCE header for keywords ");
1100 const cpl_frame *frmSci = kmos_molecfit_get_frame_spectrums(frameset);
1101 cpl_error_ensure(frmSci, CPL_ERROR_DATA_NOT_FOUND,
1102 return CPL_ERROR_DATA_NOT_FOUND, "Input Data not found in input frameset!");
1103 const char *fileScience = cpl_frame_get_filename(frmSci);
1104 cpl_propertylist *pl_sci = cpl_propertylist_load(fileScience, 0);
1105 cpl_error_ensure(pl_sci , cpl_error_get_code(),
1106 return cpl_error_get_code(), "Cannot load primary Data header propertylist from '%s'!", fileScience);
1107
1108
1109 /*Get MJD_OBS values from BEST_FIT_PARAMETERS and SCIENCE files for QC param ESO DRS PWV DELTA MJD */
1110 //int raise_err = !strcmp(conf->scale_pwv,"none");
1111
1112 /*if(!cpl_propertylist_has(conf->pl_best_fit_params, KEY_MJDOBS)){
1113 if(raise_err)
1114 cpl_msg_error(cpl_func,"Missing %s keyword from %s.\n\tCannot populate ESO DRS PWV DELTA MJD.\n", KEY_MJDOBS,BEST_FIT_PARM);
1115 else
1116 cpl_msg_info(cpl_func,"Missing %s keyword from science spectrum.\n\tCannot populate ESO DRS PWV DELTA MJD.\n",KEY_MJDOBS);
1117 }
1118
1119 if(!cpl_propertylist_has(pl_sci, KEY_MJDOBS)){
1120 if(raise_err)
1121 cpl_msg_error(cpl_func,"Missing %s keyword from science spectrum.\n\tCannot populate ESO DRS PWV DELTA MJD.\n",KEY_MJDOBS);
1122 else
1123 cpl_msg_info(cpl_func,"Missing %s keyword from science spectrum.\n\tCannot populate ESO DRS PWV DELTA MJD.\n",KEY_MJDOBS);
1124 }*/
1125
1126 /*key_exp*/
1127 /*if(!cpl_propertylist_has(conf->pl_best_fit_params, KEY_EXPTIME)){
1128 if(raise_err)
1129 cpl_msg_error(cpl_func,"Missing %s keyword from %s.\n\tCannot populate ESO DRS PWV DELTA MJD.\n",KEY_EXPTIME, BEST_FIT_PARM);
1130 else
1131 cpl_msg_info(cpl_func,"Missing %s keyword from %s.\n\tCannot populate ESO DRS PWV DELTA MJD.\n", KEY_EXPTIME, BEST_FIT_PARM);
1132 }
1133 if(!cpl_propertylist_has(pl_sci,KEY_EXPTIME)){
1134 if(raise_err)
1135 cpl_msg_error(cpl_func,"Missing %s keyword from science spectrum.\n\tCannot populate ESO DRS PWV DELTA MJD.\n", KEY_EXPTIME);
1136 else
1137 cpl_msg_info(cpl_func,"Missing %s keyword from science spectrum.\n\tCannot populate ESO DRS PWV DELTA MJD.\n", KEY_EXPTIME);
1138 } */
1139
1140 /* This new QC Keyword is included in the Molecfit PWV calcultaions - check with Lodo what QC parameters are needed for this.
1141 *
1142 if(cpl_propertylist_has(bfp_hdr,KEY_EXPTIME) && cpl_propertylist_has(bfp_hdr,KEY_MJDOBS) &&
1143 cpl_propertylist_has(data_hdr,KEY_EXPTIME) && cpl_propertylist_has(data_hdr,KEY_MJDOBS)){
1144 double t0 = cpl_propertylist_get_double(bfp_hdr, KEY_MJDOBS);
1145 cpl_type exp_type = cpl_propertylist_get_type(bfp_hdr,KEY_EXPTIME);
1146 if(exp_type == CPL_TYPE_INT){
1147 t0 = t0 + 0.5*cpl_propertylist_get_int(bfp_hdr,KEY_EXPTIME);
1148 } else if (exp_type == CPL_TYPE_FLOAT){
1149 t0 = t0 + 0.5*cpl_propertylist_get_float(bfp_hdr,KEY_EXPTIME);
1150 } else if (exp_type == CPL_TYPE_DOUBLE){
1151 t0 = t0 + 0.5*cpl_propertylist_get_double(bfp_hdr,KEY_EXPTIME);
1152 }
1153 exp_type = cpl_propertylist_get_type(data_hdr,KEY_EXPTIME);
1154 double t1 = cpl_propertylist_get_double(data_hdr, KEY_MJDOBS);
1155 if(exp_type == CPL_TYPE_INT){
1156 t1 = t1 + 0.5*cpl_propertylist_get_int(data_hdr,KEY_EXPTIME);
1157 } else if (exp_type == CPL_TYPE_FLOAT){
1158 t1 = t1 + 0.5*cpl_propertylist_get_float(data_hdr,KEY_EXPTIME);
1159 } else if (exp_type == CPL_TYPE_DOUBLE){
1160 t1 = t1 + 0.5*cpl_propertylist_get_double(data_hdr,KEY_EXPTIME);
1161 }
1162
1163 cpl_propertylist_append_double(qc_new,"ESO DRS PWV DELTA MJD",t1-t0);
1164 cpl_propertylist_set_comment(qc_new,"ESO DRS PWV DELTA MJD","Sci-Telluric Mean MJD");
1165 } */
1166
1167 /*** Loading data form the input fits file ***/
1168 cpl_errorstate preState = cpl_errorstate_get();
1169
1170 //PIPE-10280 -> correcting the h2o column in the atm profile can be done here.
1171
1172 cpl_msg_info(cpl_func, "SCALE_PWV value - %s.", conf->scale_pwv);
1173
1174 /* // END of getting scale_pwv/ pwv_sci */
1175 if (!strcmp(conf->scale_pwv,"auto")){
1176 if(cpl_propertylist_has(pl_sci,"ESO TEL AMBI IWV START") && cpl_propertylist_has(pl_sci,"ESO TEL AMBI IWV END")){
1177 double iwv_start = cpl_propertylist_get_double(pl_sci,"ESO TEL AMBI IWV START");
1178 double iwv_end = cpl_propertylist_get_double(pl_sci,"ESO TEL AMBI IWV END");
1179 if(iwv_start == 0.0 && iwv_end == 0.0){
1180 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1181 "molecfit_calctrans: The ESO TEL AMBI IWV START/END science header keywords are both 0.0 which is not permitted by SCALE_PWV=auto");
1182 return cpl_error_get_code();
1183 }
1184 conf->pwv_sci = 0.5*(iwv_start+iwv_end);
1185 } else {
1186 /* IWV data not in headers, raise error */
1187 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1188 "molecfit_calctrans: Missing ESO TEL AMBI IWV START/END science header keywords required by SCALE_PWV=auto. Deactivating transmission function scaling. ");
1189 conf->scale_pwv = "none";
1190 //return cpl_error_get_code();
1191 }
1192 }
1193 //if the supplied value is a header keyword (i.e. it has characters in it) and not equal to none
1194 else if (!reti && strcmp(conf->scale_pwv,"none")){// && parameters->scale_pwv has chars and != NONE) {
1195 if(cpl_propertylist_has(pl_sci,conf->scale_pwv)){
1196 conf->pwv_sci = cpl_propertylist_get_double(pl_sci,conf->scale_pwv);
1197 } else {
1198 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1199 "molecfit_calctrans: Missing science header keyword %s required by SCALE_PWV", conf->scale_pwv);
1200 return cpl_error_get_code();
1201 }
1202 }
1203 else if (reti && strcmp(conf->scale_pwv,"none")) {
1204 /* numerical value supplied, convert to float and use it */
1205 conf->pwv_sci = atof(conf->scale_pwv);
1206 } else if (strcmp(conf->scale_pwv,"none")){
1207 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1208 "molecfit_calctrans: Error converting supplied value of SCALE_PWV: %s",conf->scale_pwv);
1209 return cpl_error_get_code();
1210 }
1211
1212 // END of getting scale_pwv/ pwv_sci
1213
1214 for (cpl_size n_ifu = 0; n_ifu < N_IFUS; n_ifu++) {
1215
1216 /* Get number of extension */
1217 cpl_size ext = (n_ifu * 2) + 1;
1218
1219 /* Get Best fit parameters */
1220 conf->res_table[n_ifu] = cpl_table_load(fileBestFitParm, ext, 0);
1221 if (!(conf->res_table[n_ifu])) {
1222 /* The extension doesn't have data spectrum */
1223 cpl_errorstate_set(preState);
1224 } else {
1225 cpl_msg_info(cpl_func, "%s, ext=%02lld: Loaded input data to kmos_molecfit_calctrans recipe.", BEST_FIT_PARM, ext);
1226 }
1227
1228 /* Get Atmospheric profile */
1229 conf->atmprof[n_ifu] = cpl_table_load(fileAtmosParm, ext, 0);
1230 if (!(conf->atmprof[n_ifu])) {
1231 /* The extension doesn't have atmprof */
1232 cpl_errorstate_set(preState);
1233 } else {
1234 cpl_msg_info(cpl_func, "%s, ext=%02lld: Loaded input data to kmos_molecfit_calctrans recipe.", ATMOS_PARM, ext);
1235
1236
1237 if (!(conf->res_table[n_ifu])) {
1238 /* The extension doesn't have data spectrum */
1239 cpl_errorstate_set(preState);
1240 cpl_msg_info(cpl_func, "%s, ext=%02lld Does not exist- cannot scale PWV transmission lines.", BEST_FIT_PARM, ext);
1241 } else {
1242 cpl_msg_info(cpl_func, "ext=%02lld Exists: Transmission Scaling starting - nScale Value -%d.", ext, (int)strcmp(conf->scale_pwv,"auto"));
1243
1244 int ridx;
1245 for (ridx=0; ridx<cpl_table_get_nrow(conf->res_table[n_ifu]) ; ridx++){
1246 if(!strcmp(cpl_table_get_string(conf->res_table[n_ifu],"parameter",ridx),"h2o_col_mm")){
1247 conf->h2o_col_mm = cpl_table_get_double(conf->res_table[n_ifu],"value",ridx,NULL);
1248 }
1249 }
1250
1251
1252 /* ------------------ PWV SCALING APPLIED - START ------------------*/
1253 /*Calculate pwv_sci */
1254 if ((!strcmp(conf->scale_pwv,"auto")) || (!reti && strcmp(conf->scale_pwv,"none")) || (reti && strcmp(conf->scale_pwv,"none")) ){
1255 cpl_msg_info(cpl_func, "internal calc starting now, pwv_sci-> %f, h2o_col_value-> %f",conf->pwv_sci ,conf->h2o_col_mm );
1256 if(conf->h2o_col_mm != -99.9 && conf->h2o_col_mm != 0.0){
1257
1258 conf->pwv_ratio = conf->pwv_sci / conf->h2o_col_mm ;
1259 cpl_msg_info(cpl_func, "internal calc done");
1260 }
1261 }
1262
1263 cpl_msg_info(cpl_func,"Value of parameters->pwv_sci: %e; parameters->h2o_col_mm (pwv_tell): %e; parameters->pwv_ratio: %e; parameters->scale_pwv: %s\n",conf->pwv_sci, conf->h2o_col_mm, conf->pwv_ratio, conf->scale_pwv);
1264 /* Rescale values in parameters->atm_parameters and write out to CALCTRANS_ATM_PARAMETERS.fits */
1265 if(conf->pwv_ratio == 1.0){
1266 cpl_msg_warning(cpl_func,"molecfit_calctrans: pwv_ratio is 1.0. No scaling based on PWV performed.\n");
1267 }
1268
1269 cpl_table_multiply_scalar(conf->atmprof[n_ifu], MF_MOLECULES_H2O , conf->pwv_ratio);
1270
1271 /* ------------------ PWV SCALING APPLIED - END ------------------*/
1272
1273 }
1274
1275 }
1276 //atmprof[n_ifu] updating H2O column for pwv scaling;
1277
1278 }
1279
1280 cpl_msg_info(cpl_func, "ENDING PWV SCALING SECTIONS");
1281 cpl_msg_info(cpl_func, "ERROR STATE - %s.", cpl_error_get_message());
1282
1283 //cpl_frame_delete(frmBestFitParm) ;
1284 //cpl_frame_delete(frmAtmosParm);
1285 //cpl_frame_delete(frmSci);
1286 cpl_propertylist_delete(pl_sci);
1287
1288 regfree(&regex);
1289
1290 /*** Check and assign mapping of IFUS ***/
1291 cpl_msg_info(cpl_func, "Mapping IFU's ... (Using BEST_FIT_PARM data in automatic assignment)");
1292 for (cpl_size n_ifu = 0; n_ifu < N_IFUS; n_ifu++) {
1293
1294 kmos_spectrum *ifu = &(conf->mf.ifus[n_ifu]);
1295 cpl_size ifu_num = n_ifu + 1;
1296
1297 /* Check if it's necessary to re-mapping automatically */
1298 if (ifu->map != -1) {
1299
1300 if (!(conf->res_table[ifu->map - 1])) {
1301 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1302 "Mapping IFU_X.%02lld->IFU_Y.%02d by the user failed! It doesn't contain IFU_Y data in the file %s.fits",
1303 ifu_num, ifu->map, BEST_FIT_PARM);
1304 }
1305
1306 cpl_msg_info(cpl_func, "IFU_X.%02lld mapping to IFU_Y.%02d --> "
1307 "Defined by the user with the input parameter (IFU_%02lld=%02d)",
1308 ifu_num, ifu->map, ifu_num, ifu->map);
1309 } else {
1310
1311 /* First rule: ifuX_i (science) have ifuY_i (calibration) */
1312 if (conf->res_table[n_ifu]) {
1313 ifu->map = ifu_num;
1314 cpl_msg_info(cpl_func, "IFU_X.%02lld mapping to IFU_Y.%02d --> "
1315 "Defined automatically (Same IFU_Y [with calibration data] for IFU_X [science data] - 1st rule)",
1316 ifu_num, ifu->map);
1317 }
1318
1319 /* Second rule: ifuX_(1-8)-->ifu_Y(1-8), ifuX_(9-16)-->ifu_Y(9-16), ifuX_(17-24)-->ifu_Y(17-24) */
1320 if (ifu->map == -1) {
1321 cpl_size ifuY_detector = (n_ifu / 8) + 1; /* Get detector of Science (IFU_X) */
1322 cpl_size ifuY_detector_init = (ifuY_detector - 1) * 8; /* Starting IFU_Y (calibration) in the detector of IFU_X number (science) [valid = 0, 8, 16] */
1323 for (cpl_size ifu_Y = ifuY_detector_init; ifu_Y < ifuY_detector_init + 8 && ifu->map == -1; ifu_Y++) {
1324
1325 /* If exist data --> Map */
1326 if (conf->res_table[ifu_Y]) {
1327 ifu->map = ifu_Y + 1;
1328 cpl_msg_info(cpl_func, "IFU_X.%02lld mapping to IFU_Y.%02d --> "
1329 "Defined automatically (First IFU_Y [with calibration data] inside detector:%lld of IFU_X [science data] - 2nd rule)",
1330 ifu_num, ifu->map, ifuY_detector);
1331 }
1332 }
1333 }
1334
1335 /* Third rule: If not found it in the normal range, looking for in all the range */
1336 if (ifu->map == -1) {
1337 cpl_size ifuX_detector = (n_ifu / 8) + 1; /* Get detector of Science (IFU_X) */
1338 for (cpl_size ifu_Y = 0; ifu_Y < N_IFUS && ifu->map == -1; ifu_Y++) {
1339
1340 /* If exist data --> Map */
1341 if (conf->res_table[ifu_Y]) {
1342 cpl_size ifuY_detector = (ifu_Y / 8) + 1; /* Get detector of calibration (IFU_Y) */
1343 ifu->map = ifu_Y + 1;
1344 cpl_msg_info(cpl_func, "IFU_X.%02lld mapping to IFU_Y.%02d --> "
1345 "Defined automatically (First IFU_Y [with calibration date] in the instrument (detector=%lld) outside the IFU_X detector=%lld [science data] - 3rd rule)", ifu_num, ifu->map,
1346 ifuY_detector, ifuX_detector);
1347 }
1348 }
1349 }
1350
1351 cpl_error_ensure(ifu->map != -1, CPL_ERROR_ILLEGAL_INPUT,
1352 return CPL_ERROR_ILLEGAL_INPUT, "Cannot search any IFU_Y data for the IFU_X");
1353 }
1354 }
1355
1356
1357 /*** Get the molecfit parameters from the BEST_FIL_PARAMS propertylist ***/
1358 cpl_msg_info(cpl_func, "Loading input parameters provided from kmos_molecfit_model recipe ...");
1359
1360 conf->mf.grating.name = cpl_propertylist_get_string(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_WRANGE );
1361 conf->mf.grating.wave_range = cpl_propertylist_get_string(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_WRANGE );
1362
1363 conf->mf.grating.list_molec = cpl_propertylist_get_string(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_LIST );
1364 conf->mf.grating.fit_molec = cpl_propertylist_get_string(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_FIT );
1365 conf->mf.grating.rel_col = cpl_propertylist_get_string(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_RELATIVE_VALUE);
1366
1367 conf->mf.kernmode = cpl_propertylist_get_bool( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_KERN_MODE );
1368 conf->mf.kernfac = cpl_propertylist_get_double(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_KERN_FAC );
1369 conf->mf.varkern = cpl_propertylist_get_bool( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_VAR_KERN );
1370
1371 conf->mf.fit_continuum.fit = cpl_propertylist_get_bool( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_FIT_CONTINUUM );
1372 conf->mf.fit_continuum.n = cpl_propertylist_get_int( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_CONTINUUM_N );
1373
1374 conf->mf.fit_wavelenght.fit = cpl_propertylist_get_bool( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_FIT_WLC );
1375 conf->mf.fit_wavelenght.n = cpl_propertylist_get_int( conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_WLC_N );
1376 conf->mf.fit_wavelenght.const_val = cpl_propertylist_get_double(conf->pl_best_fit_params, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_WLC_CONST );
1377
1378 cpl_msg_info(cpl_func, "Filling up the result headers ...");
1379
1380 /* Save parameter in the output propertylist */
1381
1382 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_WRANGE, conf->mf.grating.wave_range );
1383
1384 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_LIST, conf->mf.grating.list_molec );
1385 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_FIT, conf->mf.grating.fit_molec );
1386 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "KMOS_MOLECFIT_KEYWORD_RELATIVE_VALUE, conf->mf.grating.rel_col );
1387
1388 cpl_propertylist_update_bool( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_KERN_MODE, conf->mf.kernmode );
1389 cpl_propertylist_update_double(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_KERN_FAC, conf->mf.kernfac );
1390 cpl_propertylist_update_bool( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_VAR_KERN, conf->mf.varkern );
1391
1392 cpl_propertylist_update_bool( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_FIT_CONTINUUM, conf->mf.fit_continuum.fit );
1393 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_CONTINUUM_N, conf->mf.fit_continuum.n );
1394
1395 cpl_propertylist_update_bool( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_FIT_WLC, conf->mf.fit_wavelenght.fit );
1396 cpl_propertylist_update_int( conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_WLC_N, conf->mf.fit_wavelenght.n );
1397 cpl_propertylist_update_double(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT" "MF_PARAMETERS_WLC_CONST, conf->mf.fit_wavelenght.const_val);
1398
1399
1400 /* Check status */
1401 if (!cpl_errorstate_is_equal(initialState)) {
1402 /* Configuration failed */
1403 return cpl_error_get_code();
1404 }
1405
1406 return CPL_ERROR_NONE;
1407}
1408
1409/*----------------------------------------------------------------------------*/
1418/*----------------------------------------------------------------------------*/
1419static cpl_error_code kmos_molecfit_calctrans_mf_conf(
1420 kmos_molecfit_calctrans_parameter *conf,
1421 double median,
1422 mf_parameters_config *config_parameters)
1423{
1424 /* Check input */
1425 cpl_error_ensure(conf, CPL_ERROR_NULL_INPUT,
1426 return CPL_ERROR_NULL_INPUT, "conf input is NULL!");
1427
1428 /*** Building generic configuration molecfic file ***/
1429 cpl_error_code err = kmos_molecfit_conf_generic(&(conf->mf), config_parameters);
1430 if (err != CPL_ERROR_NONE) {
1431 return cpl_error_set_message(cpl_func, err,
1432 "Building molecfit configuration variable failed!");
1433 }
1434
1435 /*** PARAMETERS NOT INCLUDED IN THE RECIPE: HARD-CODED ***/
1436
1437 config_parameters->fitting.fit_continuum.fit = conf->mf.fit_continuum.fit;
1438 config_parameters->fitting.fit_continuum.n = conf->mf.fit_continuum.n;
1439 config_parameters->fitting.fit_continuum.const_val = median; /* Molecfit default: 1. */
1440 cpl_msg_info(cpl_func,"--.cont_const = %g", config_parameters->fitting.fit_continuum.const_val);
1441
1442 config_parameters->fitting.fit_wavelenght.fit = conf->mf.fit_wavelenght.fit;
1443 config_parameters->fitting.fit_wavelenght.n = conf->mf.fit_wavelenght.n;
1444 config_parameters->fitting.fit_wavelenght.const_val = conf->mf.fit_wavelenght.const_val;
1445
1446 return CPL_ERROR_NONE;
1447}
1448
1449/*----------------------------------------------------------------------------*/
1455/*----------------------------------------------------------------------------*/
1456static void kmos_molecfit_calctrans_clean(
1457 kmos_molecfit_calctrans_parameter *conf)
1458{
1459 if (conf) {
1460
1461 if (&(conf->mf)) kmos_molecfit_clean(&(conf->mf));
1462
1463 if (conf->pl_atmos_params) cpl_propertylist_delete( conf->pl_atmos_params );
1464 if (conf->pl_best_fit_params) cpl_propertylist_delete( conf->pl_best_fit_params);
1465 for (cpl_size i = 0; i < N_IFUS; i ++) {
1466 if (conf->atmprof[i] ) cpl_table_delete( conf->atmprof[i] );
1467 if (conf->res_table[i]) cpl_table_delete( conf->res_table[i] );
1468 if (conf->results[i] ) mf_calctrans_convolution_results_delete(conf->results[i] );
1469 }
1470
1471 cpl_free(conf);
1472 }
1473}