X-shooter Pipeline Reference Manual 3.8.15
xsh_molecfit_correct.c
Go to the documentation of this file.
1/*
2 * This file is part of the ESO X-Shooter Pipeline
3 * Copyright (C) 2001-2018 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*----------------------------------------------------------------------------*/
24/*----------------------------------------------------------------------------*/
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28/* xshooter headers */
29#include <xsh_error.h>
30#include <xsh_utils.h>
31
32/* Molecfit Model */
34#include <mf_wrap_config.h>
35#include <telluriccorr.h>
36//#include <mf_spectrum.h>
37//#include <mf_wrap.h>
38/*----------------------------------------------------------------------------*/
42/*----------------------------------------------------------------------------*/
43
44/*---------------------------------------------------------------------------
45 Recipe Defines
46 ---------------------------------------------------------------------------*/
47
48#define RECIPE_ID "xsh_molecfit_correct"
49#define RECIPE_AUTHOR "N. Fernando, B. Miszalski"
50#define RECIPE_CONTACT "nuwanthika.fernando@partner.eso.org"
51
52/*---------------------------------------------------------------------------
53 Functions prototypes
54 ---------------------------------------------------------------------------*/
55
56/*
57 * Plugin initalization, execute and cleanup handlers
58 */
59
60int xsh_molecfit_correct_create(cpl_plugin *);
61int xsh_molecfit_correct_exec(cpl_plugin *);
62int xsh_molecfit_correct_destroy(cpl_plugin *);
63
64/* The actual executor function */
65//int xsh_molecfit_correct(cpl_frameset *frameset, const cpl_parameterlist *parlist);
66
67/*----------------------------------------------------------------------------*/
71/*----------------------------------------------------------------------------*/
72
74"Applies molecfit_correct";
75
77"Applies molecfit_correct";
78
79/*----------------------------------------------------------------------------*/
83/*----------------------------------------------------------------------------*/
84
85/*----------------------------------------------------------------------------*/
89/*----------------------------------------------------------------------------*/
90
91
92/*----------------------------------------------------------------------------*/
96/*----------------------------------------------------------------------------*/
97
98/*----------------------------------------------------------------------------*/
102/*----------------------------------------------------------------------------*/
103
106/*----------------------------------------------------------------------------*/
110/*----------------------------------------------------------------------------*/
111
112/*--------------------------------------------------------------------------*/
121/*--------------------------------------------------------------------------*/
122int cpl_plugin_get_info(cpl_pluginlist *list) {
123 cpl_recipe *recipe = NULL;
124 cpl_plugin *plugin = NULL;
125
126 recipe = cpl_calloc(1, sizeof(*recipe));
127 if ( recipe == NULL ){
128 return -1;
129 }
130
131 plugin = &recipe->interface ;
132
133 cpl_plugin_init(plugin,
134 CPL_PLUGIN_API, /* Plugin API */
135 XSH_BINARY_VERSION, /* Plugin version */
136 CPL_PLUGIN_TYPE_RECIPE, /* Plugin type */
137 RECIPE_ID, /* Plugin name */
139 xsh_molecfit_correct_description, /* Detailed help */
140 RECIPE_AUTHOR, /* Author name */
141 RECIPE_CONTACT, /* Contact address */
142 xsh_get_license(), /* Copyright */
146
147 cpl_pluginlist_append(list, plugin);
148
149 return (cpl_error_get_code() != CPL_ERROR_NONE);
150 }
151
152/*--------------------------------------------------------------------------*/
162/*--------------------------------------------------------------------------*/
163
164int xsh_molecfit_correct_create(cpl_plugin *plugin){
165 cpl_recipe *recipe = NULL;
166 /*xsh_clipping_param detarc_clip_param = {2.0, 0, 0.7, 0, 0.3};
167 xsh_detect_arclines_param detarc_param =
168 {6, 3, 0, 5, 4, 1, 5, 5.0,
169 XSH_GAUSSIAN_METHOD, FALSE};
170 xsh_dispersol_param dispsol_param = { 4, 5 } ;
171 char paramname[256];
172 cpl_parameter* p=NULL;
173 int ival=DECODE_BP_FLAG_DEF;
174 */
175
176 /* Reset library state */
177 xsh_init();
178
179 /* Check input */
180 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin");
181
182 /* Get the recipe out of the plugin */
183 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
184 CPL_ERROR_TYPE_MISMATCH,
185 "Plugin is not a recipe");
186
187 recipe = (cpl_recipe *)plugin;
188
189 /* Create the parameter list in the cpl_recipe object */
190 recipe->parameters = cpl_parameterlist_new();
191 assure( recipe->parameters != NULL,
192 CPL_ERROR_ILLEGAL_OUTPUT,
193 "Memory allocation failed!");
194
195 //xsh_molecfit_correct parameters
196
197 //column_wave
198 check(xsh_parameters_new_string(recipe->parameters,RECIPE_ID,
199 "COLUMN_WAVE","WAVE",
200 "In the case of fits binary science input: name of the column in the input that identifies the wavelength."));
201
202 //column_flux
203 check(xsh_parameters_new_string(recipe->parameters,RECIPE_ID,
204 "COLUMN_FLUX","FLUX",
205 "In the case of fits binary science input: name of the column in the input that identifies the flux."));
206
207 //column_dflux
208 check(xsh_parameters_new_string(recipe->parameters,RECIPE_ID,
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."));
211
212 //threshold
213 check(xsh_parameters_new_double(recipe->parameters,RECIPE_ID,
214 "THRESHOLD",0.01,
215 "Use this value when the transmission function is lower than the specified threshold."));
216
217 cleanup:
218 if ( cpl_error_get_code() != CPL_ERROR_NONE ){
219 xsh_error_dump(CPL_MSG_ERROR);
220 return 1;
221 }
222 else {
223 return 0;
224 }
225}
226
227
228/*--------------------------------------------------------------------------*/
234/*--------------------------------------------------------------------------*/
235
236int xsh_molecfit_correct_exec(cpl_plugin *plugin) {
237 cpl_recipe *recipe = NULL;
238
239 /* Check parameter */
240 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
241
242 /* Get the recipe out of the plugin */
243 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
244 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
245
246 recipe = (cpl_recipe *)plugin;
247 /* Check recipe */
248 xsh_molecfit_correct( recipe->frames, recipe->parameters);
249
250 cleanup:
251 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
252 xsh_error_dump(CPL_MSG_ERROR);
253 cpl_error_reset();
254 return 1;
255 }
256 else {
257 return 0;
258 }
259}
260
261/*--------------------------------------------------------------------------*/
267/*--------------------------------------------------------------------------*/
268int xsh_molecfit_correct_destroy(cpl_plugin *plugin)
269{
270 cpl_recipe *recipe = NULL;
271
272 /* Check parameter */
273 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
274
275 /* Get the recipe out of the plugin */
276 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
277 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
278
279 recipe = (cpl_recipe *)plugin;
280
281 xsh_free_parameterlist(&recipe->parameters);
282
283 cleanup:
284 if (cpl_error_get_code() != CPL_ERROR_NONE)
285 {
286 return 1;
287 }
288 else
289 {
290 return 0;
291 }
292}
293
294int xsh_molecfit_correct(cpl_frameset *frameset, const cpl_parameterlist *parlist){
295
296 cpl_frameset_dump(frameset,NULL);
297
298 /* Get initial errorstate */
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;//molecfit_check_and_set_groups(frameset);
302
303 cpl_parameterlist* ilist = cpl_parameterlist_new();
304 cpl_parameterlist* iframelist = cpl_parameterlist_new();
305 // get instrument specific parameter defaults
306 err = xsh_molecfit_correct_config(frameset,parlist,ilist,iframelist);
307 if(err){
308 return err;
309 }
310
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"));
313 //const char* obsmode = cpl_parameter_get_string(cpl_parameterlist_find(iframelist,"OBSMODE"));
314 //const char* is_idp = cpl_parameter_get_string(cpl_parameterlist_find(iframelist,"IDP"));
315 //const char* fname = cpl_parameter_get_string(cpl_parameterlist_find(iframelist,"INPUTFILENAME"));
316
317
318 /* Check frameset TAGS */
319 //setup some necessary frameset tags
320 cpl_frame* f = cpl_frameset_find(frameset,input_name);
321 if(f){
322 cpl_frame_set_group(f,CPL_FRAME_GROUP_RAW);
323 }
324 const char* tcor_tag = mf_wrap_tag_suffix("TELLURIC_CORR",arm,CPL_FALSE);
325 f = cpl_frameset_find(frameset,tcor_tag);
326 if(f){
327 cpl_frame_set_group(f,CPL_FRAME_GROUP_CALIB);
328 }
329
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)");
333 return err;
334 }
335
336
337 /* Check mandatory TAGS/Parameters */
338 /*
339 if (!err) {
340
341 // SCIENCE_CALCTRANS/SCIENCE : Check only the first (at least need to contain one)
342 cpl_frame *input_frame_data = cpl_frameset_find(frameset, MOLECFIT_SCIENCE);
343 if (!input_frame_data) {
344 err = cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND, "%s data not found in frameset!", MOLECFIT_SCIENCE);
345 }
346
347 // TELLURIC_CORR
348 if (!err) {
349 const cpl_frame *input_telluric_corr = cpl_frameset_find_const(frameset, MOLECFIT_TELLURIC_CORR);
350 if (!input_telluric_corr) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Illegal INPUT TELLURIC_CORR!");
351 }
352
353 // MAPPING_CORRECT
354 if (!err) {
355 const cpl_frame *input_mapping_correct = cpl_frameset_find_const(frameset, MOLECFIT_MAPPING_CORRECT);
356 if (!input_mapping_correct && (!strcmp(cpl_parameter_get_string(cpl_parameterlist_find_const(parlist, MOLECFIT_PARAMETER_MAPPING_CORRECT)), MF_PARAMETERS_NULL) ) ){
357 err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Illegal INPUT MAPPING_CORRECT!");
358 }
359 }
360 }
361 }*/
362
363
364 // TEST MAPPING CORRECT
365 /*if (!err) {
366 cpl_error_code map_err=CPL_ERROR_NONE;
367 map_err=molecfit_config_mappingchk(frameset,parlist,MOLECFIT_TELLURIC_CORR,
368 MOLECFIT_MAPPING_CORRECT,
369 "TELLURIC_CORR_EXT",
370 "MAPPING_CORRECT",
371 "SCIENCE");
372 if (map_err) cpl_msg_error(cpl_func,"Mapping Errors detected cannot proceed further");
373 }*/
374
375
376 // Recipe Parameters : Need scientific_header_primary
377 /*molecfit_correct_parameter *parameters = NULL;
378 if (!err) {
379
380 // Get recipe parameters and update the molecfit default configuration
381 cpl_msg_info(cpl_func, "Load '%s' recipe parameters ...", MOLECFIT_CORRECT);
382 parameters = molecfit_correct_parameters(frameset, parlist);
383
384 if (!parameters) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Illegal INPUT PARAMETERS!");
385 else err = cpl_error_get_code();
386 }*/
387 cpl_parameterlist* mergedlist = cpl_parameterlist_new();
388
389 cpl_msg_info(cpl_func,"calling mf_wrap_merge_parameterlists");
390 err = mf_wrap_merge_parameterlists(ilist, parlist,mergedlist);
391
392 /* Recipe Parameters : Need scientific_header_primary */
393 molecfit_correct_parameter *parameters = NULL;
394 if (!err) {
395
396 /* Get recipe parameters and update the molecfit default configuration */
397 cpl_msg_info(cpl_func, "Load 'MOLECFIT_CORRECT' recipe parameters ...");
398 /* Note: TELLURIC_CORR is loaded in mf_wrap_config_corr_init() */
399 parameters = mf_wrap_config_corr_init(frameset, mergedlist,arm);
400
401 if (!parameters) err = cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Illegal INPUT PARAMETERS!");
402 else err = cpl_error_get_code();
403 }
404
405
406 /* Load TAG = MAPPING_CORRECT */
407 cpl_table *mapping_correct = NULL;
408 if (!err) {
409
410 if (parameters->mapping_correct_table) {
411 mapping_correct = cpl_table_duplicate(parameters->mapping_correct_table);
412 } else {
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);
415 //cpl_msg_info (cpl_func, "Loading %s cpl_table", MOLECFIT_MAPPING_CORRECT);
416 mapping_correct = mf_wrap_load_unique_table(frameset, tag_name);
417 //mapping_correct = molecfit_load_unique_table(frameset, MOLECFIT_MAPPING_CORRECT);
418 }
419
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();
423 }
424
425 /*** Correct SCIENCE_CALCTRANS/SCIENCE spectra ***/
426 if (!err) {
427
428 //cpl_msg_info(cpl_func, "CORRECT input %s/%s files ", MOLECFIT_SCIENCE_CALCTRANS, MOLECFIT_SCIENCE);
429
430 cpl_size n_frames = cpl_frameset_get_size(frameset);
431 for (cpl_size frame = 0; frame < n_frames && !err; frame++) {
432
433 /* Check all inputs in frameset to get only the SCIENCE_CALCTRANS/SCIENCE frames */
434 cpl_frame *frame_data = cpl_frameset_get_position(frameset, frame);
435 const char *tag = cpl_frame_get_tag(frame_data);
436 //use strstr here, as the arm suffix may be present
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")
443 ){
444
445 /* Create a new independent cpl_frameset for this concrete input DATA frame */
446 cpl_frameset *frameset_output = cpl_frameset_new();
447 cpl_frameset_insert(frameset_output, cpl_frame_duplicate(frame_data));
448
449 /* Load every frame in the input */
450 const char *filename = cpl_frame_get_filename(frame_data);
451 mf_wrap_fits *data = mf_wrap_fits_load(filename, CPL_FALSE);
452 //molecfit_fits *data = molecfit_fits_load(filename, CPL_FALSE);
453
454 /* Check DATA */
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();
457
458 /* Convert to table for execute molecfit */
459 //if (!err) err = molecfit_data_convert_to_table( data,
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);
469
470 /* Save input DATA --> Combined (molecfit_spectrum in BINTABLE format) */
471//not relevant for xshooter
472/* if (parameters->chip_extensions) {
473
474 const char *filename_base = basename(data->filename);
475
476 char *out_combined = NULL;
477 if (parameters->suppress_extension) out_combined = cpl_sprintf("%s_%lld.fits", MOLECFIT_CORRECT_CHIPS_COMBINED, frame );
478 else out_combined = cpl_sprintf("%s_%s", MOLECFIT_CORRECT_CHIPS_COMBINED, filename_base);
479
480 cpl_size index_combined = data->v_ext[0].spectrum_data ? 0 : 1;
481 cpl_msg_info(cpl_func, "Save combined multi-extension molecfit_spectrum input FITS file ('%s') in ext=%lld ...", out_combined, index_combined);
482
483 err += molecfit_save(frameset, frameset, parlist, RECIPE_NAME, parameters->pl, MOLECFIT_CORRECT_CHIPS_COMBINED, out_combined);
484 if (!err) err = molecfit_save_mf_results(data->v_ext[index_combined].spectrum_head, out_combined, CPL_FALSE, NULL, data->v_ext[index_combined].spectrum_data, NULL);
485 }
486 */
487
488 /* Execution extensions */
489 cpl_size n_ext;
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;
493
494 /* Create output SPECTRUM SCIENCE FITS file */
495 mf_wrap_fits *spectrum_corr_data = NULL;
496 //molecfit_fits *spectrum_corr_data = NULL;
497 if (!err) {
498
499 char *spectrum_filename = cpl_sprintf("SPECTRUM_%s.fits", input_name);//data->filename);
500 //char *spectrum_filename = cpl_sprintf("SPECTRUM_%s", data->filename);
501 //char *spectrum_filename = cpl_sprintf("SPECTRUM_%s", basename(data->filename));
502 //spectrum_corr_data = molecfit_fits_create(spectrum_filename, molecfit_fits_file_image_1D, molecfit_fits_vector, data->n_ext);
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);
505
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);
508
509 /* Create dummy extensions */
510 for (cpl_size ext = 0; ext < data->n_ext; ext++) {
511 if (data->v_ext[ext].spectrum_data) {
512 cpl_size size = -1;
513 //if ( data->format == molecfit_fits_file_table ) {
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);
518 } else {
519 size = cpl_table_get_nrow(data->v_ext[ext].table);
520 }
521 }
522 //else if (data->format == molecfit_fits_file_image_1D) size = cpl_vector_get_size( data->v_ext[ext].vector);
523 //else if (data->format == molecfit_fits_file_image_2D) size = cpl_image_get_size_x( data->v_ext[ext].image );
524 //else if (data->format == molecfit_fits_file_image_3D) size = cpl_imagelist_get_size(data->v_ext[ext].cube );
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 );
528
529 spectrum_corr_data->v_ext[ext].vector = cpl_vector_new(size);
530 }
531 }
532 }
533
534 /* Loop over the data extensions */
535 int null;
536 for (cpl_size ext = 0; ext < n_ext && !err; ext++) {
537
538 /* Create spectrum header output */
539 if (!err) spectrum_corr_data->v_ext[ext].header = cpl_propertylist_duplicate(data->v_ext[ext].spectrum_head);
540
541 /* Get data extension : Only manage extensions with data */
542 if (data->v_ext[ext].spectrum_data) {
543
544 /* Get TELLURIC_CORR */
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"));
548 //only apply the threshold if it is a sensible value
549 if(threshold >= 0 && threshold <= 1.0) {
550 cpl_size vs = cpl_vector_get_size(telluric_corr);
551 //iterate over vector, applying the threshold
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);
555 }
556 }
557 }
558 //debug - shows that the threshold is applied
559 //const char* vfname = cpl_sprintf("vec%lld.fits",ext);
560 //cpl_vector_save(telluric_corr,vfname,CPL_TYPE_DOUBLE,NULL,CPL_IO_CREATE);
561
562 /* Check DATA with TELLURIC_CORR */
563 if (!telluric_corr)
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);
568
569 if (!err) {
570
571 /* Create input molecfit data */
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,
578 telluric_corr);
579
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!");
582
583
584 /* Apply correction to molecfit data */
585 if (!err) {
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);
588 }
589
590 /* Create spectrum data output */
591 if (!err) {
592
593 /* Copy data */
594 err = mf_wrap_data_update_vector(molecfit_data, parameters->chip_extensions, spectrum_corr_data, ext);
595 //err = molecfit_data_update_vector(molecfit_data, parameters->chip_extensions, spectrum_corr_data, ext);
596
597 /* Copy additional if chip combined */
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);
601 }
602 }
603 }
604
605 /* Update Input data with telluric correction */
606 if (!err) {
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);
611 /*if ( data->format == molecfit_fits_file_table ) err = molecfit_data_update_table( molecfit_data, parameters->chip_extensions, data, ext, parameters->column_flux);
612 else if (data->format == molecfit_fits_file_image_1D) err = molecfit_data_update_vector(molecfit_data, parameters->chip_extensions, data, ext);
613 else if (data->format == molecfit_fits_file_image_2D) err = molecfit_data_update_image( molecfit_data, parameters->chip_extensions, data, ext);
614 else if (data->format == molecfit_fits_file_image_3D) err = molecfit_data_update_cube( molecfit_data, parameters->chip_extensions, data, ext);
615 */
616 }
617
618 /* Cleanup */
619 if (molecfit_data) cpl_table_delete(molecfit_data);
620 }
621 }
622 }
623
624 /* Save update OUT : SPECTRUM and DATA */
625 if (!err) {
626
627 //const char *filename_base = basename(data->filename);
628 const char *filename_base = input_name;//data->filename;//basename(data->filename);
629 //const char* output_tag = mf_wrap_tag_suffix(MOLECFIT_SPECTRUM_TELLURIC_CORR,arm,CPL_FALSE);
630 //TODO: still to sort output filenames/tags etc.
631
632 /* Save input SPECTRUM extracted --> Corrected */
633 char *out_telluric_corr = NULL;
634 //const char* output_tag = mf_wrap_tag_suffix(MOLECFIT_SPECTRUM_TELLURIC_CORR,arm,CPL_FALSE);
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);
637
638 //cpl_msg_info(cpl_func, "Writing on disk [%s] %s input FITS corrected on SPECTRUM format --> %s (PRO.CATG=%s)", data->filename, tag, out_telluric_corr, MOLECFIT_SPECTRUM_TELLURIC_CORR);
639 err = mf_wrap_fits_write(frameset, frameset_output, parlist, RECIPE_NAME, MOLECFIT_SPECTRUM_TELLURIC_CORR, spectrum_corr_data, out_telluric_corr);
640
641 cpl_free(out_telluric_corr);
642
643
644 /* Save input SCIENCE --> Corrected */
645 if (!err) {
646
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);
650
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);
653 //err = molecfit_fits_write(frameset, frameset_output, parlist, RECIPE_NAME, MOLECFIT_SCIENCE_TELLURIC_CORR, data, out_data);
654
655 cpl_free(out_data);
656 }
657 }
658
659 /* Cleanup */
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);
663 //if (data ) molecfit_fits_delete(data);
664 //if (spectrum_corr_data) molecfit_fits_delete(spectrum_corr_data);
665 }
666 }
667 }
668
669 /* Cleanup */
670 if (parameters ) molecfit_correct_parameter_delete( parameters );
671 if (mapping_correct) cpl_table_delete( mapping_correct);
672
673
674 /* Check Recipe status and end */
675 if (!err && cpl_errorstate_is_equal(initial_errorstate)) {
676 cpl_msg_info(cpl_func,"Recipe successfully!");
677 } else {
678 /* Dump the error history */
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());
681 }
682
683 return err;
684}
685
686
687cpl_error_code xsh_molecfit_correct_config(cpl_frameset *frameset, const cpl_parameterlist *parlist,
688 cpl_parameterlist* ilist, cpl_parameterlist* iframelist){
689
690 //cpl_msg_info(cpl_func,"xsh_molecfit_correct_config");
691 //cpl_msg_info(cpl_func,"FRAMESET");
692 //cpl_frameset_dump(frameset,stdout);
693 //cpl_msg_info(cpl_func,"PARLIST");
694 //cpl_parameterlist_dump(parlist,stdout);
695 //cpl_msg_info(cpl_func,"");
696
697 cpl_parameterlist* iframe = cpl_parameterlist_new();
698 cpl_error_code err= CPL_ERROR_NONE;
699 err=xsh_molecfit_utils_find_input_frame(frameset, iframe);
700 if(err){
701 return err;
702 }
703
704 //const char* input_name = cpl_parameter_get_string(cpl_parameterlist_find(iframe,"INPUTNAME"));
705 //const char* arm = cpl_parameter_get_string(cpl_parameterlist_find(iframe,"ARM"));
706 //const char* obsmode = cpl_parameter_get_string(cpl_parameterlist_find(iframe,"OBSMODE"));
707 const char* is_idp = cpl_parameter_get_string(cpl_parameterlist_find(iframe,"IDP"));
708 //const char* fname = cpl_parameter_get_string(cpl_parameterlist_find(iframe,"INPUTFILENAME"));
709
710 //cpl_msg_info(cpl_func,"iframe details; INPUTNAME: %s; ARM: %s; IDP: %s; OBSMODE: %s; FILENAME: %s",input_name,arm,is_idp,obsmode,fname);
711
712 //add iframe parameters (INPUTNAME,ARM,OBSMODE,IDP) to iframelist so that we can access them from xsh_molecfit_correct
713 //these are not added to ilist, as they are only meant to be instrument dependent molecfit parameters
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"));
720
721 //merge1d
722 const char* MAPPING_CORRECT;
723 cpl_boolean USE_PRIMARY_DATA;
724 int USE_DFLUX;
725 //If IDP format
726 if(!strcmp(is_idp,"TRUE")){
727 MAPPING_CORRECT = "0,1";
728 USE_DFLUX= 0;
729 USE_PRIMARY_DATA = CPL_FALSE;
730 } else {
731 //if not IDP format
732 MAPPING_CORRECT = "1";
733 USE_PRIMARY_DATA= CPL_TRUE;
734 USE_DFLUX = 1;
735 }
736 int USE_MASK = 0;
737 cpl_boolean SUPPRESS_EXTENSION = CPL_FALSE;
738 cpl_boolean CHIP_EXTENSIONS= CPL_FALSE;
739
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));
743
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));
747 return err;
748}
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,...)
Definition: xsh_error.h:54
#define check(COMMAND)
Definition: xsh_error.h:71
#define xsh_error_dump(level)
Definition: xsh_error.h:92
int size
void xsh_free_parameterlist(cpl_parameterlist **p)
Deallocate a parameter list and set the pointer to NULL.
Definition: xsh_utils.c:2224
const char * xsh_get_license(void)
Get the pipeline copyright and license.
Definition: xsh_utils.c:1193
void xsh_init(void)
Reset library state.
Definition: xsh_utils.c:1160
int threshold
Definition: xsh_detmon_lg.c:90
#define RECIPE_CONTACT
char xsh_molecfit_correct_description_short[]
#define RECIPE_ID
#define RECIPE_AUTHOR
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)