KMOS Pipeline Reference Manual
1.3.11
|
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 /*----------------------------------------------------------------------------- 00025 * Includes 00026 *----------------------------------------------------------------------------*/ 00027 00028 #include <string.h> 00029 00030 #include <cpl.h> 00031 00032 #include "kmo_utils.h" 00033 #include "kmo_dfs.h" 00034 #include "kmo_priv_sky_mask.h" 00035 #include "kmo_priv_functions.h" 00036 #include "kmo_error.h" 00037 #include "kmo_constants.h" 00038 #include "kmo_debug.h" 00039 00040 /*----------------------------------------------------------------------------- 00041 * Functions prototypes 00042 *----------------------------------------------------------------------------*/ 00043 00044 static int kmo_sky_mask_create(cpl_plugin *); 00045 static int kmo_sky_mask_exec(cpl_plugin *); 00046 static int kmo_sky_mask_destroy(cpl_plugin *); 00047 static int kmo_sky_mask(cpl_parameterlist *, cpl_frameset *); 00048 00049 /*----------------------------------------------------------------------------- 00050 * Static variables 00051 *----------------------------------------------------------------------------*/ 00052 00053 static char kmo_sky_mask_description[] = 00054 "This recipes calculates masks of the skies surrounding the objects in the diff-\n" 00055 "erent IFUs of a reconstructed F3I frame. In the resulting mask pixels belonging\n" 00056 "to objects have value 1 and sky pixels have value 0.\n" 00057 "The noise and the background level of the input data cube are estimated using\n" 00058 "the mode calculated in kmo_stats. If the results aren't satisfactory, try chan-\n" 00059 "ging --cpos_rej and --cneg_rej. Then pixels are flagged in the data cube which\n" 00060 "have a value less than the mode plus twice the noise (val < mode + 2*sigma).\n" 00061 "For each spatial pixel the fraction of flagged pixels in its spectral channel\n" 00062 "is determined.\n" 00063 "Spatial pixels are selected where the fraction of flagged spectral pixels is\n" 00064 "greater than 0.95 (corresponding to the 2*sigma above).\n" 00065 "The input cube can contain noise extensions, but they will be ignored. The out-\n" 00066 "put doesn’t contain noise extensions.\n" 00067 "\n" 00068 "BASIC PARAMETERS:\n" 00069 "-----------------\n" 00070 "--fraction\n" 00071 "The fraction of pixels that have to be greater than the threshold can be defi-\n" 00072 "ned with this parameter (value must be between 0 and 1).\n" 00073 "\n" 00074 "--range\n" 00075 "If required, a limited wavelength range can be defined (e.g. \"1.8,2.1\").\n" 00076 "\n" 00077 "ADVANCED PARAMETERS\n" 00078 "-------------------\n" 00079 "--cpos_rej\n" 00080 "--cneg_rej\n" 00081 "--citer\n" 00082 "An iterative sigma clipping is applied in order to calculate the mode (using\n" 00083 "kmo_stats). For each position all pixels in the spectrum are examined. If they\n" 00084 "deviate significantly, they will be rejected according to the conditions:\n" 00085 " val > mean + stdev * cpos_rej\n" 00086 " and\n" 00087 " val < mean - stdev * cneg_rej\n" 00088 "In the first iteration median and percentile level are used.\n" 00089 "\n" 00090 "-------------------------------------------------------------------------------\n" 00091 " Input files:\n" 00092 "\n" 00093 " DO KMOS \n" 00094 " category Type Explanation Required #Frames\n" 00095 " -------- ----- ----------- -------- -------\n" 00096 " <none or any> F3I The datacube frame Y 1 \n" 00097 "\n" 00098 " Output files:\n" 00099 "\n" 00100 " DO KMOS\n" 00101 " category Type Explanation\n" 00102 " -------- ----- -----------\n" 00103 " SKY_MASK F2I The mask frame\n" 00104 "-------------------------------------------------------------------------------\n" 00105 "\n"; 00106 00107 /*----------------------------------------------------------------------------- 00108 * Functions code 00109 *----------------------------------------------------------------------------*/ 00110 00127 int cpl_plugin_get_info(cpl_pluginlist *list) 00128 { 00129 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00130 cpl_plugin *plugin = &recipe->interface; 00131 00132 cpl_plugin_init(plugin, 00133 CPL_PLUGIN_API, 00134 KMOS_BINARY_VERSION, 00135 CPL_PLUGIN_TYPE_RECIPE, 00136 "kmo_sky_mask", 00137 "Create a mask of spatial pixels that indicates which " 00138 "pixels can be considered as sky.", 00139 kmo_sky_mask_description, 00140 "Alex Agudo Berbel", 00141 "usd-help@eso.org", 00142 kmos_get_license(), 00143 kmo_sky_mask_create, 00144 kmo_sky_mask_exec, 00145 kmo_sky_mask_destroy); 00146 00147 cpl_pluginlist_append(list, plugin); 00148 00149 return 0; 00150 } 00151 00159 static int kmo_sky_mask_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 /* --range */ 00175 p = cpl_parameter_new_value("kmos.kmo_sky_mask.range", 00176 CPL_TYPE_STRING, 00177 "Min & max wavelengths to use in sky pixel " 00178 "determination, e.g. [x1_start,x1_end]" 00179 " (microns).", 00180 "kmos.kmo_sky_mask", 00181 ""); 00182 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range"); 00183 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00184 cpl_parameterlist_append(recipe->parameters, p); 00185 00186 /* --fraction */ 00187 p = cpl_parameter_new_value("kmos.kmo_sky_mask.fraction", 00188 CPL_TYPE_DOUBLE, 00189 "Minimum fraction of spatial pixels to select " 00190 "as sky (value between 0 and 1).", 00191 "kmos.kmo_sky_mask", 00192 0.95); 00193 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fraction"); 00194 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00195 cpl_parameterlist_append(recipe->parameters, p); 00196 00197 return kmos_combine_pars_create(recipe->parameters, 00198 "kmos.kmo_sky_mask", 00199 DEF_REJ_METHOD, 00200 TRUE); 00201 } 00202 00208 static int kmo_sky_mask_exec(cpl_plugin *plugin) 00209 { 00210 cpl_recipe *recipe; 00211 00212 /* Get the recipe out of the plugin */ 00213 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00214 recipe = (cpl_recipe *)plugin; 00215 else return -1; 00216 00217 return kmo_sky_mask(recipe->parameters, recipe->frames); 00218 } 00219 00225 static int kmo_sky_mask_destroy(cpl_plugin *plugin) 00226 { 00227 cpl_recipe *recipe; 00228 00229 /* Get the recipe out of the plugin */ 00230 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00231 recipe = (cpl_recipe *)plugin; 00232 else return -1 ; 00233 00234 cpl_parameterlist_delete(recipe->parameters); 00235 return 0 ; 00236 } 00237 00252 static int kmo_sky_mask(cpl_parameterlist *parlist, cpl_frameset *frameset) 00253 { 00254 cpl_imagelist *data_in = NULL; 00255 00256 cpl_image *data_out = NULL; 00257 00258 cpl_vector *ranges = NULL; 00259 00260 int ret_val = 0, 00261 nr_devices = 0, 00262 i = 0, 00263 valid_ifu = FALSE, 00264 citer = 0, 00265 devnr = 0, 00266 index_data = 0; 00267 00268 double cpos_rej = 0.0, 00269 cneg_rej = 0.0, 00270 fraction = 0.0, 00271 ifu_crpix = 0.0, 00272 ifu_crval = 0.0, 00273 ifu_cdelt = 0.0; 00274 00275 const char *ranges_txt = NULL, 00276 *cmethod = NULL; 00277 00278 cpl_propertylist *sub_header_data = NULL; 00279 00280 main_fits_desc desc; 00281 00282 cpl_frame *frame = NULL; 00283 00284 KMO_TRY 00285 { 00286 kmo_init_fits_desc(&desc); 00287 00288 // --- check input --- 00289 KMO_TRY_ASSURE((parlist != NULL) && 00290 (frameset != NULL), 00291 CPL_ERROR_NULL_INPUT, 00292 "Not all input data is provided!"); 00293 00294 KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1, 00295 CPL_ERROR_NULL_INPUT, 00296 "Exactly one data cube must be provided!"); 00297 00298 KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_sky_mask") == 1, 00299 CPL_ERROR_ILLEGAL_INPUT, 00300 "Cannot identify RAW and CALIB frames!"); 00301 00302 KMO_TRY_EXIT_IF_NULL( 00303 frame = kmo_dfs_get_frame(frameset, "0")); 00304 00305 cpl_msg_info("", "--- Parameter setup for kmo_sky_mask ------"); 00306 00307 ranges_txt = kmo_dfs_get_parameter_string(parlist, 00308 "kmos.kmo_sky_mask.range"); 00309 KMO_TRY_CHECK_ERROR_STATE(); 00310 KMO_TRY_EXIT_IF_ERROR( 00311 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.range")); 00312 00313 ranges = kmo_identify_ranges(ranges_txt); 00314 KMO_TRY_CHECK_ERROR_STATE(); 00315 00316 fraction = kmo_dfs_get_parameter_double(parlist, 00317 "kmos.kmo_sky_mask.fraction"); 00318 KMO_TRY_CHECK_ERROR_STATE(); 00319 KMO_TRY_EXIT_IF_ERROR( 00320 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_shift.fraction")); 00321 00322 KMO_TRY_ASSURE((fraction >= 0.0) && 00323 (fraction <= 1.0), 00324 CPL_ERROR_ILLEGAL_INPUT, 00325 "fraction must be between 0.0 and 1.0!!"); 00326 00327 KMO_TRY_EXIT_IF_ERROR( 00328 kmos_combine_pars_load(parlist, 00329 "kmos.kmo_sky_mask", 00330 &cmethod, 00331 &cpos_rej, 00332 &cneg_rej, 00333 &citer, 00334 NULL, 00335 NULL, 00336 FALSE)); 00337 00338 cpl_msg_info("", "-------------------------------------------"); 00339 00340 // load descriptor, header and data of first operand 00341 desc = kmo_identify_fits_header( 00342 cpl_frame_get_filename(frame)); 00343 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be " 00344 "in KMOS-format!"); 00345 00346 KMO_TRY_ASSURE(desc.fits_type == f3i_fits, 00347 CPL_ERROR_ILLEGAL_INPUT, 00348 "The input file hasn't correct data type " 00349 "(KMOSTYPE must be F3I)!"); 00350 00351 // --- load, update & save primary header --- 00352 KMO_TRY_EXIT_IF_ERROR( 00353 kmo_dfs_save_main_header(frameset, SKY_MASK, "", frame, 00354 NULL, parlist, cpl_func)); 00355 00356 // --- load data --- 00357 if (desc.ex_noise == TRUE) { 00358 nr_devices = desc.nr_ext / 2; 00359 } else { 00360 nr_devices = desc.nr_ext; 00361 } 00362 00363 for (i = 1; i <= nr_devices; i++) { 00364 if (desc.ex_noise == FALSE) { 00365 devnr = desc.sub_desc[i - 1].device_nr; 00366 } else { 00367 devnr = desc.sub_desc[2 * i - 1].device_nr; 00368 } 00369 00370 if (desc.ex_badpix == FALSE) { 00371 index_data = kmo_identify_index_desc(desc, devnr, FALSE); 00372 } else { 00373 index_data = kmo_identify_index_desc(desc, devnr, 2); 00374 } 00375 KMO_TRY_CHECK_ERROR_STATE(); 00376 00377 KMO_TRY_EXIT_IF_NULL( 00378 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr, 00379 FALSE)); 00380 00381 // check if IFU is valid 00382 valid_ifu = FALSE; 00383 if (desc.sub_desc[index_data-1].valid_data == TRUE) { 00384 valid_ifu = TRUE; 00385 } 00386 00387 if (valid_ifu) { 00388 // load data 00389 KMO_TRY_EXIT_IF_NULL( 00390 data_in = kmo_dfs_load_cube(frameset, "0", devnr, FALSE)); 00391 00392 if (ranges != NULL) { 00393 ifu_crpix = cpl_propertylist_get_double(sub_header_data, CRPIX3); 00394 KMO_TRY_CHECK_ERROR_STATE_MSG( 00395 "CRPIX3 keyword in FITS-header is missing!"); 00396 00397 ifu_crval = cpl_propertylist_get_double(sub_header_data, CRVAL3); 00398 KMO_TRY_CHECK_ERROR_STATE_MSG( 00399 "CRVAL3 keyword in FITS-header is missing!"); 00400 00401 ifu_cdelt = cpl_propertylist_get_double(sub_header_data, CDELT3); 00402 KMO_TRY_CHECK_ERROR_STATE_MSG( 00403 "CDELT3 keyword in FITS-header is missing!"); 00404 } 00405 00406 cpl_propertylist_erase(sub_header_data, CRPIX3); 00407 cpl_propertylist_erase(sub_header_data, CRVAL3); 00408 cpl_propertylist_erase(sub_header_data, CDELT3); 00409 cpl_propertylist_erase(sub_header_data, CTYPE3); 00410 00411 // calc mode and noise 00412 KMO_TRY_EXIT_IF_NULL( 00413 data_out = kmo_calc_sky_mask(data_in, 00414 ranges, 00415 fraction, 00416 ifu_crpix, 00417 ifu_crval, 00418 ifu_cdelt, 00419 cpos_rej, 00420 cneg_rej, 00421 citer)); 00422 00423 // save data 00424 KMO_TRY_EXIT_IF_ERROR( 00425 kmo_dfs_save_image(data_out, SKY_MASK, "", sub_header_data, 0.)); 00426 00427 // free memory 00428 cpl_imagelist_delete(data_in); data_in = NULL; 00429 cpl_image_delete(data_out); data_out = NULL; 00430 } else { 00431 // invalid IFU, just save sub_headers 00432 KMO_TRY_EXIT_IF_ERROR( 00433 kmo_dfs_save_sub_header(SKY_MASK, "", sub_header_data)); 00434 } 00435 00436 // free memory 00437 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00438 } 00439 } 00440 KMO_CATCH 00441 { 00442 KMO_CATCH_MSG(); 00443 00444 ret_val = -1; 00445 } 00446 00447 kmo_free_fits_desc(&desc); 00448 cpl_propertylist_delete(sub_header_data); sub_header_data = NULL; 00449 cpl_imagelist_delete(data_in); data_in = NULL; 00450 cpl_image_delete(data_out); data_out = NULL; 00451 cpl_vector_delete(ranges); ranges = NULL; 00452 return ret_val; 00453 } 00454