32#include <kmo_priv_functions.h>
33#include <kmo_cpl_extensions.h>
34#include <kmo_constants.h>
35#include <kmo_priv_rotate.h>
37static int kmo_rotate_create(cpl_plugin *);
38static int kmo_rotate_exec(cpl_plugin *);
39static int kmo_rotate_destroy(cpl_plugin *);
40static int kmo_rotate(cpl_parameterlist *, cpl_frameset *);
42static char kmo_rotate_description[] =
43"This recipe rotates a cube spatially (CCW). If the rotation angle isn't\n"
44"a multiple of 90 degrees, the output cube will be interpolated and get larger\n"
46"By default all IFUs will be rotated.\n"
51"This parameter must be supplied. It contains the amount of rotation to apply.\n"
52"The unit is in degrees. If it contains one value (e.g. “3.5”) all IFUs are\n"
53"rotated by the same amount. If 24 values are supplied each IFU is rotated\n"
54"individually (e.g. “2.3;15.7;…;-3.3”).\n"
57"The interpolation method to apply when rotating an angle not being a multiple\n"
58"of 90. There are two methods available:\n"
59" * BCS: Bicubic spline\n"
60" * NN: Nearest Neighbor (currently disabled)\n"
63"If a single IFU should be rotated, it can be defined using the --ifu parameter\n"
64"(--rotations parameter contains only one value).\n"
66"ADVANCED PARAMETERS\n"
67"-------------------\n"
69"Specify if flux conservation should be applied.\n"
72"By default the output frame grows when rotating an angle not being a multiple\n"
73"of 90. In this case none of the input data is lost. When it is desired to keep\n"
74"the same size as the input frame this parameter can be set to TRUE and the\n"
75"data will be clipped.\n"
77"-------------------------------------------------------------------------------\n"
81" category Type Explanation Required #Frames\n"
82" -------- ----- ----------- -------- -------\n"
83" <none or any> F3I data frame Y 1 \n"
88" category Type Explanation\n"
89" -------- ----- -----------\n"
90" ROTATE F3I Rotated data cube\n"
91"-------------------------------------------------------------------------------\n"
112 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
113 cpl_plugin *plugin = &recipe->interface;
115 cpl_plugin_init(plugin,
118 CPL_PLUGIN_TYPE_RECIPE,
120 "Rotate a cube spatially",
121 kmo_rotate_description,
123 "https://support.eso.org/",
129 cpl_pluginlist_append(list, plugin);
141static int kmo_rotate_create(cpl_plugin *plugin)
147 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
148 recipe = (cpl_recipe *)plugin;
153 recipe->parameters = cpl_parameterlist_new();
157 p = cpl_parameter_new_value(
"kmos.kmo_rotate.imethod",
159 "Method to use for interpolation: "
160 "[\"BCS\" (bicubic spline, default), "
161 "\"NN\" (nearest neighbor), not implemented yet]",
164 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"imethod");
165 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
166 cpl_parameterlist_append(recipe->parameters, p);
169 p = cpl_parameter_new_value(
"kmos.kmo_rotate.extrapolate",
171 "Applies only when rotation angle is different "
172 "from multiples of 90 degrees: "
173 "FALSE: Output IFU will be larger than the input "
175 "TRUE: The size of input and output IFU remains "
176 "the same. Data will be clipped.",
179 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"extrapolate");
180 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
181 cpl_parameterlist_append(recipe->parameters, p);
184 p = cpl_parameter_new_value(
"kmos.kmo_rotate.rotations",
186 "The rotations for all specified IFUs. "
187 "\"rot1;rot2;...\" (degrees)",
190 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rotations");
191 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
192 cpl_parameterlist_append(recipe->parameters, p);
195 p = cpl_parameter_new_value(
"kmos.kmo_rotate.ifu",
197 "The IFU to rotate [1 to 24] or rotate all IFUs "
201 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ifu");
202 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
203 cpl_parameterlist_append(recipe->parameters, p);
206 p = cpl_parameter_new_value(
"kmos.kmo_rotate.flux",
208 "Apply flux conservation: "
210 "FALSE (don't apply)",
213 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flux");
214 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
215 cpl_parameterlist_append(recipe->parameters, p);
225static int kmo_rotate_exec(cpl_plugin *plugin)
230 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
231 recipe = (cpl_recipe *)plugin;
234 return kmo_rotate(recipe->parameters, recipe->frames);
242static int kmo_rotate_destroy(cpl_plugin *plugin)
247 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
248 recipe = (cpl_recipe *)plugin;
251 cpl_parameterlist_delete(recipe->parameters);
269static int kmo_rotate(cpl_parameterlist *parlist, cpl_frameset *frameset)
271 const char *method = NULL,
272 *rotations_txt = NULL;
274 cpl_imagelist *data = NULL,
277 cpl_vector *rotations = NULL,
292 enum extrapolationType extrapol_enum = 0;
294 const double *protations2 = NULL;
296 cpl_propertylist *sub_header_data = NULL,
297 *sub_header_noise = NULL;
299 cpl_frame *frame = NULL;
301 main_fits_desc desc1;
305 kmo_init_fits_desc(&desc1);
308 KMO_TRY_ASSURE((parlist != NULL) &&
310 CPL_ERROR_NULL_INPUT,
311 "Not all input data is provided!");
313 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1,
314 CPL_ERROR_NULL_INPUT,
315 "A cube must be provided!");
317 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset) == 1,
318 CPL_ERROR_ILLEGAL_INPUT,
319 "Cannot identify RAW and CALIB frames!");
321 cpl_msg_info(
"",
"--- Parameter setup for kmo_rotate --------");
323 KMO_TRY_EXIT_IF_NULL(
324 method = kmo_dfs_get_parameter_string(parlist,
325 "kmos.kmo_rotate.imethod"));
326 KMO_TRY_EXIT_IF_ERROR(
327 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_rotate.imethod"));
329 extrapolate = kmo_dfs_get_parameter_bool(parlist,
330 "kmos.kmo_rotate.extrapolate");
331 KMO_TRY_CHECK_ERROR_STATE();
333 if (extrapolate == 1) {
334 extrapol_enum = NONE_NANS;
335 }
else if (extrapolate == 0) {
336 extrapol_enum = RESIZE_NANS;
338 KMO_TRY_ASSURE(1 == 0,
339 CPL_ERROR_ILLEGAL_INPUT,
340 "extrapolate must be 1 or 0!");
343 KMO_TRY_EXIT_IF_ERROR(
344 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_rotate.extrapolate"));
346 rotations_txt = kmo_dfs_get_parameter_string(parlist,
347 "kmos.kmo_rotate.rotations");
348 KMO_TRY_CHECK_ERROR_STATE();
349 KMO_TRY_EXIT_IF_ERROR(
350 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_rotate.rotations"));
352 KMO_TRY_ASSURE(strcmp(rotations_txt,
"") != 0,
353 CPL_ERROR_ILLEGAL_INPUT,
354 "At least one value for --rotations parameter must be "
357 rotations = kmo_identify_values(rotations_txt);
358 KMO_TRY_CHECK_ERROR_STATE();
360 size = cpl_vector_get_size(rotations);
361 KMO_TRY_CHECK_ERROR_STATE();
363 KMO_TRY_ASSURE((size == 1) || (size == KMOS_NR_IFUS),
364 CPL_ERROR_ILLEGAL_INPUT,
365 "rotations parameter must have either one or 24 elements!");
367 ifu = kmo_dfs_get_parameter_int(parlist,
"kmos.kmo_rotate.ifu");
368 KMO_TRY_CHECK_ERROR_STATE();
369 KMO_TRY_EXIT_IF_ERROR(
370 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_rotate.ifu"));
374 KMO_TRY_ASSURE((size == 1) || (size == KMOS_NR_IFUS),
375 CPL_ERROR_ILLEGAL_INPUT,
376 "rotations parameter must have exactly 1 elements"
377 "(rotate all IFUs the same amount) or 24 elements "
378 "(rotate all IFUs individually)!");
381 KMO_TRY_ASSURE(size == 1,
382 CPL_ERROR_ILLEGAL_INPUT,
383 "rotations parameter must have exactly one elements "
384 "to rotate a single IFU!");
388 if (size == KMOS_NR_IFUS) {
389 KMO_TRY_EXIT_IF_NULL(
390 rotations2 = cpl_vector_duplicate(rotations));
392 KMO_TRY_EXIT_IF_NULL(
393 rotations2 = cpl_vector_new(KMOS_NR_IFUS));
394 KMO_TRY_EXIT_IF_NULL(
395 protations2 = cpl_vector_get_data_const(rotations));
396 for (i = 0; i < KMOS_NR_IFUS; i++) {
397 cpl_vector_set(rotations2, i, protations2[0]);
401 KMO_TRY_EXIT_IF_NULL(
402 protations2 = cpl_vector_get_data_const(rotations2));
404 KMO_TRY_ASSURE((strcmp(method,
"NN") == 0) ||
405 (strcmp(method,
"BCS") == 0)
410 CPL_ERROR_ILLEGAL_INPUT,
411 "method must be \"BCS\"!");
413 flux = kmo_dfs_get_parameter_bool(parlist,
414 "kmos.kmo_rotate.flux");
415 KMO_TRY_CHECK_ERROR_STATE();
416 KMO_TRY_EXIT_IF_ERROR(
417 kmo_dfs_print_parameter_help(parlist,
"kmos.kmo_rotate.flux"));
419 cpl_msg_info(
"",
"-------------------------------------------");
421 KMO_TRY_ASSURE((flux == 0) ||
423 CPL_ERROR_ILLEGAL_INPUT,
424 "flux must be either 0 or 1 !");
427 KMO_TRY_EXIT_IF_NULL(
428 frame = kmo_dfs_get_frame(frameset,
"0"));
430 desc1 = kmo_identify_fits_header(
431 cpl_frame_get_filename(frame));
432 KMO_TRY_CHECK_ERROR_STATE_MSG(
"Provided fits file doesn't seem to be "
435 KMO_TRY_ASSURE(desc1.fits_type == f3i_fits,
436 CPL_ERROR_ILLEGAL_INPUT,
437 "First input file hasn't correct data type "
438 "(KMOSTYPE must be F3I)!");
441 KMO_TRY_EXIT_IF_ERROR(
442 kmo_dfs_save_main_header(frameset, ROTATE,
"", frame,
443 NULL, parlist, cpl_func));
446 if (desc1.ex_noise == TRUE) {
447 nr_devices = desc1.nr_ext / 2;
449 nr_devices = desc1.nr_ext;
452 for (i = 1; i <= nr_devices; i++) {
453 if (desc1.ex_noise == FALSE) {
454 devnr = desc1.sub_desc[i - 1].device_nr;
456 devnr = desc1.sub_desc[2 * i - 1].device_nr;
459 if (desc1.ex_badpix == FALSE) {
460 index_data = kmo_identify_index_desc(desc1, devnr, FALSE);
462 index_data = kmo_identify_index_desc(desc1, devnr, 2);
464 KMO_TRY_CHECK_ERROR_STATE();
466 if (desc1.ex_noise) {
467 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE);
469 KMO_TRY_CHECK_ERROR_STATE();
471 KMO_TRY_EXIT_IF_NULL(
472 sub_header_data = kmo_dfs_load_sub_header(frameset,
"0", devnr,
477 if (desc1.sub_desc[index_data-1].valid_data == TRUE) {
481 if (desc1.ex_noise) {
483 KMO_TRY_EXIT_IF_NULL(
484 sub_header_noise = kmo_dfs_load_sub_header(frameset,
"0",
490 KMO_TRY_EXIT_IF_NULL(
491 data = kmo_dfs_load_cube(frameset,
"0", devnr, FALSE));
494 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) {
495 KMO_TRY_EXIT_IF_NULL(
496 noise = kmo_dfs_load_cube(frameset,
"0", devnr, TRUE));
499 if ((ifu == 0) || (ifu == devnr)) {
501 KMO_TRY_EXIT_IF_ERROR(
502 kmo_priv_rotate(&data, &noise,
503 &sub_header_data, &sub_header_noise,
505 flux, devnr, method, extrapol_enum));
512 KMO_TRY_EXIT_IF_ERROR(
513 kmo_dfs_save_cube(data, ROTATE,
"", sub_header_data, 0./0.));
515 if (desc1.ex_noise) {
516 KMO_TRY_EXIT_IF_ERROR(
517 kmo_dfs_save_cube(noise, ROTATE,
"", sub_header_noise,
522 cpl_imagelist_delete(data); data = NULL;
523 cpl_imagelist_delete(noise); noise = NULL;
526 KMO_TRY_EXIT_IF_ERROR(
527 kmo_dfs_save_sub_header(ROTATE,
"", sub_header_data));
529 if (desc1.ex_noise) {
530 KMO_TRY_EXIT_IF_ERROR(
531 kmo_dfs_save_sub_header(ROTATE,
"", sub_header_noise));
536 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
537 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
546 kmo_free_fits_desc(&desc1);
547 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
548 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
549 cpl_imagelist_delete(data); data = NULL;
550 cpl_imagelist_delete(noise); noise = NULL;
551 cpl_vector_delete(rotations); rotations = NULL;
552 cpl_vector_delete(rotations2); rotations2 = NULL;
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.