36#include "kmo_priv_make_image.h"
37#include "kmo_priv_functions.h"
38#include "kmo_constants.h"
44static int kmo_make_image_create(cpl_plugin *);
45static int kmo_make_image_exec(cpl_plugin *);
46static int kmo_make_image_destroy(cpl_plugin *);
47static int kmo_make_image(cpl_parameterlist *, cpl_frameset *);
53static char kmo_make_image_description[] =
54"This recipe collapses a cube along the spectral axis using rejection. By \n"
55"default all spectral slices are averaged.\n"
56"Errors are propagated for the same spectral ranges as for the input data if\n"
57"a noise map is provided.\n"
62"The spectral range can be delimited to one or several sub-ranges like \n"
63"\"1.8,1.9\" or \"1.8,1.9; 2.0,2.11\"\n"
66"Following methods of frame combination are available:\n"
67" * 'ksigma' (Default)\n"
68" An iterative sigma clipping. For each position all pixels in the\n"
69" spectrum are examined. If they deviate significantly, they will be\n"
70" rejected according to the conditions:\n"
71" val > mean + stdev * cpos_rej\n"
73" val < mean - stdev * cneg_rej\n"
74" where --cpos_rej, --cneg_rej and --citer are the wished parameters\n"
75" In the first iteration median and percentile level are used.\n"
77" At each pixel position the median is calculated.\n"
79" At each pixel position the average is calculated.\n"
81" At each pixel position the sum is calculated.\n"
83" The specified number of min and max pixel values will be rejected.\n"
84" --cmax and --cmin apply to this method.\n"
86"ADVANCED PARAMETERS\n"
87"-------------------\n"
89"Optionally an OH spectrum can be provided. In this case a threshold can be\n"
90"defined. The wavelengths of values above the threshold level in the OH\n"
91"spectrum are omitted in the input frame. This parameter can be combined with\n"
92"the --range parameter. Negative threshold values are ignored.\n"
93"Own spectra can be converted into the required F1S KMOS FITS format for the\n"
94"OH spectrum using kmo_fits_stack.\n"
99" see --cmethod='ksigma'\n"
102" see --cmethod='min_max'\n"
104"---------------------------------------------------------------------------\n"
106" DO CATG Type Explanation Required #Frames\n"
107" ------- ----- ----------- -------- -------\n"
108" <none or any> F3I data frame Y 1 \n"
109" <none or any> F1S OH line spectrum N 0,1 \n"
112" DO CATG Type Explanation\n"
113" ------- ----- -----------\n"
114" MAKE_IMAGE F2I Collapsed data cubes\n"
115"---------------------------------------------------------------------------\n"
138 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
139 cpl_plugin *plugin = &recipe->interface;
141 cpl_plugin_init(plugin,
144 CPL_PLUGIN_TYPE_RECIPE,
146 "Collapse a cube to create a spatial image",
147 kmo_make_image_description,
149 "https://support.eso.org/",
151 kmo_make_image_create,
153 kmo_make_image_destroy);
155 cpl_pluginlist_append(list, plugin);
169static int kmo_make_image_create(cpl_plugin *plugin)
175 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
176 recipe = (cpl_recipe *)plugin;
181 recipe->parameters = cpl_parameterlist_new();
185 p = cpl_parameter_new_value(
"kmos.kmo_make_image.range", CPL_TYPE_STRING,
186 "The spectral ranges to combine. e.g."
187 "\"x1_start,x1_end;x2_start,x2_end\" (microns)",
188 "kmos.kmo_make_image",
"");
189 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"range");
190 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
191 cpl_parameterlist_append(recipe->parameters, p);
194 p = cpl_parameter_new_value(
"kmos.kmo_make_image.threshold",
195 CPL_TYPE_DOUBLE,
"The OH threshold level (%)",
196 "kmos.kmo_make_image", 0.1);
197 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"threshold");
198 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
199 cpl_parameterlist_append(recipe->parameters, p);
201 return kmos_combine_pars_create(recipe->parameters,
"kmos.kmo_make_image",
202 DEF_REJ_METHOD, FALSE);
212static int kmo_make_image_exec(cpl_plugin *plugin)
217 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
218 recipe = (cpl_recipe *)plugin;
221 return kmo_make_image(recipe->parameters, recipe->frames);
231static int kmo_make_image_destroy(cpl_plugin *plugin)
236 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
237 recipe = (cpl_recipe *)plugin;
240 cpl_parameterlist_delete(recipe->parameters);
259static int kmo_make_image(cpl_parameterlist *parlist, cpl_frameset *frameset)
261 const char *cmethod = NULL;
263 double threshold = 0.0,
273 cpl_imagelist *data_in = NULL,
276 cpl_image *data_out = NULL,
279 const char *ranges_txt = NULL;
281 cpl_vector *ranges = NULL,
282 *identified_slices = NULL,
283 *spec_data_in = NULL,
284 *spec_lambda_in = NULL;
297 cpl_propertylist *sub_header_data = NULL,
298 *sub_header_noise = NULL,
301 main_fits_desc desc1,
304 cpl_frame *op1_frame = NULL,
309 kmo_init_fits_desc(&desc1);
310 kmo_init_fits_desc(&desc2);
313 KMO_TRY_ASSURE((parlist != NULL) && (frameset != NULL),
314 CPL_ERROR_NULL_INPUT,
"Not all input data is provided");
316 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset) == 1,
317 CPL_ERROR_ILLEGAL_INPUT,
"Cannot identify RAW and CALIB frames");
319 cpl_msg_info(
"",
"--- Parameter setup for kmo_make_image ----");
320 threshold = kmo_dfs_get_parameter_double(parlist,
321 "kmos.kmo_make_image.threshold");
322 KMO_TRY_CHECK_ERROR_STATE();
323 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist,
324 "kmos.kmo_make_image.threshold"));
326 ranges_txt = kmo_dfs_get_parameter_string(parlist,
327 "kmos.kmo_make_image.range");
328 KMO_TRY_CHECK_ERROR_STATE();
329 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist,
330 "kmos.kmo_make_image.range"));
331 ranges = kmo_identify_ranges(ranges_txt);
332 KMO_TRY_CHECK_ERROR_STATE();
334 KMO_TRY_EXIT_IF_ERROR(kmos_combine_pars_load(parlist,
335 "kmos.kmo_make_image", &cmethod, &cpos_rej, &cneg_rej,
336 &citer, &cmin, &cmax, FALSE));
337 cpl_msg_info(
"",
"-------------------------------------------");
339 KMO_TRY_ASSURE((cpl_frameset_get_size(frameset) == 1) ||
340 ((cpl_frameset_get_size(frameset) == 2) && (threshold != 0.0)),
341 CPL_ERROR_NULL_INPUT,
342 "A cube or a cube and a OH line spectrum must be provided");
345 op1_frame=cpl_frameset_get_position(frameset, 0) ;
346 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(op1_frame));
347 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Wrong File Format");
348 KMO_TRY_ASSURE(desc1.fits_type == f3i_fits, CPL_ERROR_ILLEGAL_INPUT,
349 "First file has wrong data type (expect F3I)");
352 if (cpl_frameset_get_size(frameset) > 1) {
353 op2_frame=cpl_frameset_get_position(frameset, 1) ;
354 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(op2_frame));
355 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Wrong File Format");
356 KMO_TRY_ASSURE(desc2.fits_type == f1s_fits, CPL_ERROR_ILLEGAL_INPUT,
357 "Second file has wrong data type (expect F1S)");
360 spec_header = kmos_dfs_load_sub_header(op2_frame, 1, FALSE);
361 KMO_TRY_EXIT_IF_NULL(spec_header) ;
362 KMO_TRY_ASSURE(cpl_propertylist_get_int(spec_header, NAXIS) == 1,
363 CPL_ERROR_ILLEGAL_INPUT,
364 "Second input file must be a vector");
365 spec_crpix = cpl_propertylist_get_double(spec_header, CRPIX1);
366 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Cannot get CRPIX1");
367 spec_crval = cpl_propertylist_get_double(spec_header, CRVAL1);
368 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Cannot get CRVAL1");
369 spec_cdelt = cpl_propertylist_get_double(spec_header, CDELT1);
370 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Cannot get CDELT1");
373 kmclipm_vector * tmp_vec ;
374 tmp_vec = kmos_dfs_load_vector(op2_frame, 1, FALSE) ;
375 spec_data_in = kmclipm_vector_create_non_rejected(tmp_vec);
376 kmclipm_vector_delete(tmp_vec);
377 KMO_TRY_EXIT_IF_NULL(spec_data_in) ;
380 threshold = threshold * cpl_vector_get_max(spec_data_in);
383 KMO_TRY_EXIT_IF_NULL(
384 spec_lambda_in = kmo_create_lambda_vec(
385 cpl_vector_get_size(spec_data_in),
386 (
int)spec_crpix, spec_crval, spec_cdelt));
390 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, MAKE_IMAGE,
391 "", op1_frame, NULL, parlist, cpl_func));
394 if (desc1.ex_noise == TRUE) {
395 nr_devices = desc1.nr_ext / 2;
397 nr_devices = desc1.nr_ext;
400 for (i = 1; i <= nr_devices; i++) {
403 if (desc1.ex_noise == FALSE) {
404 devnr = desc1.sub_desc[i - 1].device_nr;
406 devnr = desc1.sub_desc[2 * i - 1].device_nr;
410 if (desc1.ex_badpix == FALSE) {
411 index_data = kmo_identify_index_desc(desc1, devnr, FALSE);
413 index_data = kmo_identify_index_desc(desc1, devnr, 2);
415 KMO_TRY_CHECK_ERROR_STATE();
418 if (desc1.ex_noise) {
419 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE);
421 KMO_TRY_CHECK_ERROR_STATE();
424 sub_header_data = kmos_dfs_load_sub_header(op1_frame, devnr, FALSE);
425 KMO_TRY_EXIT_IF_NULL(sub_header_data) ;
429 if (desc1.sub_desc[index_data-1].valid_data == TRUE) {
434 if (desc1.ex_noise) {
435 sub_header_noise = kmos_dfs_load_sub_header(op1_frame, devnr,
437 KMO_TRY_EXIT_IF_NULL(sub_header_noise) ;
438 if (cpl_propertylist_has(sub_header_noise, CRPIX3))
439 cpl_propertylist_erase(sub_header_noise, CRPIX3);
440 if (cpl_propertylist_has(sub_header_noise, CRVAL3))
441 cpl_propertylist_erase(sub_header_noise, CRVAL3);
442 if (cpl_propertylist_has(sub_header_noise, CDELT3))
443 cpl_propertylist_erase(sub_header_noise, CDELT3);
444 if (cpl_propertylist_has(sub_header_noise, CTYPE3))
445 cpl_propertylist_erase(sub_header_noise, CTYPE3);
446 if (cpl_propertylist_has(sub_header_noise, CUNIT3))
447 cpl_propertylist_erase(sub_header_noise, CUNIT3);
448 if (cpl_propertylist_has(sub_header_noise, CD1_3))
449 cpl_propertylist_erase(sub_header_noise, CD1_3);
450 if (cpl_propertylist_has(sub_header_noise, CD2_3))
451 cpl_propertylist_erase(sub_header_noise, CD2_3);
452 if (cpl_propertylist_has(sub_header_noise, CD3_3))
453 cpl_propertylist_erase(sub_header_noise, CD3_3);
454 if (cpl_propertylist_has(sub_header_noise, CD3_2))
455 cpl_propertylist_erase(sub_header_noise, CD3_2);
456 if (cpl_propertylist_has(sub_header_noise, CD3_1))
457 cpl_propertylist_erase(sub_header_noise, CD3_1);
462 data_in = kmos_dfs_load_cube(op1_frame, devnr, FALSE) ;
463 KMO_TRY_EXIT_IF_NULL(data_in) ;
466 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data){
467 noise_in = kmos_dfs_load_cube(op1_frame, devnr, TRUE) ;
468 KMO_TRY_EXIT_IF_NULL(noise_in) ;
472 ifu_crpix = cpl_propertylist_get_double(sub_header_data,CRPIX3);
473 KMO_TRY_CHECK_ERROR_STATE_MSG(
"CRPIX3 is missing");
474 ifu_crval = cpl_propertylist_get_double(sub_header_data,CRVAL3);
475 KMO_TRY_CHECK_ERROR_STATE_MSG(
"CRVAL3 is missing");
476 ifu_cdelt = cpl_propertylist_get_double(sub_header_data,CDELT3);
477 KMO_TRY_CHECK_ERROR_STATE_MSG(
"CDELT3 is missing");
479 if (spec_data_in == NULL) {
480 identified_slices = kmo_identify_slices(ranges, ifu_crpix,
481 ifu_crval, ifu_cdelt, desc1.naxis3);
483 identified_slices = kmo_identify_slices_with_oh(
484 spec_data_in, spec_lambda_in, ranges, threshold,
485 ifu_crpix, ifu_crval, ifu_cdelt, desc1.naxis3);
487 KMO_TRY_EXIT_IF_NULL(identified_slices) ;
489 if (cpl_propertylist_has(sub_header_data, CRPIX3))
490 cpl_propertylist_erase(sub_header_data, CRPIX3);
491 if (cpl_propertylist_has(sub_header_data, CRVAL3))
492 cpl_propertylist_erase(sub_header_data, CRVAL3);
493 if (cpl_propertylist_has(sub_header_data, CDELT3))
494 cpl_propertylist_erase(sub_header_data, CDELT3);
495 if (cpl_propertylist_has(sub_header_data, CTYPE3))
496 cpl_propertylist_erase(sub_header_data, CTYPE3);
497 if (cpl_propertylist_has(sub_header_data, CUNIT3))
498 cpl_propertylist_erase(sub_header_data, CUNIT3);
499 if (cpl_propertylist_has(sub_header_data, CD1_3))
500 cpl_propertylist_erase(sub_header_data, CD1_3);
501 if (cpl_propertylist_has(sub_header_data, CD2_3))
502 cpl_propertylist_erase(sub_header_data, CD2_3);
503 if (cpl_propertylist_has(sub_header_data, CD3_3))
504 cpl_propertylist_erase(sub_header_data, CD3_3);
505 if (cpl_propertylist_has(sub_header_data, CD3_2))
506 cpl_propertylist_erase(sub_header_data, CD3_2);
507 if (cpl_propertylist_has(sub_header_data, CD3_1))
508 cpl_propertylist_erase(sub_header_data, CD3_1);
511 KMO_TRY_EXIT_IF_ERROR(kmclipm_make_image(data_in, noise_in,
512 &data_out, &noise_out, identified_slices, cmethod,
513 cpos_rej, cneg_rej, citer, cmax, cmin));
515 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(data_out, MAKE_IMAGE,
516 "", sub_header_data, 0./0.));
519 if (desc1.ex_noise) {
520 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(noise_out,
521 MAKE_IMAGE,
"", sub_header_noise, 0./0.));
525 cpl_imagelist_delete(data_in); data_in = NULL;
526 cpl_imagelist_delete(noise_in); noise_in = NULL;
527 cpl_image_delete(data_out); data_out = NULL;
528 cpl_image_delete(noise_out); noise_out = NULL;
529 cpl_vector_delete(identified_slices); identified_slices = NULL;
531 if (cpl_propertylist_has(sub_header_data, CRPIX3))
532 cpl_propertylist_erase(sub_header_data, CRPIX3);
533 if (cpl_propertylist_has(sub_header_data, CRVAL3))
534 cpl_propertylist_erase(sub_header_data, CRVAL3);
535 if (cpl_propertylist_has(sub_header_data, CDELT3))
536 cpl_propertylist_erase(sub_header_data, CDELT3);
537 if (cpl_propertylist_has(sub_header_data, CTYPE3))
538 cpl_propertylist_erase(sub_header_data, CTYPE3);
539 if (cpl_propertylist_has(sub_header_data, CUNIT3))
540 cpl_propertylist_erase(sub_header_data, CUNIT3);
541 if (cpl_propertylist_has(sub_header_data, CD1_3))
542 cpl_propertylist_erase(sub_header_data, CD1_3);
543 if (cpl_propertylist_has(sub_header_data, CD2_3))
544 cpl_propertylist_erase(sub_header_data, CD2_3);
545 if (cpl_propertylist_has(sub_header_data, CD3_3))
546 cpl_propertylist_erase(sub_header_data, CD3_3);
547 if (cpl_propertylist_has(sub_header_data, CD3_2))
548 cpl_propertylist_erase(sub_header_data, CD3_2);
549 if (cpl_propertylist_has(sub_header_data, CD3_1))
550 cpl_propertylist_erase(sub_header_data, CD3_1);
553 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_sub_header(MAKE_IMAGE,
"",
556 if (desc1.ex_noise) {
557 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_sub_header(MAKE_IMAGE,
558 "", sub_header_noise));
563 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
564 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
573 kmo_free_fits_desc(&desc1);
574 kmo_free_fits_desc(&desc2);
575 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
576 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
577 cpl_propertylist_delete(spec_header); spec_header = NULL;
578 cpl_imagelist_delete(data_in); data_in = NULL;
579 cpl_imagelist_delete(noise_in); noise_in = NULL;
580 cpl_image_delete(data_out); data_out = NULL;
581 cpl_image_delete(noise_out); noise_out = NULL;
582 cpl_vector_delete(spec_data_in); spec_data_in = NULL;
583 cpl_vector_delete(spec_lambda_in); spec_lambda_in = NULL;
584 cpl_vector_delete(ranges); ranges = NULL;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.