34#include "kmo_priv_fit_profile.h"
35#include "kmo_priv_functions.h"
38#include "kmo_constants.h"
45static int kmo_fit_profile_create(cpl_plugin *);
46static int kmo_fit_profile_exec(cpl_plugin *);
47static int kmo_fit_profile_destroy(cpl_plugin *);
48static int kmo_fit_profile(cpl_parameterlist *, cpl_frameset *);
54static char kmo_fit_profile_description[] =
55"This recipe creates either spectral or spatial profiles of sources using dif-\n"
56"ferent functions to fit. Spectral profiles can be created for F1I frames (if\n"
57"WCS is defined in the input frame, the output parameters are in respect to the\n"
59"Spatial profiles can be created for F2I frames (any WCS information is ignored\n"
61"If the frames contain no noise information, constant noise is assumed for the\n"
67"F1I frames can be fitted using either 'gauss', 'moffat' or 'lorentz' function.\n"
68"F2I frames can be fitted using either 'gauss' or 'moffat' function.\n"
70"ADVANCED PARAMETERS\n"
71"-------------------\n"
73"For F1I frames the spectral range can be defined. With available WCS informa-\n"
74"tion the range can be provided in units (e.g. “1.2;1.5”), otherwise in pixels\n"
76"For F2I frames the spatial range can be defined as follow: “x1,x2;y1,y2”\n"
78"-------------------------------------------------------------------------------\n"
82" category Type Explanation Required #Frames\n"
83" -------- ----- ----------- -------- -------\n"
84" <none or any> F1I or Frame with or Y 1 \n"
85" F2I without noise \n"
90" category Type Explanation\n"
91" -------- ----- -----------\n"
92" FIT_PROFILE F1I Fitted profile (without noise frame)\n"
93" or (3 Extensions) \n"
95"-------------------------------------------------------------------------------\n"
120 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
121 cpl_plugin *plugin = &recipe->interface;
123 cpl_plugin_init(plugin,
126 CPL_PLUGIN_TYPE_RECIPE,
128 "Fit spectral line profiles as well as spatial profiles"
129 " with a simple function - for example to measure "
130 "resolution or find the centre of a source",
131 kmo_fit_profile_description,
133 "https://support.eso.org/",
135 kmo_fit_profile_create,
136 kmo_fit_profile_exec,
137 kmo_fit_profile_destroy);
139 cpl_pluginlist_append(list, plugin);
151static int kmo_fit_profile_create(cpl_plugin *plugin)
157 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
158 recipe = (cpl_recipe *)plugin;
163 recipe->parameters = cpl_parameterlist_new();
167 p = cpl_parameter_new_value(
"kmos.kmo_fit_profile.method",
169 "Either fit \"gauss\", \"moffat\" or "
170 "\"lorentz\" for 1D data."
171 "Either fit \"gauss\" or \"moffat\" for "
173 "kmos.kmo_fit_profile",
175 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"method");
176 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
177 cpl_parameterlist_append(recipe->parameters, p);
180 p = cpl_parameter_new_value(
"kmos.kmo_fit_profile.range",
182 "The spectral or spatial range to combine. "
183 "Default is the whole range. "
184 "e.g. F1I: \"0.5,2.1\" (microns), "
185 "e.g. F2I: \"1,7;3,10\" (pixels: x1,x2;y1,y2), "
186 "pixels are counted from 1.",
187 "kmos.kmo_fit_profile",
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);
201static int kmo_fit_profile_exec(cpl_plugin *plugin)
206 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
207 recipe = (cpl_recipe *)plugin;
210 return kmo_fit_profile(recipe->parameters, recipe->frames);
218static int kmo_fit_profile_destroy(cpl_plugin *plugin)
223 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
224 recipe = (cpl_recipe *)plugin;
227 cpl_parameterlist_delete(recipe->parameters);
245static int kmo_fit_profile(cpl_parameterlist *parlist, cpl_frameset *frameset)
247 cpl_image *data_img_in = NULL,
248 *data_img_in2 = NULL,
249 *data_img_out = NULL,
250 *noise_img_in = NULL,
251 *noise_img_in2 = NULL;
253 cpl_vector *data_vec_in = NULL,
254 *data_vec_out = NULL,
255 *noise_vec_in = NULL,
264 cpl_frame *frame = NULL;
265 cpl_frame *frame_final = NULL;
285 const char *ranges_txt = NULL,
287 const char *input_tag = NULL;
288 const char *ocs_name_header = NULL;
289 const char *ocs_name = NULL;
291 cpl_propertylist *sub_header_data = NULL,
292 *sub_header_noise = NULL,
295 cpl_propertylist *header = NULL;
299 cpl_errorstate curr_err;
303 kmo_init_fits_desc(&desc);
306 KMO_TRY_ASSURE((parlist != NULL) &&
308 CPL_ERROR_NULL_INPUT,
309 "Not all input data is provided!");
311 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1,
312 CPL_ERROR_NULL_INPUT,
313 "A fits-file must be provided!");
316 if (cpl_frameset_count_tags(frameset,
"0") > 0)
318 else if (cpl_frameset_count_tags(frameset, COMMANDLINE) > 0)
319 input_tag = COMMANDLINE ;
320 else if (cpl_frameset_count_tags(frameset, MAKE_IMAGE) > 0)
321 input_tag = MAKE_IMAGE ;
323 cpl_msg_error(__func__,
"Missing input frames");
324 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
328 KMO_TRY_EXIT_IF_NULL(
329 frame = kmo_dfs_get_frame(frameset, input_tag));
331 header = kmo_dfs_load_primary_header(frameset, input_tag);
333 cpl_error_code error = CPL_ERROR_NONE;
334 error |= cpl_frame_set_level(frame, CPL_FRAME_LEVEL_TEMPORARY);
337 desc = kmo_identify_fits_header(
338 cpl_frame_get_filename(frame));
339 char * fit_profile_tmp = cpl_sprintf(
"%s_tmp.fits", FIT_PROFILE) ;
341 KMO_TRY_CHECK_ERROR_STATE();
343 KMO_TRY_ASSURE((desc.fits_type == f2i_fits) ||
344 (desc.fits_type == f1i_fits),
345 CPL_ERROR_ILLEGAL_INPUT,
346 "DATA isn't in the correct format (either F2I or F1I)!");
348 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset) == 1,
349 CPL_ERROR_ILLEGAL_INPUT,
350 "Cannot identify RAW and CALIB frames!");
353 cpl_msg_info(cpl_func,
"--- Parameter setup for kmo_fit_profile ---");
355 KMO_TRY_EXIT_IF_NULL(
356 method = kmo_dfs_get_parameter_string(parlist,
357 "kmos.kmo_fit_profile.method"));
358 KMO_TRY_EXIT_IF_ERROR(
359 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fit_profile.method"));
361 ranges_txt = kmo_dfs_get_parameter_string(parlist,
362 "kmos.kmo_fit_profile.range");
363 KMO_TRY_CHECK_ERROR_STATE();
364 KMO_TRY_EXIT_IF_ERROR(
365 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fit_profile.range"));
367 cpl_msg_info(
"",
"-------------------------------------------");
369 if (strcmp(ranges_txt,
"") != 0) {
371 ranges = kmo_identify_ranges(ranges_txt);
372 KMO_TRY_CHECK_ERROR_STATE();
374 KMO_TRY_EXIT_IF_NULL(
375 pranges = cpl_vector_get_data(ranges));
377 KMO_TRY_ASSURE((pranges[0] < pranges[1]),
378 CPL_ERROR_ILLEGAL_INPUT,
379 "x1 must be smaller than x2!");
381 KMO_TRY_ASSURE((((desc.fits_type == f2i_fits) &&
382 (cpl_vector_get_size(ranges) == 4) ) || (
383 (desc.fits_type == f1i_fits) &&
384 (cpl_vector_get_size(ranges) == 2) )),
385 CPL_ERROR_ILLEGAL_INPUT,
386 "'range' must contain 2 values for F1I and "
387 "4 values for F2I!");
389 if (desc.fits_type == f2i_fits) {
395 KMO_TRY_ASSURE((x1 > 0) &&
397 (x2 < desc.naxis1) &&
399 CPL_ERROR_ILLEGAL_INPUT,
400 "Provided range is larger than images in F2I!");
402 KMO_TRY_ASSURE(y1 < y2,
403 CPL_ERROR_ILLEGAL_INPUT,
404 "y1 must be smaller than y2!");
411 if (desc.fits_type == f2i_fits) {
417 ranges = cpl_vector_new(2);
418 cpl_vector_set(ranges, 0, 1);
419 cpl_vector_set(ranges, 1, desc.naxis1);
424 KMO_TRY_EXIT_IF_ERROR(
427 cpl_propertylist_save(header, fit_profile_tmp, CPL_IO_CREATE));
430 if (desc.ex_noise == TRUE) {
431 nr_devices = desc.nr_ext / 2;
433 nr_devices = desc.nr_ext;
436 for (i = 1; i <= nr_devices; i++) {
437 if (desc.ex_noise == FALSE) {
438 devnr = desc.sub_desc[i - 1].device_nr;
440 devnr = desc.sub_desc[2 * i - 1].device_nr;
443 if (desc.ex_badpix == FALSE) {
444 index_data = kmo_identify_index_desc(desc, devnr, FALSE);
446 index_data = kmo_identify_index_desc(desc, devnr, 2);
448 KMO_TRY_CHECK_ERROR_STATE();
451 index_noise = kmo_identify_index_desc(desc, devnr, TRUE);
453 KMO_TRY_CHECK_ERROR_STATE();
458 KMO_TRY_EXIT_IF_NULL(
459 sub_header_data = kmo_dfs_load_sub_header(frameset, input_tag, devnr,
464 curr_err = cpl_errorstate_get();
465 ocs_name_header = cpl_sprintf(
"%s%d%s", IFU_NAME_PREFIX, i, IFU_NAME_POSTFIX);
466 ocs_name = cpl_propertylist_get_string(sub_header_data, ocs_name_header);
469 if ((desc.sub_desc[index_data-1].valid_data == TRUE) && (strcmp(ocs_name,
"Sky")) && (strcmp(ocs_name,
""))) {
472 cpl_errorstate_set(curr_err);
474 KMO_TRY_CHECK_ERROR_STATE();
481 KMO_TRY_EXIT_IF_NULL(
482 sub_header_noise = kmo_dfs_load_sub_header(frameset, input_tag,
487 if (desc.fits_type == f2i_fits) {
496 KMO_TRY_EXIT_IF_NULL(
497 data_img_in = kmo_dfs_load_image(frameset, input_tag,
498 devnr, FALSE, FALSE, NULL));
500 KMO_TRY_EXIT_IF_NULL(
501 data_img_in2 = cpl_image_extract(data_img_in,
505 if (desc.ex_noise && desc.sub_desc[index_noise-1].valid_data) {
509 KMO_TRY_EXIT_IF_NULL(
510 noise_img_in = kmo_dfs_load_image(frameset, input_tag,
511 devnr, TRUE, FALSE, NULL));
513 KMO_TRY_EXIT_IF_NULL(
514 noise_img_in2 = cpl_image_extract(noise_img_in,
519 KMO_TRY_EXIT_IF_NULL(
520 fit_par = kmo_fit_profile_2D(data_img_in2,
525 cpl_vector_delete(fit_par); fit_par = NULL;
527 if (cpl_propertylist_get_double(pl, FIT_INTENSITY) > 5){
532 KMO_TRY_EXIT_IF_ERROR(
533 cpl_propertylist_append(sub_header_data, pl));
536 KMO_TRY_EXIT_IF_ERROR(
539 kmclipm_image_save(data_img_out, fit_profile_tmp,
540 CPL_BPP_IEEE_FLOAT, sub_header_data, CPL_IO_EXTEND, 0./0.));
543 cpl_image_delete(data_img_in); data_img_in = NULL;
544 cpl_image_delete(data_img_in2); data_img_in2 = NULL;
545 cpl_image_delete(data_img_out); data_img_out = NULL;
546 cpl_image_delete(noise_img_in); noise_img_in = NULL;
547 cpl_image_delete(noise_img_in2); noise_img_in2 = NULL;
554 kmclipm_vector *ddd = NULL;
558 KMO_TRY_EXIT_IF_NULL(
559 ddd = kmo_dfs_load_vector(frameset, input_tag,
561 data_vec_in = kmclipm_vector_create_non_rejected(ddd);
562 kmclipm_vector_delete(ddd); ddd = NULL;
566 if (cpl_propertylist_has(sub_header_data, CRPIX1) &&
567 cpl_propertylist_has(sub_header_data, CRVAL1) &&
568 cpl_propertylist_has(sub_header_data, CDELT1))
570 crpix1 = cpl_propertylist_get_double(sub_header_data,
572 crval1 = cpl_propertylist_get_double(sub_header_data,
574 cdelt1 = cpl_propertylist_get_double(sub_header_data,
577 if (strcmp(ranges_txt,
"") == 0) {
578 cpl_vector_set(ranges, 0,
580 cdelt1*(cpl_vector_get(ranges,0)-1));
581 cpl_vector_set(ranges, 1,
583 cdelt1*(cpl_vector_get(ranges,1)-1));
598 KMO_TRY_EXIT_IF_NULL(
599 ranges2 = kmo_identify_slices(ranges,
604 KMO_TRY_EXIT_IF_NULL(
605 pranges = cpl_vector_get_data(ranges2));
608 for (j = 0; j < cpl_vector_get_size(ranges2); j++) {
609 if ((pranges[j] == 1) && (x1 == -1)) {
612 if ((pranges[j] == 1) && (x1 != -1)) {
616 cpl_vector_delete(ranges2); ranges2 = NULL;
619 KMO_TRY_EXIT_IF_NULL(
620 lambda_vec = kmo_create_lambda_vec(desc.naxis1,
625 KMO_TRY_EXIT_IF_NULL(
626 lambda_vec2 = cpl_vector_extract(lambda_vec, x1, x2, 1));
628 KMO_TRY_EXIT_IF_NULL(
629 data_vec2 = cpl_vector_extract(data_vec_in, x1, x2, 1));
633 if (desc.ex_noise && desc.sub_desc[index_noise-1].valid_data) {
637 KMO_TRY_EXIT_IF_NULL(
638 ddd = kmo_dfs_load_vector(frameset, input_tag,
640 noise_vec_in = kmclipm_vector_create_non_rejected(ddd);
641 kmclipm_vector_delete(ddd); ddd =NULL;
643 KMO_TRY_EXIT_IF_NULL(
644 noise_vec2 = cpl_vector_extract(noise_vec_in,
649 KMO_TRY_EXIT_IF_NULL(
650 fit_par = kmo_fit_profile_1D(lambda_vec2,
657 if (cpl_propertylist_get_double(pl, FIT_INTENSITY) > 5){
661 cpl_vector_delete(fit_par); fit_par = NULL;
664 if (cpl_propertylist_has(sub_header_data, CRPIX1) &&
665 cpl_propertylist_has(sub_header_data, CRVAL1) &&
666 cpl_propertylist_has(sub_header_data, CDELT1))
668 KMO_TRY_EXIT_IF_ERROR(
669 kmclipm_update_property_double(sub_header_data,
672 "[pix] Reference pixel in x"));
675 KMO_TRY_EXIT_IF_ERROR(
676 kmclipm_update_property_double(sub_header_noise,
679 "[pix] Reference pixel in x"));
684 KMO_TRY_EXIT_IF_ERROR(
685 cpl_propertylist_append(sub_header_data, pl));
688 ddd = kmclipm_vector_create(cpl_vector_duplicate(data_vec_out));
689 KMO_TRY_EXIT_IF_ERROR(
692 kmclipm_vector_save(ddd, fit_profile_tmp,
693 CPL_BPP_IEEE_FLOAT, sub_header_data, CPL_IO_EXTEND, 0./0.));
695 kmclipm_vector_delete(ddd); ddd = NULL;
698 cpl_vector_delete(data_vec_in); data_vec_in = NULL;
699 cpl_vector_delete(data_vec_out); data_vec_out = NULL;
700 cpl_vector_delete(noise_vec_in); noise_vec_in = NULL;
701 cpl_vector_delete(noise_vec2); noise_vec2 = NULL;
702 cpl_vector_delete(lambda_vec); lambda_vec = NULL;
703 cpl_vector_delete(lambda_vec2); lambda_vec2 = NULL;
704 cpl_vector_delete(data_vec2); data_vec2 = NULL;
707 cpl_propertylist_delete(pl); pl = NULL;
710 KMO_TRY_EXIT_IF_ERROR(
712 cpl_propertylist_save(sub_header_data, fit_profile_tmp, CPL_IO_EXTEND));
715 KMO_TRY_EXIT_IF_ERROR(
717 cpl_propertylist_save(sub_header_data, fit_profile_tmp, CPL_IO_EXTEND));
722 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
723 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
728 new_header = kmclipm_propertylist_load(fit_profile_tmp, 0);
730 kmclipm_update_property_double(new_header, QC_NR_STARS, nr_stars,
731 "Number of extensions with PRO.FIT.INTENS > 5.");
733 frame_final = kmo_dfs_get_frame(frameset, input_tag);
734 error |= cpl_frame_set_level(frame_final, CPL_FRAME_LEVEL_FINAL);
737 KMO_TRY_EXIT_IF_ERROR(
738 kmo_dfs_save_main_header(frameset, FIT_PROFILE,
"", frame_final,
739 new_header, parlist, cpl_func));
740 desc = kmo_identify_fits_header(cpl_frame_get_filename(frame_final));
742 for (i = 1; i <= nr_devices; i++) {
752 KMO_TRY_EXIT_IF_NULL(
753 sub_header_data = kmclipm_propertylist_load(fit_profile_tmp, devnr));
757 KMO_TRY_EXIT_IF_NULL(
758 sub_header_noise = kmclipm_propertylist_load(fit_profile_tmp, devnr));
762 curr_err = cpl_errorstate_get();
763 ocs_name_header = cpl_sprintf(
"%s%d%s", IFU_NAME_PREFIX, i, IFU_NAME_POSTFIX);
764 ocs_name = cpl_propertylist_get_string(sub_header_data, ocs_name_header);
765 if ((desc.sub_desc[devnr-1].valid_data == TRUE) && (strcmp(ocs_name,
"Sky")) && (strcmp(ocs_name,
""))) {
768 cpl_errorstate_set(curr_err);
770 if (desc.fits_type == f2i_fits) {
774 KMO_TRY_EXIT_IF_NULL(
775 data_img_in = kmclipm_image_load(fit_profile_tmp, CPL_TYPE_FLOAT, 0, devnr));
779 KMO_TRY_EXIT_IF_ERROR(
780 kmo_dfs_save_image(data_img_in, FIT_PROFILE,
"",
781 sub_header_data, 0./0.));
786 kmclipm_vector *ddd = NULL;
789 KMO_TRY_EXIT_IF_NULL(
790 ddd = kmclipm_vector_load(fit_profile_tmp, devnr));
793 KMO_TRY_EXIT_IF_ERROR(
794 kmo_dfs_save_vector(ddd, FIT_PROFILE,
"",
795 sub_header_data, 0./0.));
796 kmclipm_vector_delete(ddd); ddd = NULL;
800 KMO_TRY_EXIT_IF_ERROR(
801 kmo_dfs_save_sub_header(FIT_PROFILE,
"", sub_header_noise));
818 unlink(cpl_sprintf(
"%s_tmp.fits",FIT_PROFILE));
820 kmo_free_fits_desc(&desc);
821 cpl_image_delete(data_img_in); data_img_in = NULL;
822 cpl_image_delete(data_img_in2); data_img_in2 = NULL;
823 cpl_image_delete(data_img_out); data_img_out = NULL;
824 cpl_image_delete(noise_img_in); noise_img_in = NULL;
825 cpl_image_delete(noise_img_in2); noise_img_in2 = NULL;
826 cpl_vector_delete(data_vec_in); data_vec_in = NULL;
827 cpl_vector_delete(data_vec2); data_vec2 = NULL;
828 cpl_vector_delete(data_vec_out); data_vec_out = NULL;
829 cpl_vector_delete(noise_vec_in); noise_vec_in = NULL;
830 cpl_vector_delete(noise_vec2); noise_vec2 = NULL;
831 cpl_vector_delete(lambda_vec); lambda_vec = NULL;
832 cpl_vector_delete(lambda_vec2); lambda_vec2 = NULL;
833 cpl_vector_delete(fit_par); fit_par = NULL;
834 cpl_vector_delete(ranges); ranges = NULL;
835 cpl_vector_delete(ranges2); ranges2 = NULL;
836 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
837 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
839 cpl_propertylist_delete(header); header = NULL;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.