|
KMOS Pipeline Reference Manual
1.0.8
|
00001 /* $Id: kmo_shift.c,v 1.12 2013/01/25 03:04:51 erw 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: erw $ 00023 * $Date: 2013/01/25 03:04:51 $ 00024 * $Revision: 1.12 $ 00025 * $Name: kmosp_v1_0_8__20130220 $ 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_shift.h> 00044 00045 static int kmo_shift_create(cpl_plugin *); 00046 static int kmo_shift_exec(cpl_plugin *); 00047 static int kmo_shift_destroy(cpl_plugin *); 00048 static int kmo_shift(cpl_parameterlist *, cpl_frameset *); 00049 00050 static char kmo_shift_description[] = 00051 "This recipe shifts a cube spatially. A positive x-shift shifts the data to the\n" 00052 "left, a positive y-shift shifts upwards, where a shift of one pixel equals\n" 00053 "0.2arcsec. The output will still have the same dimensions, but the borders \n" 00054 "will be filled with NaNs accordingly.\n" 00055 "To adjust only the WCS without moving the data the --wcs-only parameter has to\n" 00056 "be set to TRUE. The WCS is updated in the same way as if the data would have\n" 00057 "moved as well. This means that the point at (x,y) has the same coordinates as\n" 00058 "the point (x+1,y+1) after updating the WCS (the WCS moved in the opposite\n" 00059 "direction).\n" 00060 "\n" 00061 "BASIC PARAMETERS:\n" 00062 "-----------------\n" 00063 "--shifts\n" 00064 "This parameter must be supplied. It contains the amount of shift to apply. The\n" 00065 "unit is in arcsec. If the --shifts parameter contains only two values (x,y),\n" 00066 "all IFUs will be shifted by the same amount. If it contains 48 values\n" 00067 "(x1,y1;x2,y2;...;x24,y24), the IFUs are shifted individually.\n" 00068 "\n" 00069 "--imethod\n" 00070 "The interpolation method to apply when the shift value isn’t a multiple of the\n" 00071 "pixel scale. There are two methods available:\n" 00072 " * BCS: Bicubic spline\n" 00073 " * NN: Nearest Neighbor\n" 00074 "\n" 00075 "--ifu\n" 00076 "If a single IFU should be shifted, it can be defined using the --ifu parameter\n" 00077 "(--shifts parameter contains only two values).\n" 00078 "\n" 00079 "ADVANCED PARAMETERS\n" 00080 "-------------------\n" 00081 "--flux\n" 00082 "Specify if flux conservation should be applied.\n" 00083 "\n" 00084 "--extrapolate\n" 00085 "By default no extrapolation is applied. This means that the output frame will\n" 00086 "shrink at most one pixel, because the data is shifted out of the frame. When\n" 00087 "turning extrapolation on, the size of the output frame stays the same as for\n" 00088 "the input frame.\n" 00089 "\n" 00090 "--wcs-only\n" 00091 "By default data and WCS are shifted in sync. If this parameter is set to TRUE\n" 00092 "only the WCS is updated (i.e. if someone thinks that the IFU isn't pointing\n" 00093 "exactly to the correct coordinates.)\n" 00094 "\n" 00095 "-------------------------------------------------------------------------------\n" 00096 " Input files:\n" 00097 "\n" 00098 " DO KMOS \n" 00099 " category Type Explanation Required #Frames\n" 00100 " -------- ----- ----------- -------- -------\n" 00101 " <none or any> F3I data frame Y 1 \n" 00102 "\n" 00103 " Output files:\n" 00104 "\n" 00105 " DO KMOS\n" 00106 " category Type Explanation\n" 00107 " -------- ----- -----------\n" 00108 " SHIFT F3I Shifted data cube\n" 00109 "-------------------------------------------------------------------------------\n" 00110 "\n"; 00111 00128 int cpl_plugin_get_info(cpl_pluginlist *list) 00129 { 00130 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00131 cpl_plugin *plugin = &recipe->interface; 00132 00133 cpl_plugin_init(plugin, 00134 CPL_PLUGIN_API, 00135 KMOS_BINARY_VERSION, 00136 CPL_PLUGIN_TYPE_RECIPE, 00137 "kmo_shift", 00138 "Shift a cube spatially", 00139 kmo_shift_description, 00140 "Alex Agudo Berbel", 00141 "agudo@mpe.mpg.de", 00142 kmos_get_license(), 00143 kmo_shift_create, 00144 kmo_shift_exec, 00145 kmo_shift_destroy); 00146 00147 cpl_pluginlist_append(list, plugin); 00148 00149 return 0; 00150 } 00151 00159 static int kmo_shift_create(cpl_plugin *plugin) 00160 { 00161 cpl_recipe *recipe; 00162 cpl_parameter *p; 00163 00164 /* Check that the plugin is part of a valid recipe */ 00165 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00166 recipe = (cpl_recipe *)plugin; 00167 else 00168 return -1; 00169 00170 /* Create the parameters list in the cpl_recipe object */ 00171 recipe->parameters = cpl_parameterlist_new(); 00172 00173 /* Fill the parameters list */ 00174 /* --imethod */ 00175 p = cpl_parameter_new_value("kmos.kmo_shift.imethod", 00176 CPL_TYPE_STRING, 00177 "Method to use for interpolation.\n" 00178 "[\"BCS\" (bicubic spline, default), " 00179 "\"NN\" (nearest neighbor)]", 00180 "kmos.kmo_shift", 00181 "BCS"); 00182 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod"); 00183 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00184 cpl_parameterlist_append(recipe->parameters, p); 00185 00186 /* --extrapolate */ 00187 p = cpl_parameter_new_value("kmos.kmo_shift.extrapolate", 00188 CPL_TYPE_BOOL, 00189 "Applies only to 'method=BCS' when doing sub-" 00190 "pixel shifts: " 00191 "FALSE: shifted IFU will be filled with NaN's " 00192 "at the borders," 00193 "TRUE: shifted IFU will be extrapolated at " 00194 "the borders", 00195 "kmos.kmo_shift", 00196 0); 00197 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "extrapolate"); 00198 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00199 cpl_parameterlist_append(recipe->parameters, p); 00200 00201 /* --shifts */ 00202 p = cpl_parameter_new_value("kmos.kmo_shift.shifts", 00203 CPL_TYPE_STRING, 00204 "The shifts for each spatial dimension for all " 00205 "specified IFUs." 00206 "\"x1,y1;x2,y2;...\" (arcsec)", 00207 "kmos.kmo_shift", 00208 ""); 00209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "shifts"); 00210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00211 cpl_parameterlist_append(recipe->parameters, p); 00212 00213 /* --ifu */ 00214 p = cpl_parameter_new_value("kmos.kmo_shift.ifu", 00215 CPL_TYPE_INT, 00216 "The IFU to shift [1 to 24] or shift all IFUs " 00217 "Default value of 0 applies shift to all IFUs.", 00218 "kmos.kmo_shift", 00219 0); 00220 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifu"); 00221 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00222 cpl_parameterlist_append(recipe->parameters, p); 00223 00224 /* --flux */ 00225 p = cpl_parameter_new_value("kmos.kmo_shift.flux", 00226 CPL_TYPE_BOOL, 00227 "Apply flux conservation: " 00228 "(TRUE (apply) or " 00229 "FALSE (don't apply)", 00230 "kmos.kmo_shift", 00231 FALSE); 00232 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux"); 00233 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00234 cpl_parameterlist_append(recipe->parameters, p); 00235 00236 /* --wcs-only */ 00237 p = cpl_parameter_new_value("kmos.kmo_shift.wcs-only", 00238 CPL_TYPE_BOOL, 00239 "FALSE: if data and wcs should be updated." 00240 "TRUE: if only wcs should be corrected", 00241 "kmos.kmo_shift", 00242 0); 00243 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcs-only"); 00244 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00245 cpl_parameterlist_append(recipe->parameters, p); 00246 00247 return 0; 00248 } 00249 00255 static int kmo_shift_exec(cpl_plugin *plugin) 00256 { 00257 cpl_recipe *recipe; 00258 00259 /* Get the recipe out of the plugin */ 00260 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00261 recipe = (cpl_recipe *)plugin; 00262 else return -1 ; 00263 00264 return kmo_shift(recipe->parameters, recipe->frames); 00265 } 00266 00272 static int kmo_shift_destroy(cpl_plugin *plugin) 00273 { 00274 cpl_recipe *recipe; 00275 00276 /* Get the recipe out of the plugin */ 00277 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00278 recipe = (cpl_recipe *)plugin; 00279 else return -1 ; 00280 00281 cpl_parameterlist_delete(recipe->parameters); 00282 return 0 ; 00283 } 00284 00299 static int kmo_shift(cpl_parameterlist *parlist, cpl_frameset *frameset) 00300 { 00301 const char *method = NULL, 00302 *shifts_txt = NULL; 00303 00304 cpl_imagelist *data = NULL, 00305 *noise = NULL; 00306 00307 cpl_vector *shifts = NULL, 00308 *shifts2 = NULL; 00309 00310 int ret_val = 0, 00311 nr_devices = 0, 00312 i = 0, 00313 valid_ifu = FALSE, 00314 flux = FALSE, 00315 size = 0, 00316 ifu = 0, 00317 extrapolate = 0, 00318 wcs_only = FALSE, 00319 devnr = 0, 00320 index_data = 0, 00321 index_noise = 0; 00322 00323 enum extrapolationType extrapol_enum = 0; 00324 00325 const double *pshifts2 = NULL; 00326 00327 cpl_propertylist *sub_header_data = NULL, 00328 *sub_header_noise = NULL; 00329 00330 cpl_frame *frame = NULL; 00331 00332 main_fits_desc desc1; 00333 00334 KMO_TRY 00335 { 00336 kmo_init_fits_desc(&desc1); 00337 00338 /* --- check input --- */ 00339 KMO_TRY_ASSURE((parlist != NULL) && 00340 (frameset != NULL), 00341 CPL_ERROR_NULL_INPUT, 00342 "Not all input data is provided!"); 00343 00344 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1, 00345 CPL_ERROR_NULL_INPUT, 00346 "A cube must be provided!"); 00347 00348 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_shift") == 1, 00349 CPL_ERROR_ILLEGAL_INPUT, 00350 "Cannot identify RAW and CALIB frames!"); 00351 00352 cpl_msg_info("", "--- Parameter setup for kmo_shift ---------"); 00353 00354 KMO_TRY_EXIT_IF_NULL( 00355 method = kmo_dfs_get_parameter_string(parlist, 00356 "kmos.kmo_shift.imethod")); 00357 KMO_TRY_EXIT_IF_ERROR( 00358 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.imethod")); 00359 00360 extrapolate = kmo_dfs_get_parameter_bool(parlist, 00361 "kmos.kmo_shift.extrapolate"); 00362 KMO_TRY_CHECK_ERROR_STATE(); 00363 00364 if (strcmp(method, "NN") == 0) { 00365 extrapol_enum = NONE_NANS; 00366 } else if (strcmp(method, "BCS") == 0) { 00367 if (extrapolate == FALSE) { 00368 extrapol_enum = NONE_NANS; 00369 } else if (extrapolate == TRUE) { 00370 extrapol_enum = BCS_NATURAL; 00371 } else { 00372 KMO_TRY_ASSURE(1 == 0, 00373 CPL_ERROR_ILLEGAL_INPUT, 00374 "extrapolate must either FALSE or TRUE!"); 00375 } 00376 } else { 00377 KMO_TRY_ASSURE(1 == 0, 00378 CPL_ERROR_ILLEGAL_INPUT, 00379 "method must be either \"BCS\" or \"NN\" !"); 00380 } 00381 00382 KMO_TRY_EXIT_IF_ERROR( 00383 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.extrapolate")); 00384 00385 shifts_txt = kmo_dfs_get_parameter_string(parlist, 00386 "kmos.kmo_shift.shifts"); 00387 KMO_TRY_CHECK_ERROR_STATE(); 00388 KMO_TRY_EXIT_IF_ERROR( 00389 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.shifts")); 00390 00391 KMO_TRY_ASSURE(strcmp(shifts_txt, "") != 0, 00392 CPL_ERROR_ILLEGAL_INPUT, 00393 "At least two values for --shifts parameter must be " 00394 "provided!"); 00395 00396 shifts = kmo_identify_ranges(shifts_txt); 00397 KMO_TRY_CHECK_ERROR_STATE(); 00398 00399 size = cpl_vector_get_size(shifts); 00400 KMO_TRY_CHECK_ERROR_STATE(); 00401 00402 KMO_TRY_ASSURE((size % 2) == 0, 00403 CPL_ERROR_ILLEGAL_INPUT, 00404 "shifts parameter must have an even number of elements!"); 00405 00406 ifu = kmo_dfs_get_parameter_int(parlist, "kmos.kmo_shift.ifu"); 00407 KMO_TRY_CHECK_ERROR_STATE(); 00408 KMO_TRY_EXIT_IF_ERROR( 00409 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.ifu")); 00410 00411 if (ifu == 0) { 00412 // shift all IFUs the same or different amounts 00413 KMO_TRY_ASSURE((size == 2) || (size == 2*KMOS_NR_IFUS), 00414 CPL_ERROR_ILLEGAL_INPUT, 00415 "shifts parameter must have exactly 2 elements" 00416 "(shift all IFUs the same amount) or 48 elements " 00417 "(shift all IFUs individually)!"); 00418 } else { 00419 // shift only one specific IFU 00420 KMO_TRY_ASSURE(size == 2, 00421 CPL_ERROR_ILLEGAL_INPUT, 00422 "shifts parameter must have exactly 2 elements to " 00423 "shift a single IFU!"); 00424 } 00425 00426 // setup a vector of length 48 regardless of how many IFUs to shift 00427 if (size == 2*KMOS_NR_IFUS) { 00428 KMO_TRY_EXIT_IF_NULL( 00429 shifts2 = cpl_vector_duplicate(shifts)); 00430 } else { 00431 KMO_TRY_EXIT_IF_NULL( 00432 shifts2 = cpl_vector_new(2*KMOS_NR_IFUS)); 00433 KMO_TRY_EXIT_IF_NULL( 00434 pshifts2 = cpl_vector_get_data_const(shifts)); 00435 for (i = 0; i < KMOS_NR_IFUS; i++) { 00436 cpl_vector_set(shifts2, 2*i, pshifts2[0]); 00437 cpl_vector_set(shifts2, 2*i+1, pshifts2[1]); 00438 } 00439 } 00440 00441 KMO_TRY_EXIT_IF_NULL( 00442 pshifts2 = cpl_vector_get_data_const(shifts2)); 00443 00444 flux = kmo_dfs_get_parameter_bool(parlist, 00445 "kmos.kmo_shift.flux"); 00446 KMO_TRY_CHECK_ERROR_STATE(); 00447 KMO_TRY_EXIT_IF_ERROR( 00448 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.flux")); 00449 00450 KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE), 00451 CPL_ERROR_ILLEGAL_INPUT, 00452 "flux must be TRUE or FALSE!"); 00453 00454 wcs_only = kmo_dfs_get_parameter_bool(parlist, "kmos.kmo_shift.wcs-only"); 00455 KMO_TRY_CHECK_ERROR_STATE(); 00456 KMO_TRY_EXIT_IF_ERROR( 00457 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.wcs-only")); 00458 00459 KMO_TRY_ASSURE((wcs_only == TRUE) || (wcs_only == FALSE), 00460 CPL_ERROR_NULL_INPUT, 00461 "wcs_only must be TRUE or FALSE!"); 00462 00463 cpl_msg_info("", "-------------------------------------------"); 00464 00465 KMO_TRY_ASSURE((flux == 0) || 00466 (flux == 1), 00467 CPL_ERROR_ILLEGAL_INPUT, 00468 "flux must be either 0 or 1 !"); 00469 00470 // load descriptor of first operand 00471 KMO_TRY_EXIT_IF_NULL( 00472 frame = kmo_dfs_get_frame(frameset, "0")); 00473 00474 desc1 = kmo_identify_fits_header( 00475 cpl_frame_get_filename(frame)); 00476 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be " 00477 "in KMOS-format!"); 00478 00479 KMO_TRY_ASSURE(desc1.fits_type == f3i_fits, 00480 CPL_ERROR_ILLEGAL_INPUT, 00481 "First input file hasn't correct data type " 00482 "(KMOSTYPE must be F3I)!"); 00483 00484 // --- load, update & save primary header --- 00485 KMO_TRY_EXIT_IF_ERROR( 00486 kmo_dfs_save_main_header(frameset, SHIFT, "", frame, NULL, 00487 parlist, cpl_func)); 00488 00489 // --- load data --- 00490 if (desc1.ex_noise == TRUE) { 00491 nr_devices = desc1.nr_ext / 2; 00492 } else { 00493 nr_devices = desc1.nr_ext; 00494 } 00495 00496 for (i = 1; i <= nr_devices; i++) { 00497 if (desc1.ex_noise == FALSE) { 00498 devnr = desc1.sub_desc[i - 1].device_nr; 00499 } else { 00500 devnr = desc1.sub_desc[2 * i - 1].device_nr; 00501 } 00502 00503 if (desc1.ex_badpix == FALSE) { 00504 index_data = kmo_identify_index_desc(desc1, devnr, FALSE); 00505 } else { 00506 index_data = kmo_identify_index_desc(desc1, devnr, 2); 00507 } 00508 KMO_TRY_CHECK_ERROR_STATE(); 00509 00510 if (desc1.ex_noise) { 00511 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE); 00512 } 00513 KMO_TRY_CHECK_ERROR_STATE(); 00514 00515 KMO_TRY_EXIT_IF_NULL( 00516 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr, 00517 FALSE)); 00518 00519 // check if IFU is valid 00520 valid_ifu = FALSE; 00521 if (desc1.sub_desc[index_data-1].valid_data == TRUE) { 00522 valid_ifu = TRUE; 00523 } 00524 00525 if (desc1.ex_noise) { 00526 // load noise anyway since we have to save it in the output 00527 KMO_TRY_EXIT_IF_NULL( 00528 sub_header_noise = kmo_dfs_load_sub_header(frameset, "0", 00529 devnr, TRUE)); 00530 } 00531 00532 if (valid_ifu) { 00533 // load data 00534 KMO_TRY_EXIT_IF_NULL( 00535 data = kmo_dfs_load_cube(frameset, "0", devnr, FALSE)); 00536 00537 // load noise, if existing 00538 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) { 00539 KMO_TRY_EXIT_IF_NULL( 00540 noise = kmo_dfs_load_cube(frameset, "0", devnr, TRUE)); 00541 } 00542 00543 if ((ifu == 0) || (ifu == devnr)) { 00544 // process here 00545 KMO_TRY_EXIT_IF_ERROR( 00546 kmo_priv_shift(&data, &noise, 00547 &sub_header_data, &sub_header_noise, 00548 pshifts2[2*i-2] / KMOS_PIX_RESOLUTION, 00549 pshifts2[2*i-1] / KMOS_PIX_RESOLUTION, 00550 flux, devnr, method, extrapol_enum, 00551 wcs_only)); 00552 } else { 00553 // leave data and noise as they are and 00554 // save them again unshifted 00555 } 00556 00557 // save data and noise (if existing) 00558 KMO_TRY_EXIT_IF_ERROR( 00559 kmo_dfs_save_cube(data, SHIFT, "", sub_header_data, 0./0.)); 00560 00561 if (desc1.ex_noise) { 00562 KMO_TRY_EXIT_IF_ERROR( 00563 kmo_dfs_save_cube(noise, SHIFT, "", sub_header_noise, 0./0.)); 00564 } 00565 00566 // free memory 00567 cpl_imagelist_delete(data); data = NULL; 00568 cpl_imagelist_delete(noise); noise = NULL; 00569 } else { 00570 // invalid IFU, just save sub_headers 00571 KMO_TRY_EXIT_IF_ERROR( 00572 kmo_dfs_save_sub_header(SHIFT, "", sub_header_data)); 00573 00574 if (desc1.ex_noise == TRUE) { 00575 KMO_TRY_EXIT_IF_ERROR( 00576 kmo_dfs_save_sub_header(SHIFT, "", sub_header_noise)); 00577 } 00578 } 00579 00580 // free memory 00581 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00582 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL; 00583 } 00584 } 00585 KMO_CATCH 00586 { 00587 KMO_CATCH_MSG(); 00588 ret_val = -1; 00589 } 00590 00591 kmo_free_fits_desc(&desc1); 00592 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00593 cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL; 00594 cpl_imagelist_delete(data); data = NULL; 00595 cpl_imagelist_delete(noise); noise = NULL; 00596 cpl_vector_delete(shifts); shifts = NULL; 00597 cpl_vector_delete(shifts2); shifts2 = NULL; 00598 00599 return ret_val; 00600 } 00601
1.7.6.1