34#include <mf_wrap_config.h>
35#include <telluriccorr.h>
48#define RECIPE_ID "xsh_molecfit_correct"
49#define RECIPE_AUTHOR "N. Fernando, B. Miszalski"
50#define RECIPE_CONTACT "nuwanthika.fernando@partner.eso.org"
74"Applies molecfit_correct";
77"Applies molecfit_correct";
123 cpl_recipe *recipe = NULL;
124 cpl_plugin *plugin = NULL;
126 recipe = cpl_calloc(1,
sizeof(*recipe));
127 if ( recipe == NULL ){
131 plugin = &recipe->interface ;
133 cpl_plugin_init(plugin,
136 CPL_PLUGIN_TYPE_RECIPE,
147 cpl_pluginlist_append(list, plugin);
149 return (cpl_error_get_code() != CPL_ERROR_NONE);
165 cpl_recipe *recipe = NULL;
180 assure( plugin != NULL, CPL_ERROR_NULL_INPUT,
"Null plugin");
183 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
184 CPL_ERROR_TYPE_MISMATCH,
185 "Plugin is not a recipe");
187 recipe = (cpl_recipe *)plugin;
190 recipe->parameters = cpl_parameterlist_new();
191 assure( recipe->parameters != NULL,
192 CPL_ERROR_ILLEGAL_OUTPUT,
193 "Memory allocation failed!");
199 "COLUMN_WAVE",
"WAVE",
200 "In the case of fits binary science input: name of the column in the input that identifies the wavelength."));
204 "COLUMN_FLUX",
"FLUX",
205 "In the case of fits binary science input: name of the column in the input that identifies the flux."));
209 "COLUMN_DFLUX",
"ERR",
210 "In the case of fits binary science input: name of the column in the input that identifies the flux errors."));
215 "Use this value when the transmission function is lower than the specified threshold."));
218 if ( cpl_error_get_code() != CPL_ERROR_NONE ){
237 cpl_recipe *recipe = NULL;
240 assure( plugin != NULL, CPL_ERROR_NULL_INPUT,
"Null plugin" );
243 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
244 CPL_ERROR_TYPE_MISMATCH,
"Plugin is not a recipe");
246 recipe = (cpl_recipe *)plugin;
251 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
270 cpl_recipe *recipe = NULL;
273 assure( plugin != NULL, CPL_ERROR_NULL_INPUT,
"Null plugin" );
276 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
277 CPL_ERROR_TYPE_MISMATCH,
"Plugin is not a recipe");
279 recipe = (cpl_recipe *)plugin;
284 if (cpl_error_get_code() != CPL_ERROR_NONE)
296 cpl_frameset_dump(frameset,NULL);
299 cpl_error_ensure(frameset && parlist, CPL_ERROR_NULL_INPUT,
return CPL_ERROR_NULL_INPUT,
"NULL input : frameset and/or parlist");
300 cpl_errorstate initial_errorstate = cpl_errorstate_get();
301 cpl_error_code err = CPL_ERROR_NONE;
303 cpl_parameterlist* ilist = cpl_parameterlist_new();
304 cpl_parameterlist* iframelist = cpl_parameterlist_new();
311 const char* input_name = cpl_parameter_get_string(cpl_parameterlist_find(iframelist,
"INPUTNAME"));
312 const char* arm = cpl_parameter_get_string(cpl_parameterlist_find(iframelist,
"ARM"));
320 cpl_frame* f = cpl_frameset_find(frameset,input_name);
322 cpl_frame_set_group(f,CPL_FRAME_GROUP_RAW);
324 const char* tcor_tag = mf_wrap_tag_suffix(
"TELLURIC_CORR",arm,CPL_FALSE);
325 f = cpl_frameset_find(frameset,tcor_tag);
327 cpl_frame_set_group(f,CPL_FRAME_GROUP_CALIB);
330 if(strstr(input_name,
"SCI_SLIT_FLUX_MERGE2D")){
331 err = CPL_ERROR_INCOMPATIBLE_INPUT;
332 cpl_msg_info(cpl_func,
"Error: Invalid 2D input (not currently supported)");
387 cpl_parameterlist* mergedlist = cpl_parameterlist_new();
389 cpl_msg_info(cpl_func,
"calling mf_wrap_merge_parameterlists");
390 err = mf_wrap_merge_parameterlists(ilist, parlist,mergedlist);
393 molecfit_correct_parameter *parameters = NULL;
397 cpl_msg_info(cpl_func,
"Load 'MOLECFIT_CORRECT' recipe parameters ...");
399 parameters = mf_wrap_config_corr_init(frameset, mergedlist,arm);
401 if (!parameters) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
"Illegal INPUT PARAMETERS!");
402 else err = cpl_error_get_code();
407 cpl_table *mapping_correct = NULL;
410 if (parameters->mapping_correct_table) {
411 mapping_correct = cpl_table_duplicate(parameters->mapping_correct_table);
413 const char* tag_name = mf_wrap_tag_suffix(MOLECFIT_MAPPING_CORRECT,NULL,CPL_FALSE);
414 cpl_msg_info (cpl_func,
"Loading %s cpl_table", tag_name);
416 mapping_correct = mf_wrap_load_unique_table(frameset, tag_name);
420 if ( !mapping_correct ) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
"Illegal INPUT MAPPING_CORRECT -> Not input!");
421 else if (cpl_table_get_column_min(mapping_correct, MOLECFIT_MAPPING_CORRECT_EXT) < 0) err = cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"Illegal INPUT MAPPING_CORRECT -> Minimum column < 0!");
422 else err = cpl_error_get_code();
430 cpl_size n_frames = cpl_frameset_get_size(frameset);
431 for (cpl_size frame = 0; frame < n_frames && !err; frame++) {
434 cpl_frame *frame_data = cpl_frameset_get_position(frameset, frame);
435 const char *tag = cpl_frame_get_tag(frame_data);
437 if ( strstr(tag,
"SCI_SLIT_FLUX_IDP") ||
438 strstr(tag,
"SCI_SLIT_FLUX_MERGE1D") ||
439 strstr(tag,
"SCI_SLIT_FLUX_MERGE2D") ||
440 strstr(tag,
"TELL_SLIT_MERGE1D") ||
441 strstr(tag,
"TELL_SLIT_FLUX_MERGE1D") ||
442 strstr(tag,
"TELL_SLIT_FLUX_IDP")
446 cpl_frameset *frameset_output = cpl_frameset_new();
447 cpl_frameset_insert(frameset_output, cpl_frame_duplicate(frame_data));
450 const char *filename = cpl_frame_get_filename(frame_data);
451 mf_wrap_fits *
data = mf_wrap_fits_load(filename, CPL_FALSE);
455 if (!
data) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
"Illegal INPUT %s cpl_frame!", tag);
456 else err = cpl_error_get_code();
460 if (!err) err = mf_wrap_data_convert_to_table(
data,
461 parameters->chip_extensions,
462 parameters->use_only_input_pri_ext,
463 parameters->dflux_extension_data,
464 parameters->mask_extension_data,
465 parameters->column_lambda,
466 parameters->column_flux,
467 parameters->column_dflux,
468 parameters->column_mask);
490 if ( parameters->use_only_input_pri_ext) n_ext = 1;
491 else if (parameters->chip_extensions ) n_ext =
data->v_ext[0].spectrum_data ? 1 : 2;
492 else n_ext =
data->n_ext;
495 mf_wrap_fits *spectrum_corr_data = NULL;
499 char *spectrum_filename = cpl_sprintf(
"SPECTRUM_%s.fits", input_name);
503 spectrum_corr_data = mf_wrap_fits_create(spectrum_filename, mf_wrap_fits_file_image_1D, mf_wrap_fits_vector,
data->n_ext);
504 cpl_free(spectrum_filename);
506 if (spectrum_corr_data) err = cpl_error_get_code();
507 else err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
"I cannot create the FITS output file %s!", MOLECFIT_SPECTRUM_TELLURIC_CORR);
510 for (cpl_size ext = 0; ext <
data->n_ext; ext++) {
511 if (
data->v_ext[ext].spectrum_data) {
514 if (
data->format == mf_wrap_fits_file_table) {
515 if ( cpl_propertylist_get_int(
data->v_ext[ext].header, MOLECFIT_FITS_KEYWORD_NAXIS1) > 1
516 && cpl_propertylist_get_int(
data->v_ext[ext].header, MOLECFIT_FITS_KEYWORD_NAXIS2) == 1) {
517 size = cpl_propertylist_get_int(
data->v_ext[ext].header, MOLECFIT_FITS_KEYWORD_NAXIS1);
519 size = cpl_table_get_nrow(
data->v_ext[ext].table);
525 else if (
data->format == mf_wrap_fits_file_image_1D)
size = cpl_vector_get_size(
data->v_ext[ext].vector);
526 else if (
data->format == mf_wrap_fits_file_image_2D)
size = cpl_image_get_size_x(
data->v_ext[ext].image );
527 else if (
data->format == mf_wrap_fits_file_image_3D)
size = cpl_imagelist_get_size(
data->v_ext[ext].cube );
529 spectrum_corr_data->v_ext[ext].vector = cpl_vector_new(
size);
536 for (cpl_size ext = 0; ext < n_ext && !err; ext++) {
539 if (!err) spectrum_corr_data->v_ext[ext].header = cpl_propertylist_duplicate(
data->v_ext[ext].spectrum_head);
542 if (
data->v_ext[ext].spectrum_data) {
545 cpl_size index_telluric_corr_ext = cpl_table_get(mapping_correct, MOLECFIT_MAPPING_CORRECT_EXT, ext, &null);
546 cpl_vector *telluric_corr = parameters->telluric_corr->v_ext[index_telluric_corr_ext].vector;
547 double threshold = cpl_parameter_get_double(cpl_parameterlist_find(mergedlist,
"THRESHOLD"));
550 cpl_size vs = cpl_vector_get_size(telluric_corr);
552 for (cpl_size vdx=0;vdx < vs; vdx++){
553 if(cpl_vector_get(telluric_corr,vdx) <
threshold){
554 cpl_vector_set(telluric_corr,vdx,
threshold);
564 err = cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"I cannot MATCH the TELLURIC_CORR extension with the %s extension for correct!", tag);
565 else if (cpl_table_get_nrow(
data->v_ext[ext].spectrum_data) <= 0
566 || cpl_table_get_nrow(
data->v_ext[ext].spectrum_data) != cpl_vector_get_size(telluric_corr))
567 err = cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"I cannot MATCH the rows between the TELLURIC_CORR extension with the %s extension for correct!", tag);
572 cpl_msg_info(cpl_func,
"Create input molecfit cpl_table data : %s [%s], ext=%lld", tag,
data->filename, ext);
573 cpl_table *molecfit_data = mf_spectrum_create_input_to_correct(
data->v_ext[ext].spectrum_data,
574 parameters->column_lambda,
575 parameters->column_flux,
576 parameters->column_dflux,
577 parameters->column_mask,
580 if (molecfit_data) err = cpl_error_get_code();
581 else err = cpl_error_set_message(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT,
"I cannot Create the input molecfit SPECTRUM_TABLE to correct!");
586 cpl_msg_info(cpl_func,
"File : %s, ext=%lld : Apply correction",
data->filename, ext);
587 err = mf_calctrans_correct_spectrum(molecfit_data, MF_PARAMETERS_TRANSMISSION_TRUE);
594 err = mf_wrap_data_update_vector(molecfit_data, parameters->chip_extensions, spectrum_corr_data, ext);
598 if (parameters->chip_extensions) {
599 for (cpl_size i = ext + 1; i <
data->n_ext; i++) {
600 spectrum_corr_data->v_ext[i].header = cpl_propertylist_duplicate(
data->v_ext[i].spectrum_head);
607 if (
data->format == mf_wrap_fits_file_table ) err = mf_wrap_data_update_table( molecfit_data, parameters->chip_extensions,
data, ext, parameters->column_flux);
608 else if (
data->format == mf_wrap_fits_file_image_1D) err = mf_wrap_data_update_vector(molecfit_data, parameters->chip_extensions,
data, ext);
609 else if (
data->format == mf_wrap_fits_file_image_2D) err = mf_wrap_data_update_image( molecfit_data, parameters->chip_extensions,
data, ext);
610 else if (
data->format == mf_wrap_fits_file_image_3D) err = mf_wrap_data_update_cube( molecfit_data, parameters->chip_extensions,
data, ext);
619 if (molecfit_data) cpl_table_delete(molecfit_data);
628 const char *filename_base = input_name;
633 char *out_telluric_corr = NULL;
635 if (parameters->suppress_extension) out_telluric_corr = cpl_sprintf(
"%s_%lld.fits", MOLECFIT_SPECTRUM_TELLURIC_CORR, frame );
636 else out_telluric_corr = cpl_sprintf(
"%s_%s.fits", MOLECFIT_SPECTRUM_TELLURIC_CORR, filename_base);
639 err = mf_wrap_fits_write(frameset, frameset_output, parlist, RECIPE_NAME, MOLECFIT_SPECTRUM_TELLURIC_CORR, spectrum_corr_data, out_telluric_corr);
641 cpl_free(out_telluric_corr);
647 char *out_data = NULL;
648 if (parameters->suppress_extension) out_data = cpl_sprintf(
"%s_%lld.fits", MOLECFIT_SCIENCE_TELLURIC_CORR, frame );
649 else out_data = cpl_sprintf(
"%s_%s.fits", MOLECFIT_SCIENCE_TELLURIC_CORR, filename_base);
651 cpl_msg_info(cpl_func,
"Writing on disk [%s] %s input FITS corrected on the same format --> %s (PRO.CATG=%s)",
data->filename, tag, out_data, MOLECFIT_SCIENCE_TELLURIC_CORR);
652 err = mf_wrap_fits_write(frameset, frameset_output, parlist, RECIPE_NAME, MOLECFIT_SCIENCE_TELLURIC_CORR,
data, out_data);
660 if (frameset_output ) cpl_frameset_delete(frameset_output);
661 if (
data ) mf_wrap_fits_delete(
data);
662 if (spectrum_corr_data) mf_wrap_fits_delete(spectrum_corr_data);
670 if (parameters ) molecfit_correct_parameter_delete( parameters );
671 if (mapping_correct) cpl_table_delete( mapping_correct);
675 if (!err && cpl_errorstate_is_equal(initial_errorstate)) {
676 cpl_msg_info(cpl_func,
"Recipe successfully!");
679 cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
680 cpl_msg_error(cpl_func,
"Recipe failed!, error(%d)=%s", err, cpl_error_get_message());
688 cpl_parameterlist* ilist, cpl_parameterlist* iframelist){
697 cpl_parameterlist* iframe = cpl_parameterlist_new();
698 cpl_error_code err= CPL_ERROR_NONE;
707 const char* is_idp = cpl_parameter_get_string(cpl_parameterlist_find(iframe,
"IDP"));
714 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"INPUTNAME"));
715 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"ARM"));
716 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"OBSMODE"));
717 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"IDP"));
718 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"INPUTFILENAME"));
719 err = cpl_parameterlist_append(iframelist,cpl_parameterlist_find(iframe,
"ISTWOD"));
722 const char* MAPPING_CORRECT;
723 cpl_boolean USE_PRIMARY_DATA;
726 if(!strcmp(is_idp,
"TRUE")){
727 MAPPING_CORRECT =
"0,1";
729 USE_PRIMARY_DATA = CPL_FALSE;
732 MAPPING_CORRECT =
"1";
733 USE_PRIMARY_DATA= CPL_TRUE;
737 cpl_boolean SUPPRESS_EXTENSION = CPL_FALSE;
738 cpl_boolean CHIP_EXTENSIONS= CPL_FALSE;
740 cpl_parameterlist_append(ilist,cpl_parameter_new_value(MOLECFIT_PARAMETER_MAPPING_CORRECT,CPL_TYPE_STRING,NULL,NULL,MAPPING_CORRECT));
741 cpl_parameterlist_append(ilist,cpl_parameter_new_value(
"USE_ONLY_INPUT_PRIMARY_DATA",CPL_TYPE_BOOL,NULL,NULL,USE_PRIMARY_DATA));
742 cpl_parameterlist_append(ilist,cpl_parameter_new_value(
"USE_DATA_EXTENSION_AS_DFLUX",CPL_TYPE_INT,NULL,NULL,USE_DFLUX));
744 cpl_parameterlist_append(ilist,cpl_parameter_new_value(MOLECFIT_PARAMETER_CHIP_EXTENSIONS,CPL_TYPE_BOOL,NULL,NULL,CHIP_EXTENSIONS));
745 cpl_parameterlist_append(ilist,cpl_parameter_new_value(MOLECFIT_PARAMETER_SUPPRESS_EXTENSION,CPL_TYPE_BOOL,NULL,NULL,SUPPRESS_EXTENSION));
746 cpl_parameterlist_append(ilist,cpl_parameter_new_value(
"USE_DATA_EXTENSION_AS_MASK",CPL_TYPE_INT,NULL,NULL,USE_MASK));
int xsh_molecfit_correct_exec(cpl_plugin *)
Execute the plugin instance given by the interface.
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
int xsh_molecfit_correct_create(cpl_plugin *)
Setup the recipe options.
int xsh_molecfit_correct(cpl_frameset *frameset, const cpl_parameterlist *parlist)
cpl_error_code xsh_molecfit_correct_config(cpl_frameset *frameset, const cpl_parameterlist *parlist, cpl_parameterlist *ilist, cpl_parameterlist *iframelist)
int xsh_molecfit_correct_destroy(cpl_plugin *)
Destroy what has been created by the 'create' function.
#define assure(CONDITION, ERROR_CODE,...)
#define xsh_error_dump(level)
void xsh_free_parameterlist(cpl_parameterlist **p)
Deallocate a parameter list and set the pointer to NULL.
const char * xsh_get_license(void)
Get the pipeline copyright and license.
void xsh_init(void)
Reset library state.
char xsh_molecfit_correct_description_short[]
char xsh_molecfit_correct_description[]
cpl_error_code xsh_molecfit_utils_find_input_frame(cpl_frameset *frameset, cpl_parameterlist *iframe)
void xsh_parameters_new_double(cpl_parameterlist *list, const char *recipe_id, const char *name, double value, const char *comment)
void xsh_parameters_new_string(cpl_parameterlist *list, const char *recipe_id, const char *name, const char *value, const char *comment)