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