|
KMOS Pipeline Reference Manual
1.1.0
|
00001 /* $Id: kmo_rotate.c,v 1.10 2013/01/09 13:54:20 aagudo Exp $ 00002 * 00003 * This file is part of the KMOS Pipeline 00004 * Copyright (C) 2002,2003 European Southern Observatory 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 */ 00020 00021 /* 00022 * $Author: aagudo $ 00023 * $Date: 2013/01/09 13:54:20 $ 00024 * $Revision: 1.10 $ 00025 * $Name: HEAD $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <string.h> 00033 00034 #include <cpl.h> 00035 00036 #include <kmo_debug.h> 00037 #include <kmo_utils.h> 00038 #include <kmo_dfs.h> 00039 #include <kmo_error.h> 00040 #include <kmo_priv_functions.h> 00041 #include <kmo_cpl_extensions.h> 00042 #include <kmo_constants.h> 00043 #include <kmo_priv_rotate.h> 00044 00045 static int kmo_rotate_create(cpl_plugin *); 00046 static int kmo_rotate_exec(cpl_plugin *); 00047 static int kmo_rotate_destroy(cpl_plugin *); 00048 static int kmo_rotate(cpl_parameterlist *, cpl_frameset *); 00049 00050 static char kmo_rotate_description[] = 00051 "This recipe rotates a cube spatially (CCW). If the rotation angle isn't\n" 00052 "a multiple of 90 degrees, the output cube will be interpolated and get larger\n" 00053 "accordingly.\n" 00054 "By default all IFUs will be rotated.\n" 00055 "\n" 00056 "BASIC PARAMETERS:\n" 00057 "-----------------\n" 00058 "--rotations\n" 00059 "This parameter must be supplied. It contains the amount of rotation to apply.\n" 00060 "The unit is in degrees. If it contains one value (e.g. “3.5”) all IFUs are\n" 00061 "rotated by the same amount. If 24 values are supplied each IFU is rotated\n" 00062 "individually (e.g. “2.3;15.7;…;-3.3”).\n" 00063 "\n" 00064 "--imethod\n" 00065 "The interpolation method to apply when rotating an angle not being a multiple\n" 00066 "of 90. There are two methods available:\n" 00067 " * BCS: Bicubic spline\n" 00068 " * NN: Nearest Neighbor (currently disabled)\n" 00069 "\n" 00070 "--ifu\n" 00071 "If a single IFU should be rotated, it can be defined using the --ifu parameter\n" 00072 "(--rotations parameter contains only one value).\n" 00073 "\n" 00074 "ADVANCED PARAMETERS\n" 00075 "-------------------\n" 00076 "--flux\n" 00077 "Specify if flux conservation should be applied.\n" 00078 "\n" 00079 "--extrapolate\n" 00080 "By default the output frame grows when rotating an angle not being a multiple\n" 00081 "of 90. In this case none of the input data is lost. When it is desired to keep\n" 00082 "the same size as the input frame this parameter can be set to TRUE and the\n" 00083 "data will be clipped.\n" 00084 "\n" 00085 "-------------------------------------------------------------------------------\n" 00086 " Input files:\n" 00087 "\n" 00088 " DO KMOS \n" 00089 " category Type Explanation Required #Frames\n" 00090 " -------- ----- ----------- -------- -------\n" 00091 " <none or any> F3I data frame Y 1 \n" 00092 "\n" 00093 " Output files:\n" 00094 "\n" 00095 " DO KMOS\n" 00096 " category Type Explanation\n" 00097 " -------- ----- -----------\n" 00098 " ROTATE F3I Rotated data cube\n" 00099 "-------------------------------------------------------------------------------\n" 00100 "\n"; 00101 00118 int cpl_plugin_get_info(cpl_pluginlist *list) 00119 { 00120 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00121 cpl_plugin *plugin = &recipe->interface; 00122 00123 cpl_plugin_init(plugin, 00124 CPL_PLUGIN_API, 00125 KMOS_BINARY_VERSION, 00126 CPL_PLUGIN_TYPE_RECIPE, 00127 "kmo_rotate", 00128 "Rotate a cube spatially", 00129 kmo_rotate_description, 00130 "Alex Agudo Berbel", 00131 "agudo@mpe.mpg.de", 00132 kmos_get_license(), 00133 kmo_rotate_create, 00134 kmo_rotate_exec, 00135 kmo_rotate_destroy); 00136 00137 cpl_pluginlist_append(list, plugin); 00138 00139 return 0; 00140 } 00141 00149 static int kmo_rotate_create(cpl_plugin *plugin) 00150 { 00151 cpl_recipe *recipe; 00152 cpl_parameter *p; 00153 00154 /* Check that the plugin is part of a valid recipe */ 00155 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00156 recipe = (cpl_recipe *)plugin; 00157 else 00158 return -1; 00159 00160 /* Create the parameters list in the cpl_recipe object */ 00161 recipe->parameters = cpl_parameterlist_new(); 00162 00163 /* Fill the parameters list */ 00164 /* --imethod */ 00165 p = cpl_parameter_new_value("kmos.kmo_rotate.imethod", 00166 CPL_TYPE_STRING, 00167 "Method to use for interpolation: " 00168 "[\"BCS\" (bicubic spline, default), " 00169 "\"NN\" (nearest neighbor), not implemented yet]", 00170 "kmos.kmo_rotate", 00171 "BCS"); 00172 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00173 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00174 cpl_parameterlist_append(recipe->parameters, p); 00175 00176 /* --extrapolate */ 00177 p = cpl_parameter_new_value("kmos.kmo_rotate.extrapolate", 00178 CPL_TYPE_INT, 00179 "Applies only when rotation angle is different " 00180 "from multiples of 90 degrees: " 00181 "'0': Output IFU will be larger than the input " 00182 "(Default), " 00183 "'1': The size of input and output IFU remains " 00184 "the same. Data will be clipped.", 00185 "kmos.kmo_rotate", 00186 0); 00187 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extrapolate"); 00188 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00189 cpl_parameterlist_append(recipe->parameters, p); 00190 00191 /* --rotations */ 00192 p = cpl_parameter_new_value("kmos.kmo_rotate.rotations", 00193 CPL_TYPE_STRING, 00194 "The rotations for all specified IFUs. " 00195 "\"rot1;rot2;...\" (degrees)", 00196 "kmos.kmo_rotate", 00197 ""); 00198 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rotations"); 00199 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00200 cpl_parameterlist_append(recipe->parameters, p); 00201 00202 /* --ifu */ 00203 p = cpl_parameter_new_value("kmos.kmo_rotate.ifu", 00204 CPL_TYPE_INT, 00205 "The IFU to rotate [1 to 24] or rotate all IFUs " 00206 "[0, default].", 00207 "kmos.kmo_rotate", 00208 0); 00209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifu"); 00210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00211 cpl_parameterlist_append(recipe->parameters, p); 00212 00213 /* --flux */ 00214 p = cpl_parameter_new_value("kmos.kmo_rotate.flux", 00215 CPL_TYPE_BOOL, 00216 "Apply flux conservation: " 00217 "(TRUE (apply) or " 00218 "FALSE (don't apply)", 00219 "kmos.kmo_rotate", 00220 TRUE); 00221 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00222 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00223 cpl_parameterlist_append(recipe->parameters, p); 00224 00225 return 0; 00226 } 00227 00233 static int kmo_rotate_exec(cpl_plugin *plugin) 00234 { 00235 cpl_recipe *recipe; 00236 00237 /* Get the recipe out of the plugin */ 00238 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00239 recipe = (cpl_recipe *)plugin; 00240 else return -1 ; 00241 00242 return kmo_rotate(recipe->parameters, recipe->frames); 00243 } 00244 00250 static int kmo_rotate_destroy(cpl_plugin *plugin) 00251 { 00252 cpl_recipe *recipe; 00253 00254 /* Get the recipe out of the plugin */ 00255 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00256 recipe = (cpl_recipe *)plugin; 00257 else return -1 ; 00258 00259 cpl_parameterlist_delete(recipe->parameters); 00260 return 0 ; 00261 } 00262 00277 static int kmo_rotate(cpl_parameterlist *parlist, cpl_frameset *frameset) 00278 { 00279 const char *method = NULL, 00280 *rotations_txt = NULL; 00281 00282 cpl_imagelist *data = NULL, 00283 *noise = NULL; 00284 00285 cpl_vector *rotations = NULL, 00286 *rotations2 = NULL; 00287 00288 int ret_val = 0, 00289 nr_devices = 0, 00290 i = 0, 00291 valid_ifu = FALSE, 00292 flux = 0, 00293 size = 0, 00294 ifu = 0, 00295 extrapolate = 0, 00296 devnr = 0, 00297 index_data = 0, 00298 index_noise = 0; 00299 00300 enum extrapolationType extrapol_enum = 0; 00301 00302 const double *protations2 = NULL; 00303 00304 cpl_propertylist *sub_header_data = NULL, 00305 *sub_header_noise = NULL; 00306 00307 cpl_frame *frame = NULL; 00308 00309 main_fits_desc desc1; 00310 00311 KMO_TRY 00312 { 00313 kmo_init_fits_desc(&desc1); 00314 00315 /* --- check input --- */ 00316 KMO_TRY_ASSURE((parlist != NULL) && 00317 (frameset != NULL), 00318 CPL_ERROR_NULL_INPUT, 00319 "Not all input data is provided!"); 00320 00321 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1, 00322 CPL_ERROR_NULL_INPUT, 00323 "A cube must be provided!"); 00324 00325 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_rotate") == 1, 00326 CPL_ERROR_ILLEGAL_INPUT, 00327 "Cannot identify RAW and CALIB frames!"); 00328 00329 cpl_msg_info("", "--- Parameter setup for kmo_rotate --------"); 00330 00331 KMO_TRY_EXIT_IF_NULL( 00332 method = kmo_dfs_get_parameter_string(parlist, 00333 "kmos.kmo_rotate.imethod")); 00334 KMO_TRY_EXIT_IF_ERROR( 00335 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_rotate.imethod")); 00336 00337 extrapolate = kmo_dfs_get_parameter_int(parlist, 00338 "kmos.kmo_rotate.extrapolate"); 00339 KMO_TRY_CHECK_ERROR_STATE(); 00340 00341 if (extrapolate == 1) { 00342 extrapol_enum = NONE_NANS; 00343 } else if (extrapolate == 0) { 00344 extrapol_enum = RESIZE_NANS; 00345 } else { 00346 KMO_TRY_ASSURE(1 == 0, 00347 CPL_ERROR_ILLEGAL_INPUT, 00348 "extrapolate must be 1 or 0!"); 00349 } 00350 00351 KMO_TRY_EXIT_IF_ERROR( 00352 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_rotate.extrapolate")); 00353 00354 rotations_txt = kmo_dfs_get_parameter_string(parlist, 00355 "kmos.kmo_rotate.rotations"); 00356 KMO_TRY_CHECK_ERROR_STATE(); 00357 KMO_TRY_EXIT_IF_ERROR( 00358 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_rotate.rotations")); 00359 00360 KMO_TRY_ASSURE(strcmp(rotations_txt, "") != 0, 00361 CPL_ERROR_ILLEGAL_INPUT, 00362 "At least one value for --rotations parameter must be " 00363 "provided!"); 00364 00365 rotations = kmo_identify_values(rotations_txt); 00366 KMO_TRY_CHECK_ERROR_STATE(); 00367 00368 size = cpl_vector_get_size(rotations); 00369 KMO_TRY_CHECK_ERROR_STATE(); 00370 00371 KMO_TRY_ASSURE((size == 1) || (size == KMOS_NR_IFUS), 00372 CPL_ERROR_ILLEGAL_INPUT, 00373 "rotations parameter must have either one or 24 elements!"); 00374 00375 ifu = kmo_dfs_get_parameter_int(parlist, "kmos.kmo_rotate.ifu"); 00376 KMO_TRY_CHECK_ERROR_STATE(); 00377 KMO_TRY_EXIT_IF_ERROR( 00378 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_rotate.ifu")); 00379 00380 if (ifu == 0) { 00381 // rotate all IFUs the same or different amounts 00382 KMO_TRY_ASSURE((size == 1) || (size == KMOS_NR_IFUS), 00383 CPL_ERROR_ILLEGAL_INPUT, 00384 "rotations parameter must have exactly 1 elements" 00385 "(rotate all IFUs the same amount) or 24 elements " 00386 "(rotate all IFUs individually)!"); 00387 } else { 00388 // rotate only one specific IFU 00389 KMO_TRY_ASSURE(size == 1, 00390 CPL_ERROR_ILLEGAL_INPUT, 00391 "rotations parameter must have exactly one elements " 00392 "to rotate a single IFU!"); 00393 } 00394 00395 // setup a vector of length 24 regardless of how many IFUs to rotate 00396 if (size == KMOS_NR_IFUS) { 00397 KMO_TRY_EXIT_IF_NULL( 00398 rotations2 = cpl_vector_duplicate(rotations)); 00399 } else { 00400 KMO_TRY_EXIT_IF_NULL( 00401 rotations2 = cpl_vector_new(KMOS_NR_IFUS)); 00402 KMO_TRY_EXIT_IF_NULL( 00403 protations2 = cpl_vector_get_data_const(rotations)); 00404 for (i = 0; i < KMOS_NR_IFUS; i++) { 00405 cpl_vector_set(rotations2, i, protations2[0]); 00406 } 00407 } 00408 00409 KMO_TRY_EXIT_IF_NULL( 00410 protations2 = cpl_vector_get_data_const(rotations2)); 00411 00412 KMO_TRY_ASSURE((strcmp(method, "NN") == 0) || 00413 (strcmp(method, "BCS") == 0) 00414 /*(strcmp(method, "kriging") == 0) || 00415 (strcmp(method, "cubic") == 0) || 00416 (strcmp(method, "shepard") == 0) || 00417 (strcmp(method, "drizzle") == 0)*/, 00418 CPL_ERROR_ILLEGAL_INPUT, 00419 "method must be \"BCS\"!"); 00420 00421 flux = kmo_dfs_get_parameter_bool(parlist, 00422 "kmos.kmo_rotate.flux"); 00423 KMO_TRY_CHECK_ERROR_STATE(); 00424 KMO_TRY_EXIT_IF_ERROR( 00425 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_rotate.flux")); 00426 00427 cpl_msg_info("", "-------------------------------------------"); 00428 00429 KMO_TRY_ASSURE((flux == 0) || 00430 (flux == 1), 00431 CPL_ERROR_ILLEGAL_INPUT, 00432 "flux must be either 0 or 1 !"); 00433 00434 // load descriptor of first operand 00435 KMO_TRY_EXIT_IF_NULL( 00436 frame = kmo_dfs_get_frame(frameset, "0")); 00437 00438 desc1 = kmo_identify_fits_header( 00439 cpl_frame_get_filename(frame)); 00440 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be " 00441 "in KMOS-format!"); 00442 00443 KMO_TRY_ASSURE(desc1.fits_type == f3i_fits, 00444 CPL_ERROR_ILLEGAL_INPUT, 00445 "First input file hasn't correct data type " 00446 "(KMOSTYPE must be F3I)!"); 00447 00448 // --- load, update & save primary header --- 00449 KMO_TRY_EXIT_IF_ERROR( 00450 kmo_dfs_save_main_header(frameset, ROTATE, "", frame, 00451 NULL, parlist, cpl_func)); 00452 00453 // --- load data --- 00454 if (desc1.ex_noise == TRUE) { 00455 nr_devices = desc1.nr_ext / 2; 00456 } else { 00457 nr_devices = desc1.nr_ext; 00458 } 00459 00460 for (i = 1; i <= nr_devices; i++) { 00461 if (desc1.ex_noise == FALSE) { 00462 devnr = desc1.sub_desc[i - 1].device_nr; 00463 } else { 00464 devnr = desc1.sub_desc[2 * i - 1].device_nr; 00465 } 00466 00467 if (desc1.ex_badpix == FALSE) { 00468 index_data = kmo_identify_index_desc(desc1, devnr, FALSE); 00469 } else { 00470 index_data = kmo_identify_index_desc(desc1, devnr, 2); 00471 } 00472 KMO_TRY_CHECK_ERROR_STATE(); 00473 00474 if (desc1.ex_noise) { 00475 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE); 00476 } 00477 KMO_TRY_CHECK_ERROR_STATE(); 00478 00479 KMO_TRY_EXIT_IF_NULL( 00480 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr, 00481 FALSE)); 00482 00483 // check if IFU is valid 00484 valid_ifu = FALSE; 00485 if (desc1.sub_desc[index_data-1].valid_data == TRUE) { 00486 valid_ifu = TRUE; 00487 } 00488 00489 if (desc1.ex_noise) { 00490 // load noise anyway since we have to save it in the output 00491 KMO_TRY_EXIT_IF_NULL( 00492 sub_header_noise = kmo_dfs_load_sub_header(frameset, "0", 00493 devnr, TRUE)); 00494 } 00495 00496 if (valid_ifu) { 00497 // load data 00498 KMO_TRY_EXIT_IF_NULL( 00499 data = kmo_dfs_load_cube(frameset, "0", devnr, FALSE)); 00500 00501 // load noise, if existing 00502 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) { 00503 KMO_TRY_EXIT_IF_NULL( 00504 noise = kmo_dfs_load_cube(frameset, "0", devnr, TRUE)); 00505 } 00506 00507 if ((ifu == 0) || (ifu == devnr)) { 00508 // process here 00509 KMO_TRY_EXIT_IF_ERROR( 00510 kmo_priv_rotate(&data, &noise, 00511 &sub_header_data, &sub_header_noise, 00512 protations2[i-1], 00513 flux, devnr, method, extrapol_enum)); 00514 } else { 00515 // leave data and noise as they are and 00516 // save them again unrotated 00517 } 00518 00519 // save data and noise (if existing) 00520 KMO_TRY_EXIT_IF_ERROR( 00521 kmo_dfs_save_cube(data, ROTATE, "", sub_header_data, 0./0.)); 00522 00523 if (desc1.ex_noise) { 00524 KMO_TRY_EXIT_IF_ERROR( 00525 kmo_dfs_save_cube(noise, ROTATE, "", sub_header_noise, 00526 0./0.)); 00527 } 00528 00529 // free memory 00530 cpl_imagelist_delete(data); data = NULL; 00531 cpl_imagelist_delete(noise); noise = NULL; 00532 } else { 00533 // invalid IFU, just save sub_headers 00534 KMO_TRY_EXIT_IF_ERROR( 00535 kmo_dfs_save_sub_header(ROTATE, "", sub_header_data)); 00536 00537 if (desc1.ex_noise) { 00538 KMO_TRY_EXIT_IF_ERROR( 00539 kmo_dfs_save_sub_header(ROTATE, "", sub_header_noise)); 00540 } 00541 } 00542 00543 // free memory 00544 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00545 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL; 00546 } 00547 } 00548 KMO_CATCH 00549 { 00550 KMO_CATCH_MSG(); 00551 ret_val = -1; 00552 } 00553 00554 kmo_free_fits_desc(&desc1); 00555 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00556 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL; 00557 cpl_imagelist_delete(data); data = NULL; 00558 cpl_imagelist_delete(noise); noise = NULL; 00559 cpl_vector_delete(rotations); rotations = NULL; 00560 cpl_vector_delete(rotations2); rotations2 = NULL; 00561 00562 return ret_val; 00563 } 00564
1.7.6.1