29#include "kmclipm_constants.h"
30#include "kmclipm_functions.h"
37static int kmo_fits_strip_create(cpl_plugin *);
38static int kmo_fits_strip_exec(cpl_plugin *);
39static int kmo_fits_strip_destroy(cpl_plugin *);
40static int kmo_fits_strip(cpl_parameterlist *, cpl_frameset *);
42static char kmo_fits_strip_description[] =
43"With this recipe KMOS fits frames can be stripped in following way:\n"
46"All noise extensions will be removed. Only the data extensions remain.\n"
49"Applies only to calibration products from kmo_flat and kmo_wave_cal.\n"
50"All extensions matching provided angle are kept, the others are removed.\n"
51"Supply a single integer value.\n"
54"All empty extensions will be removed.\n"
57"Supply a comma-separated string with integer values indicating the extensions\n"
58"to keep. The other extensions are removed (any data or noise information is\n"
59"disregarded, the values are interpreted absolutely)\n"
61"The parameters --noise, --angle and --empty can be combined.\n"
62"When --extension is specified, all other parameters are ignored.\n"
63"When no parameter is provided, no output will be generated.\n"
65"-------------------------------------------------------------------------------\n"
69" category Type Explanation Required #Frames\n"
70" -------- ----- ----------- -------- -------\n"
71" <none or any> F2D or frame to strip Y 1 \n"
79" category Type Explanation\n"
80" -------- ----- -----------\n"
81" STRIP F2D or Stripped frame\n"
85"-------------------------------------------------------------------------------\n"
106 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
107 cpl_plugin *plugin = &recipe->interface;
109 cpl_plugin_init(plugin,
112 CPL_PLUGIN_TYPE_RECIPE,
114 "Strip noise, rotator and/or empty extensions from a "
115 "processed KMOS fits frame",
116 kmo_fits_strip_description,
118 "https://support.eso.org/",
120 kmo_fits_strip_create,
122 kmo_fits_strip_destroy);
124 cpl_pluginlist_append(list, plugin);
136static int kmo_fits_strip_create(cpl_plugin *plugin)
138 cpl_recipe *recipe = NULL;
139 cpl_parameter *p = NULL;
142 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
143 recipe = (cpl_recipe *)plugin;
148 recipe->parameters = cpl_parameterlist_new();
152 p = cpl_parameter_new_value(
"kmos.kmo_fits_strip.empty",
154 "TRUE: if empty extensions shall be removed,"
156 "kmos.kmo_fits_strip",
158 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"empty");
159 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
160 cpl_parameterlist_append(recipe->parameters, p);
163 p = cpl_parameter_new_value(
"kmos.kmo_fits_strip.noise",
165 "TRUE: if noise extensions shall be removed,"
167 "kmos.kmo_fits_strip",
169 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"noise");
170 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
171 cpl_parameterlist_append(recipe->parameters, p);
174 p = cpl_parameter_new_value(
"kmos.kmo_fits_strip.angle",
176 "All extensions not matching provided angle "
178 "kmos.kmo_fits_strip",
180 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"angle");
181 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
182 cpl_parameterlist_append(recipe->parameters, p);
185 p = cpl_parameter_new_value(
"kmos.kmo_fits_strip.extension",
187 "Comma-separated string with integers. "
188 "All extensions matching these values are stripped.",
189 "kmos.kmo_fits_strip",
191 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extension");
192 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
193 cpl_parameterlist_append(recipe->parameters, p);
203static int kmo_fits_strip_exec(cpl_plugin *plugin)
208 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
209 recipe = (cpl_recipe *)plugin;
212 return kmo_fits_strip(recipe->parameters, recipe->frames);
220static int kmo_fits_strip_destroy(cpl_plugin *plugin)
225 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
226 recipe = (cpl_recipe *)plugin;
229 cpl_parameterlist_delete(recipe->parameters);
234cpl_error_code kmo_save_header_fits_strip(cpl_propertylist *header,
235 cpl_parameterlist *parlist,
236 cpl_frameset *frameset,
237 const char *filename)
239#define PRO_REC_PARAMi_NAME "ESO PRO REC1 PARAM%d NAME"
240#define PRO_REC_PARAMi_VALUE "ESO PRO REC1 PARAM%d VALUE"
242 cpl_error_code err = CPL_ERROR_NONE;
245 const char *kname = NULL;
246 const cpl_parameter *param = NULL;
247 cpl_frame *product_frame = NULL;
253 KMO_TRY_EXIT_IF_ERROR(
254 cpl_propertylist_update_string(header,
"PIPEFILE",
"strip.fits"));
255 KMO_TRY_EXIT_IF_ERROR(
256 cpl_propertylist_update_string(header, CPL_DFS_PRO_CATG, STRIP));
257 KMO_TRY_EXIT_IF_ERROR(
258 cpl_propertylist_update_string(header,
"ESO PRO REC1 ID", cpl_func));
259 ggg = cpl_sprintf(
"cpl-%d.%d.%d", cpl_version_get_major(), cpl_version_get_minor(), cpl_version_get_micro());
260 KMO_TRY_EXIT_IF_ERROR(
261 cpl_propertylist_update_string(header,
"ESO PRO REC1 DRS ID", ggg));
262 cpl_free(ggg); ggg = NULL;
263 KMO_TRY_EXIT_IF_ERROR(
264 cpl_propertylist_update_string(header,
"ESO PRO REC1 PIPE ID", PACKAGE
"/" PACKAGE_VERSION));
265 KMO_TRY_EXIT_IF_ERROR(
266 cpl_propertylist_update_string(header,
"ESO PRO REC1 CAL1 NAME", kmos_get_base_name(filename)));
267 KMO_TRY_EXIT_IF_ERROR(
268 cpl_propertylist_update_string(header,
"ESO PRO REC1 CAL1 CATG", COMMANDLINE));
269 KMO_TRY_EXIT_IF_ERROR(
270 cpl_propertylist_update_string(header,
"ESO PRO REC1 CAL1 DATAMD5", cpl_propertylist_get_string(header,
"DATAMD5")));
271 KMO_TRY_CHECK_ERROR_STATE();
273 while (param != NULL) {
277 kname = cpl_parameter_get_alias(param, CPL_PARAMETER_MODE_CLI);
278 const char * comment = cpl_parameter_get_help(param);
279 switch (cpl_parameter_get_type(param)) {
281 pval = cpl_strdup(cpl_parameter_get_bool(param) == 1 ?
"true" :
"false");
282 dval = cpl_sprintf(
"Default: %s", cpl_parameter_get_default_bool(param) == 1 ?
"true" :
"false");
285 pval = cpl_sprintf(
"%d", cpl_parameter_get_int(param));
286 dval = cpl_sprintf(
"Default: %d", cpl_parameter_get_default_int(param));
288 case CPL_TYPE_DOUBLE:
289 pval = cpl_sprintf(
"%g", cpl_parameter_get_double(param));
290 dval = cpl_sprintf(
"Default: %g", cpl_parameter_get_default_double(param));
292 case CPL_TYPE_STRING:
293 pval = cpl_strdup(cpl_parameter_get_string(param));
294 dval = cpl_sprintf(
"Default: '%s'", cpl_parameter_get_default_string(param));
299 CPL_ERROR_UNSPECIFIED,
302 snprintf(cval, 1024, PRO_REC_PARAMi_NAME, npar);
303 cpl_propertylist_update_string(header, cval, kname);
304 cpl_propertylist_set_comment(header, cval, comment);
306 snprintf(cval, 1024, PRO_REC_PARAMi_VALUE, npar);
307 cpl_propertylist_update_string(header, cval, pval);
308 cpl_propertylist_set_comment(header, cval, dval);
310 cpl_free((
void*)pval);
311 cpl_free((
void*)dval);
313 param = cpl_parameterlist_get_next_const(parlist);
315 KMO_TRY_CHECK_ERROR_STATE();
317 cpl_msg_info(cpl_func,
"Writing FITS %s product(%s): %s",
"propertylist",
"STRIP",
"strip.fits");
318 KMO_TRY_EXIT_IF_NULL(
319 product_frame = cpl_frame_new());
320 KMO_TRY_EXIT_IF_ERROR(
321 cpl_frame_set_filename(product_frame,
"strip.fits"));
322 KMO_TRY_EXIT_IF_ERROR(
323 cpl_frame_set_tag(product_frame,
"STRIP"));
324 KMO_TRY_EXIT_IF_ERROR(
325 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_ANY));
326 KMO_TRY_EXIT_IF_ERROR(
327 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT));
328 KMO_TRY_EXIT_IF_ERROR(
329 cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL));
330 KMO_TRY_EXIT_IF_ERROR(
331 cpl_frameset_insert(frameset, product_frame));
333 KMO_TRY_EXIT_IF_ERROR(
334 cpl_propertylist_save(header,
"strip.fits", CPL_IO_CREATE));
339 err = cpl_error_get_code();
363static int kmo_fits_strip(cpl_parameterlist *parlist, cpl_frameset *frameset)
367 remove_noise = FALSE,
368 remove_empty = FALSE,
369 remove_angle = FALSE,
384 cpl_propertylist *header = NULL,
386 cpl_imagelist *cube = NULL;
387 cpl_image *img = NULL;
388 cpl_vector *vec = NULL,
391 cpl_frame *frame = NULL;
392 const char *filename = NULL,
393 *extension_txt = NULL;
395 kmclipm_vector *kv = NULL;
399 kmo_init_fits_desc(&desc);
402 KMO_TRY_ASSURE((parlist != NULL) &&
404 CPL_ERROR_NULL_INPUT,
405 "Not all input data is provided!");
407 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1,
408 CPL_ERROR_NULL_INPUT,
409 "A fits-file must be provided!");
411 KMO_TRY_EXIT_IF_NULL(
412 frame = kmo_dfs_get_frame(frameset,
"0"));
414 KMO_TRY_EXIT_IF_NULL(
415 filename = cpl_frame_get_filename(frame));
417 desc = kmo_identify_fits_header(filename);
418 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Provided fits file doesn't seem to be "
421 KMO_TRY_ASSURE((desc.fits_type == f2d_fits) ||
422 (desc.fits_type == f3i_fits) ||
423 (desc.fits_type == f2i_fits) ||
424 (desc.fits_type == f1i_fits),
425 CPL_ERROR_ILLEGAL_INPUT,
426 "Input data hasn't correct data type "
427 "(KMOSTYPE must be F2D, F3I, F2I or F1I)!");
429 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset) == 1,
430 CPL_ERROR_ILLEGAL_INPUT,
431 "Cannot identify RAW and CALIB frames!");
433 cpl_msg_info(
"",
"--- Parameter setup for kmo_fits_strip ----");
434 remove_empty = kmo_dfs_get_parameter_bool(parlist,
435 "kmos.kmo_fits_strip.empty");
436 KMO_TRY_CHECK_ERROR_STATE();
437 KMO_TRY_ASSURE((remove_empty == TRUE) ||
438 (remove_empty == FALSE),
439 CPL_ERROR_ILLEGAL_INPUT,
440 "empty must be TRUE or FALSE!");
441 KMO_TRY_EXIT_IF_ERROR(
442 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fits_strip.empty"));
444 remove_noise = kmo_dfs_get_parameter_bool(parlist,
445 "kmos.kmo_fits_strip.noise");
446 KMO_TRY_CHECK_ERROR_STATE();
447 KMO_TRY_ASSURE((remove_noise == TRUE) ||
448 (remove_noise == FALSE),
449 CPL_ERROR_ILLEGAL_INPUT,
450 "noise must be TRUE or FALSE!");
451 KMO_TRY_EXIT_IF_ERROR(
452 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fits_strip.noise"));
454 angle = kmo_dfs_get_parameter_int(parlist,
455 "kmos.kmo_fits_strip.angle");
456 KMO_TRY_CHECK_ERROR_STATE();
457 KMO_TRY_EXIT_IF_ERROR(
458 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fits_strip.angle"));
464 KMO_TRY_ASSURE(!remove_angle || ((angle >=0) && (angle < 360)),
465 CPL_ERROR_ILLEGAL_INPUT,
466 "angle must be between 0 and 360 degrees!");
468 extension_txt = kmo_dfs_get_parameter_string(parlist,
469 "kmos.kmo_fits_strip.extension");
470 KMO_TRY_CHECK_ERROR_STATE();
471 KMO_TRY_EXIT_IF_ERROR(
472 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_fits_strip.extension"));
474 if (strcmp(extension_txt,
"") != 0) {
477 KMO_TRY_EXIT_IF_NULL(
478 split = kmo_strsplit(extension_txt,
",", NULL));
481 while (split[i] != NULL) {
485 KMO_TRY_EXIT_IF_NULL(
486 extension = cpl_vector_new(i));
487 KMO_TRY_EXIT_IF_NULL(
488 pextension = cpl_vector_get_data(extension));
490 while (split[i] != NULL) {
491 pextension[i] = atof(split[i]);
494 KMO_TRY_CHECK_ERROR_STATE();
496 kmo_strfreev(split); split = NULL;
499 KMO_TRY_EXIT_IF_ERROR(
500 cpl_vector_sort(extension, CPL_SORT_ASCENDING));
502 kv = kmclipm_vector_create(extension);
504 for (i = 0; i < kmclipm_vector_get_size(kv)-1; i++) {
505 if (kmclipm_vector_get(kv, i, NULL) == kmclipm_vector_get(kv, i+1, NULL)) {
506 kmclipm_vector_reject(kv, i+1);
509 extension = kmclipm_vector_create_non_rejected(kv);
510 kmclipm_vector_delete(kv); kv = NULL;
512 KMO_TRY_ASSURE(cpl_vector_get_max(extension) <= desc.nr_ext,
513 CPL_ERROR_ILLEGAL_INPUT,
514 "The input frame has less extensions than specified in 'extensions'-parameter!");
515 KMO_TRY_ASSURE(cpl_vector_get_max(extension) >= 1,
516 CPL_ERROR_ILLEGAL_INPUT,
517 "All values in 'extensions'-parameter must be > 1 !");
520 cpl_msg_info(
"",
"-------------------------------------------");
522 if ((!remove_empty) && (!remove_noise) && (!remove_angle) && (extension == NULL)) {
524 cpl_msg_info(
"",
"No action has been specified (angle-, noise- or empty-parameter),"
525 " therefore no output is generated");
526 }
else if (extension != NULL) {
531 KMO_TRY_EXIT_IF_NULL(
532 header = kmo_dfs_load_primary_header(frameset,
"0"));
533 KMO_TRY_EXIT_IF_ERROR(
534 kmo_save_header_fits_strip(header, parlist, frameset, filename));
535 cpl_propertylist_delete(header); header = NULL;
540 KMO_TRY_EXIT_IF_NULL(
541 pextension = cpl_vector_get_data(extension));
542 for (
int i = 0; i < cpl_vector_get_size(extension); i++) {
543 KMO_TRY_EXIT_IF_NULL(
544 sub_header = cpl_propertylist_load(filename, pextension[i]));
545 if ((desc.fits_type == f2d_fits) ||
546 (desc.fits_type == f2i_fits))
548 img = cpl_image_load(filename,CPL_TYPE_FLOAT, 0, pextension[i]);
549 if (CPL_ERROR_NONE != cpl_error_get_code()) {
552 KMO_TRY_EXIT_IF_ERROR(
553 kmo_dfs_save_image(img, STRIP,
"", sub_header, 0./0.));
554 cpl_image_delete(img); img = NULL;
555 }
else if (desc.fits_type == f3i_fits) {
556 cube = cpl_imagelist_load(filename,CPL_TYPE_FLOAT, pextension[i]);
557 if (CPL_ERROR_NONE != cpl_error_get_code()) {
560 KMO_TRY_EXIT_IF_ERROR(
561 kmo_dfs_save_cube(cube, STRIP,
"", sub_header, 0./0.));
562 cpl_imagelist_delete(cube); cube = NULL;
563 }
else if (desc.fits_type == f1i_fits) {
564 vec = cpl_vector_load(filename, pextension[i]);
565 if (CPL_ERROR_NONE != cpl_error_get_code()) {
568 KMO_TRY_EXIT_IF_NULL(
569 kv = kmclipm_vector_create(vec));
570 KMO_TRY_EXIT_IF_ERROR(
571 kmo_dfs_save_vector(kv, STRIP,
"", sub_header, 0./0.));
572 kmclipm_vector_delete(kv); kv = NULL;
574 cpl_propertylist_delete(sub_header); sub_header = NULL;
579 KMO_TRY_EXIT_IF_NULL(
580 sub_header = kmo_dfs_load_sub_header(frameset,
"0", 1, FALSE));
581 if (cpl_propertylist_has(sub_header, CAL_ROTANGLE)) {
584 cpl_propertylist_delete(sub_header); sub_header = NULL;
590 KMO_TRY_EXIT_IF_NULL(
591 header = kmo_dfs_load_primary_header(frameset,
"0"));
593 if (strcmp(MASTER_FLAT, cpl_propertylist_get_string(header, CPL_DFS_PRO_CATG))==0) {
597 if (remove_angle && isCalFrame) {
599 ocsRotAngle = cpl_propertylist_get_double(header, ROTANGLE);
600 ocsRotAngle = kmclipm_strip_angle(&ocsRotAngle);
601 proRotAngle = kmclipm_cal_propertylist_find_angle(filename, 1, FALSE, angle,
602 &dummy, &secClosestAng);
603 KMO_TRY_CHECK_ERROR_STATE();
604 if (fabs(ocsRotAngle-proRotAngle) > 0.1) {
605 cpl_msg_warning(
"",
"In the product the original ESO OCS ROT NAANGLE keyword "
606 "has been updated with the chosen "
607 "ESO PRO ROT NAANGLE (was: %g, is: %g)!", ocsRotAngle, proRotAngle);
608 KMO_TRY_EXIT_IF_ERROR(
609 cpl_propertylist_update_double(header, ROTANGLE, proRotAngle));
613 KMO_TRY_EXIT_IF_ERROR(
614 kmo_save_header_fits_strip(header, parlist, frameset, filename));
615 cpl_propertylist_delete(header); header = NULL;
618 if (!desc.ex_noise) {
619 nr_devices = desc.nr_ext;
621 nr_devices = desc.nr_ext / 2;
629 remove_noise = !remove_noise;
633 remove_noise = !remove_noise;
638 for (
int i = 0; i < nr_devices; i++) {
641 for (
int n = FALSE; n <= remove_noise; n++) {
644 KMO_TRY_EXIT_IF_NULL(
645 header = kmclipm_cal_propertylist_load(filename, i+1, n, angle, &ret_angle));
647 KMO_TRY_EXIT_IF_NULL(
648 header = kmo_dfs_load_sub_header(frameset,
"0", i + 1, n));
653 if (cpl_propertylist_has(header, CAL_ROTANGLE)) {
654 tmp_angle = cpl_propertylist_get_double(header, CAL_ROTANGLE);
655 KMO_TRY_CHECK_ERROR_STATE();
657 if (fabs(angle - tmp_angle) < 0.01) {
672 index = kmo_identify_index(filename, i+1, n);
674 if ((desc.fits_type == f2d_fits) ||
675 (desc.fits_type == f2i_fits))
678 cal_device_nr = cpl_propertylist_get_int(header, CHIPINDEX);
679 KMO_TRY_CHECK_ERROR_STATE();
680 if (cal_device_nr == actDetNr) {
681 KMO_TRY_EXIT_IF_ERROR(
682 kmo_update_sub_keywords(header,
687 print_cal_angle_msg_once = FALSE;
688 print_xcal_angle_msg_once = FALSE;
689 KMO_TRY_EXIT_IF_NULL(
690 img = kmo_dfs_load_cal_image(frameset,
"0",
693 &ret_angle, -1, 0, 0));
695 if (fabs(angle-ret_angle) > 0.01) {
696 cpl_msg_warning(
"",
"Angle provided: %g, angle found: %g", angle, ret_angle);
698 if (n == remove_noise) {
703 KMO_TRY_EXIT_IF_ERROR(
704 kmo_dfs_save_image(img, STRIP,
"", header, 0./0.));
707 img = cpl_image_load(filename,CPL_TYPE_FLOAT, 0, index);
708 if (CPL_ERROR_NONE != cpl_error_get_code()) {
711 KMO_TRY_EXIT_IF_ERROR(
712 kmo_dfs_save_image(img, STRIP,
"", header, 0./0.));
715 KMO_TRY_EXIT_IF_ERROR(
716 kmo_dfs_save_image(img, STRIP,
"", header, 0./0.));
719 cpl_image_delete(img); img = NULL;
720 }
else if (desc.fits_type == f3i_fits) {
721 cube = cpl_imagelist_load(filename,CPL_TYPE_FLOAT, index);
722 if (CPL_ERROR_NONE != cpl_error_get_code()) {
725 KMO_TRY_EXIT_IF_ERROR(
726 kmo_dfs_save_cube(cube, STRIP,
"", header, 0./0.));
729 KMO_TRY_EXIT_IF_ERROR(
730 kmo_dfs_save_cube(cube, STRIP,
"", header, 0./0.));
732 cpl_imagelist_delete(cube); cube = NULL;
733 }
else if (desc.fits_type == f1i_fits) {
734 vec = cpl_vector_load(filename, index);
735 if (CPL_ERROR_NONE != cpl_error_get_code()) {
738 KMO_TRY_EXIT_IF_ERROR(
739 kmo_dfs_save_vector(NULL, STRIP,
"", header, 0./0.));
742 KMO_TRY_EXIT_IF_NULL(
743 kv = kmclipm_vector_create(vec));
744 KMO_TRY_EXIT_IF_ERROR(
745 kmo_dfs_save_vector(kv, STRIP,
"", header, 0./0.));
747 kmclipm_vector_delete(kv); kv = NULL;
750 cpl_propertylist_delete(header); header = NULL;
762 cpl_propertylist_delete(header); header = NULL;
763 cpl_imagelist_delete(cube); cube = NULL;
764 cpl_image_delete(img); img = NULL;
765 kmclipm_vector_delete(kv); kv = NULL;
766 kmo_free_fits_desc(&desc);
767 cpl_vector_delete(extension); extension = NULL;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.