31#include "kmos_molecfit.h"
46 kmos_molecfit_parameter mf;
47 cpl_propertylist *pl_atmos_params;
48 cpl_table *atmprof[N_IFUS];
49 cpl_propertylist *pl_best_fit_params;
50 cpl_table *res_table[N_IFUS];
51 mf_calctrans_convolution_results *results[N_IFUS];
52 const char *scale_pwv;
57} kmos_molecfit_calctrans_parameter;
67static kmos_molecfit_calctrans_parameter * kmos_molecfit_calctrans_conf(
68 const cpl_parameterlist *list);
71static cpl_error_code kmos_molecfit_calctrans_frames_conf(
72 kmos_molecfit_calctrans_parameter *conf, cpl_frameset *frameset,
const cpl_parameterlist *parlist);
75static cpl_error_code kmos_molecfit_calctrans_mf_conf(
76 kmos_molecfit_calctrans_parameter *conf,
78 mf_parameters_config *config_parameters);
81static void kmos_molecfit_calctrans_clean(
82 kmos_molecfit_calctrans_parameter *conf);
90#define RECIPE_NAME KMOS_MOLECFIT_CALCTRANS
91#define CONTEXT "kmos."RECIPE_NAME
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"
104 "Input files: (It's mandatory to provide 1 file only of type A) \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"
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"
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"
135cpl_recipe_define( kmos_molecfit_calctrans,
137 "Jose A. Escartin, Yves Jung",
138 "https://support.eso.org/",
140 "Read the results from kmos_molecfit_model and computes the telluric correction for a scientific input data.",
141 kmos_molecfit_calctrans_description);
169static int kmos_molecfit_calctrans(
170 cpl_frameset *frameset,
const cpl_parameterlist *parlist)
173 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
174 return cpl_error_get_code();
178 cpl_errorstate initial_errorstate = cpl_errorstate_get();
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");
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!");
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!" );
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);
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) {
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!");
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);
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 !");
230 cpl_msg_info(cpl_func,
"Using the default molecfit kernels -> With the values inside BEST_FIT_PARMS!");
233 cpl_msg_info(cpl_func,
" +++ All input data loaded successfully! +++");
238 const char * telcorr_file =
"telcorr.fits";
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);
243 cpl_error_code sTel_img = cpl_propertylist_save(conf->mf.header_spectrums, telcorr_file , CPL_IO_CREATE);
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);
254 const double wlmin = -1.;
255 const double wlmax = -1.;
258 cpl_table *molecules = conf->mf.grating.molecules;
263 mf_configuration *mf_config = mf_configuration_create();
264 if (!mf_config) err = CPL_ERROR_NULL_INPUT;
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");
274 for (cpl_size n_ifuY = 0; n_ifuY < N_IFUS; n_ifuY++) {
277 kmos_spectrum *ifuY = &(conf->mf.ifus[n_ifuY]);
279 cpl_msg_info(cpl_func,
"IFU NUMBER : %d", ifuY->num);
282 if (ifuY->num == ifuY->map) {
285 cpl_msg_info(cpl_func,
"Building molecfict configuration variable in %s ...", ifuY->name);
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");
294 if (!err) err = kmos_molecfit_calctrans_mf_conf(conf, ifuY->median, mf_config->parameters);
303 cpl_table *spec_telluriccorr_lblrtm = mf_spectrum_create(mf_config->parameters, ifuY->data);
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,
309 spec_telluriccorr_lblrtm,
313 conf->atmprof[n_ifuY],
314 conf->res_table[n_ifuY]);
316 cpl_table_delete(spec_telluriccorr_lblrtm);
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!");
326 cpl_msg_info(cpl_func,
"Molecfit call mf_calctrans_lblrtm(...) run successfully! in %s ...", ifuY->name);
329 for (cpl_size n_ifuX = 0; n_ifuX < N_IFUS && !err; n_ifuX++) {
332 kmos_spectrum *ifuX = &(conf->mf.ifus[n_ifuX]);
335 if (ifuX->map == ifuY->num) {
338 if (conf->results[n_ifuX]) {
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");
345 cpl_msg_info(cpl_func,
"Building molecfict configuration variable ... ");
348 mf_parameters_config *config_parameters_ifuX = mf_parameters_config_create();
349 if (!config_parameters_ifuX) err = CPL_ERROR_NONE;
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");
359 if (!err) err = kmos_molecfit_calctrans_mf_conf(conf, ifuY->median, config_parameters_ifuX);
364 cpl_table *spec_telluriccorr_convolution = mf_spectrum_create(config_parameters_ifuX, ifuY->data);
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,
371 ifuY->header_ext_data,
372 spec_telluriccorr_convolution,
373 ifuX->kernel.header_ext_data,
377 conf->res_table[n_ifuY]);
379 cpl_table_delete(spec_telluriccorr_convolution);
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!");
389 cpl_msg_info(cpl_func,
"Molecfit call mf_calctrans_convolution(...) run successfully! in %s ...", ifuX->name);
394 if (config_parameters_ifuX) mf_parameters_config_delete(config_parameters_ifuX);
401 mf_calctrans_lblrtm_results_delete(lblrtm_results);
408 if (mf_config) mf_configuration_delete(mf_config);
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());
419 cpl_propertylist * tel_primary_header = kmclipm_propertylist_load(telcorr_file, 0);
420 cpl_propertylist * best_fit_header = kmclipm_propertylist_load(
421 cpl_frame_get_filename(cpl_frameset_find(frameset, BEST_FIT_PARM)),0);
423 if (cpl_propertylist_has(best_fit_header,
"ESO TEL AIRM END")){
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);
431 if (cpl_propertylist_has(best_fit_header, QC_PARAM_H2O_AVG)){
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);
438 if (cpl_propertylist_has(best_fit_header, QC_PARAM_H2O_RMS)){
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);
445 if (cpl_propertylist_has(best_fit_header, QC_PARAM_MEAS_IWV)){
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);
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);
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);
470 const char * suffix=
"";
472 if (!conf->mf.suppress_extension) {
473 suffix = kmo_dfs_get_suffix(kmo_dfs_get_frame(frameset, TELLURIC_DATA), TRUE, FALSE);
478 cpl_propertylist_update_string(tel_primary_header, KEY_PRODCATG,
"ANCILLARY.KMOS.SPECTRUM.TELLURIC") ;
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);
486 for (cpl_size n_ifu = 0; n_ifu < N_IFUS; n_ifu++) {
489 kmos_spectrum *ifu = &(conf->mf.ifus[n_ifu]);
491 cpl_table *telluric_data = (conf->results[n_ifu])->spec_telluriccorr_format;
493 cpl_vector *telluric_vec = NULL;
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);
502 double mtrans_max = cpl_vector_get_max(telluric_vec);
504 cpl_msg_info(cpl_func,
"Saving telluric data and image in IFU=%02d ... (Convolution executed) --> Max_value(%lf)", ifu->num, mtrans_max);
507 cpl_msg_info(cpl_func,
"Saving data in IFU=%02d ...", ifu->num);
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);
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);
521 char* name_data = cpl_sprintf(
"IFU.%d.DATA", ifu->num);
522 cpl_propertylist_update_string(header_data, EXTNAME, name_data);
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);
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");
535 if ((telluric_data== NULL) && (telluric_vec==NULL)) {
536 kmos_all_clean_plist(header_data) ;
538 kmos_all_clean_plist(header_noise) ;
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);
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);
570 if (frmKernel && conf->mf.use_input_kernel) {
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;
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;
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);
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);
596 if (telluric_vec) cpl_vector_delete(telluric_vec);
597 cpl_propertylist_delete(header_data);
598 cpl_propertylist_delete(header_noise);
600 unlink(telcorr_file);
605 if (conf->pwv_ratio!=1.0){
607 const cpl_frame *frmAtmosParm = cpl_frameset_find(frameset, ATMOS_PARM);
608 const char *fileAtmosParm = cpl_frame_get_filename(frmAtmosParm);
611 kmos_molecfit_save(frameset, frameset, parlist, RECIPE_NAME, conf->mf.parms, CALCTRANS_ATMOS_PARM,conf->mf.grating.name, conf->mf.suppress_extension, NULL);
614 for (cpl_size n_ifu = 1; n_ifu <= N_IFUS; n_ifu++) {
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) ;
622 kmos_all_clean_plist(header_atmos_noise) ;
628 sKernels_e = kmo_dfs_save_table(conf->atmprof[n_ifu-1], CALCTRANS_ATMOS_PARM, suffix ,header_atmos_data);
631 if (sKernels_e != CPL_ERROR_NONE) {
632 cpl_propertylist_delete(header_atmos_data);
633 cpl_propertylist_delete(header_atmos_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);
649 cpl_msg_info(cpl_func,
"Cleaning variables ...");
650 kmos_molecfit_calctrans_clean(conf);
653 if (cpl_errorstate_is_equal(initial_errorstate) && cpl_error_get_code() == CPL_ERROR_NONE ) {
654 cpl_msg_info(cpl_func,
"Recipe successfully!");
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());
661 return (
int)cpl_error_get_code();
676static cpl_error_code kmos_molecfit_calctrans_fill_parameterlist(
677 cpl_parameterlist *self)
680 cpl_errorstate prestate = cpl_errorstate_get();
684 cpl_boolean range = CPL_TRUE;
685 const void *dummyMin = NULL;
686 const void *dummyMax = NULL;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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!");
864 return CPL_ERROR_NONE;
877static kmos_molecfit_calctrans_parameter * kmos_molecfit_calctrans_conf(
878 const cpl_parameterlist *list)
881 cpl_error_ensure(list, CPL_ERROR_NULL_INPUT,
882 return NULL,
"kmos_molecfit_calctrans_fill_conf input list NULL!");
885 cpl_errorstate preState = cpl_errorstate_get();
886 const cpl_parameter *p;
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;
900 conf->pwv_ratio = 1.0;
901 conf->pwv_sci = -99.9;
902 conf->h2o_col_mm = -99.9;
905 conf->mf.parms = cpl_propertylist_new();
908 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_USE_INPUT_KERNEL);
909 conf->mf.use_input_kernel = cpl_parameter_get_bool(p);
914 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_1);
915 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
917 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_2);
918 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
920 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_3);
921 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
923 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_4);
924 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
926 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_5);
927 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
929 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_6);
930 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
932 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_7);
933 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
935 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_8);
936 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
938 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_9);
939 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
941 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_10);
942 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
944 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_11);
945 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
947 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_12);
948 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
950 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_13);
951 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
953 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_14);
954 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
956 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_15);
957 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
959 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_16);
960 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
962 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_17);
963 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
965 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_18);
966 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
968 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_19);
969 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
971 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_20);
972 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
974 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_21);
975 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
977 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_22);
978 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
980 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_23);
981 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
983 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_IFU_24);
984 conf->mf.ifus[++ifu].map = cpl_parameter_get_int(p);
987 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_SUPPRESS_EXTENSION);
988 conf->mf.suppress_extension = cpl_parameter_get_bool(p);
991 p = cpl_parameterlist_find_const(list, KMOS_MOLECFIT_PARAMETER_SCALE_PWV);
992 conf->scale_pwv = cpl_parameter_get_string(p);
995 cpl_propertylist_update_bool(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT
" "KMOS_MOLECFIT_KEYWORD_USE_INPUT_KERNEL, conf->mf.use_input_kernel);
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 );
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);
1026 cpl_msg_info(cpl_func,
"SCALE_PWV VALUE- '%s'.", conf->scale_pwv);
1036 if (!cpl_errorstate_is_equal(preState)) {
1038 kmos_molecfit_calctrans_clean(conf);
1057static cpl_error_code kmos_molecfit_calctrans_frames_conf(
1058 kmos_molecfit_calctrans_parameter *conf, cpl_frameset *frameset,
const cpl_parameterlist *parlist)
1061 cpl_error_ensure(conf && frameset, CPL_ERROR_NULL_INPUT,
1062 return CPL_ERROR_NULL_INPUT,
"kmos_molecfit_calctrans_recipe_model_conf inputs NULL!");
1065 cpl_errorstate initialState = cpl_errorstate_get();
1069 reti = regcomp(®ex,
"[a-zA-Z0-9]",0);
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();
1074 reti = regexec(®ex, conf->scale_pwv,0,NULL,0);
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);
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);
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);
1168 cpl_errorstate preState = cpl_errorstate_get();
1172 cpl_msg_info(cpl_func,
"SCALE_PWV value - %s.", conf->scale_pwv);
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();
1184 conf->pwv_sci = 0.5*(iwv_start+iwv_end);
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";
1194 else if (!reti && strcmp(conf->scale_pwv,
"none")){
1195 if(cpl_propertylist_has(pl_sci,conf->scale_pwv)){
1196 conf->pwv_sci = cpl_propertylist_get_double(pl_sci,conf->scale_pwv);
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();
1203 else if (reti && strcmp(conf->scale_pwv,
"none")) {
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();
1214 for (cpl_size n_ifu = 0; n_ifu < N_IFUS; n_ifu++) {
1217 cpl_size ext = (n_ifu * 2) + 1;
1220 conf->res_table[n_ifu] = cpl_table_load(fileBestFitParm, ext, 0);
1221 if (!(conf->res_table[n_ifu])) {
1223 cpl_errorstate_set(preState);
1225 cpl_msg_info(cpl_func,
"%s, ext=%02lld: Loaded input data to kmos_molecfit_calctrans recipe.", BEST_FIT_PARM, ext);
1229 conf->atmprof[n_ifu] = cpl_table_load(fileAtmosParm, ext, 0);
1230 if (!(conf->atmprof[n_ifu])) {
1232 cpl_errorstate_set(preState);
1234 cpl_msg_info(cpl_func,
"%s, ext=%02lld: Loaded input data to kmos_molecfit_calctrans recipe.", ATMOS_PARM, ext);
1237 if (!(conf->res_table[n_ifu])) {
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);
1242 cpl_msg_info(cpl_func,
"ext=%02lld Exists: Transmission Scaling starting - nScale Value -%d.", ext, (
int)strcmp(conf->scale_pwv,
"auto"));
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);
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){
1258 conf->pwv_ratio = conf->pwv_sci / conf->h2o_col_mm ;
1259 cpl_msg_info(cpl_func,
"internal calc done");
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);
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");
1269 cpl_table_multiply_scalar(conf->atmprof[n_ifu], MF_MOLECULES_H2O , conf->pwv_ratio);
1280 cpl_msg_info(cpl_func,
"ENDING PWV SCALING SECTIONS");
1281 cpl_msg_info(cpl_func,
"ERROR STATE - %s.", cpl_error_get_message());
1286 cpl_propertylist_delete(pl_sci);
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++) {
1294 kmos_spectrum *ifu = &(conf->mf.ifus[n_ifu]);
1295 cpl_size ifu_num = n_ifu + 1;
1298 if (ifu->map != -1) {
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);
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);
1312 if (conf->res_table[n_ifu]) {
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)",
1320 if (ifu->map == -1) {
1321 cpl_size ifuY_detector = (n_ifu / 8) + 1;
1322 cpl_size ifuY_detector_init = (ifuY_detector - 1) * 8;
1323 for (cpl_size ifu_Y = ifuY_detector_init; ifu_Y < ifuY_detector_init + 8 && ifu->map == -1; ifu_Y++) {
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);
1336 if (ifu->map == -1) {
1337 cpl_size ifuX_detector = (n_ifu / 8) + 1;
1338 for (cpl_size ifu_Y = 0; ifu_Y < N_IFUS && ifu->map == -1; ifu_Y++) {
1341 if (conf->res_table[ifu_Y]) {
1342 cpl_size ifuY_detector = (ifu_Y / 8) + 1;
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);
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");
1358 cpl_msg_info(cpl_func,
"Loading input parameters provided from kmos_molecfit_model recipe ...");
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 );
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);
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 );
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 );
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 );
1378 cpl_msg_info(cpl_func,
"Filling up the result headers ...");
1382 cpl_propertylist_update_string(conf->mf.parms, MF_PARAMETERS_CONTEX_DEFAULT
" "KMOS_MOLECFIT_KEYWORD_WRANGE, conf->mf.grating.wave_range );
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 );
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 );
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 );
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);
1401 if (!cpl_errorstate_is_equal(initialState)) {
1403 return cpl_error_get_code();
1406 return CPL_ERROR_NONE;
1419static cpl_error_code kmos_molecfit_calctrans_mf_conf(
1420 kmos_molecfit_calctrans_parameter *conf,
1422 mf_parameters_config *config_parameters)
1425 cpl_error_ensure(conf, CPL_ERROR_NULL_INPUT,
1426 return CPL_ERROR_NULL_INPUT,
"conf input is NULL!");
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!");
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;
1440 cpl_msg_info(cpl_func,
"--.cont_const = %g", config_parameters->fitting.fit_continuum.const_val);
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;
1446 return CPL_ERROR_NONE;
1456static void kmos_molecfit_calctrans_clean(
1457 kmos_molecfit_calctrans_parameter *conf)
1461 if (&(conf->mf)) kmos_molecfit_clean(&(conf->mf));
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] );