|
KMOS Pipeline Reference Manual
1.3.17
|
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 #include <math.h> 00030 00031 #include <cpl.h> 00032 00033 #include "kmo_utils.h" 00034 #include "kmo_dfs.h" 00035 #include "kmo_error.h" 00036 #include "kmo_priv_extract_spec.h" 00037 #include "kmo_priv_functions.h" 00038 #include "kmo_cpl_extensions.h" 00039 #include "kmo_constants.h" 00040 #include "kmo_priv_fit_profile.h" 00041 #include "kmo_debug.h" 00042 00043 /*----------------------------------------------------------------------------- 00044 * Functions prototypes 00045 *----------------------------------------------------------------------------*/ 00046 00047 static int kmos_extract_spec_create(cpl_plugin *); 00048 static int kmos_extract_spec_exec(cpl_plugin *); 00049 static int kmos_extract_spec_destroy(cpl_plugin *); 00050 static int kmos_extract_spec(cpl_parameterlist *, cpl_frameset *); 00051 00052 /*----------------------------------------------------------------------------- 00053 * Static variables 00054 *----------------------------------------------------------------------------*/ 00055 00056 static char kmos_extract_spec_description[] = 00057 "This recipe extracts a spectrum from a datacube. The datacube is with or \n" 00058 "without noise). The output will be a similarly formatted FITS file.\n" 00059 "\n" 00060 "---------------------------------------------------------------------------\n" 00061 " Input files:\n" 00062 "\n" 00063 " DO KMOS \n" 00064 " category Type Explanation Required #Frames\n" 00065 " -------- ----- ----------- -------- -------\n" 00066 " <none or any> F3I The datacubes Y 1 \n" 00067 " <none or any> F2I The mask N 0,1 \n" 00068 "\n" 00069 " Output files:\n" 00070 "\n" 00071 " DO KMOS\n" 00072 " category Type Explanation\n" 00073 " -------- ----- -----------\n" 00074 " EXTRACT_SPEC F1I Extracted spectrum \n" 00075 " EXTRACT_SPEC_MASK F2I (optional, if --save_mask=true and \n" 00076 " --mask_method='optimal': The calculated mask) \n" 00077 "---------------------------------------------------------------------------\n" 00078 "\n"; 00079 00080 /*----------------------------------------------------------------------------- 00081 * Functions code 00082 *----------------------------------------------------------------------------*/ 00083 00084 /*----------------------------------------------------------------------------*/ 00088 /*----------------------------------------------------------------------------*/ 00089 00092 /*----------------------------------------------------------------------------*/ 00101 /*----------------------------------------------------------------------------*/ 00102 int cpl_plugin_get_info(cpl_pluginlist *list) 00103 { 00104 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe); 00105 cpl_plugin *plugin = &recipe->interface; 00106 00107 cpl_plugin_init(plugin, 00108 CPL_PLUGIN_API, 00109 KMOS_BINARY_VERSION, 00110 CPL_PLUGIN_TYPE_RECIPE, 00111 "kmos_extract_spec", 00112 "Extract a spectrum from a cube", 00113 kmos_extract_spec_description, 00114 "Alex Agudo Berbel, Y. Jung", 00115 "usd-help@eso.org", 00116 kmos_get_license(), 00117 kmos_extract_spec_create, 00118 kmos_extract_spec_exec, 00119 kmos_extract_spec_destroy); 00120 00121 cpl_pluginlist_append(list, plugin); 00122 return 0; 00123 } 00124 00125 /*----------------------------------------------------------------------------*/ 00133 /*----------------------------------------------------------------------------*/ 00134 static int kmos_extract_spec_create(cpl_plugin *plugin) 00135 { 00136 cpl_recipe *recipe; 00137 cpl_parameter *p; 00138 00139 /* Check that the plugin is part of a valid recipe */ 00140 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00141 recipe = (cpl_recipe *)plugin; 00142 else 00143 return -1; 00144 00145 /* Create the parameters list in the cpl_recipe object */ 00146 recipe->parameters = cpl_parameterlist_new(); 00147 00148 /* Fill the parameters list */ 00149 /* --mask_method */ 00150 p = cpl_parameter_new_value("kmos.kmos_extract_spec.mask_method", 00151 CPL_TYPE_STRING, "Method used : mask, integrated or optimal", 00152 "kmos.kmos_extract_spec", "integrated"); 00153 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mask_method"); 00154 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00155 cpl_parameterlist_append(recipe->parameters, p); 00156 00157 /* --centre */ 00158 p = cpl_parameter_new_value("kmos.kmos_extract_spec.centre", 00159 CPL_TYPE_STRING, "The centre of the circular mask (pixel)", 00160 "kmos.kmos_extract_spec", "7.5,7.5"); 00161 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "centre"); 00162 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00163 cpl_parameterlist_append(recipe->parameters, p); 00164 00165 /* --radius */ 00166 p = cpl_parameter_new_value("kmos.kmos_extract_spec.radius", 00167 CPL_TYPE_DOUBLE, "The radius of the circular mask (pixel)", 00168 "kmos.kmos_extract_spec", 3.0); 00169 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "radius"); 00170 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00171 cpl_parameterlist_append(recipe->parameters, p); 00172 00173 /* --save_mask */ 00174 p = cpl_parameter_new_value("kmos.kmos_extract_spec.save_mask", 00175 CPL_TYPE_BOOL, "Flag to save the mask", "kmos.kmos_extract_spec", 00176 FALSE); 00177 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_mask"); 00178 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00179 cpl_parameterlist_append(recipe->parameters, p); 00180 00181 return kmos_combine_pars_create(recipe->parameters, 00182 "kmos.kmos_extract_spec", DEF_REJ_METHOD, FALSE); 00183 } 00184 00185 /*----------------------------------------------------------------------------*/ 00191 /*----------------------------------------------------------------------------*/ 00192 static int kmos_extract_spec_exec(cpl_plugin *plugin) 00193 { 00194 cpl_recipe *recipe; 00195 00196 /* Get the recipe out of the plugin */ 00197 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00198 recipe = (cpl_recipe *)plugin; 00199 else return -1; 00200 00201 return kmos_extract_spec(recipe->parameters, recipe->frames); 00202 } 00203 00204 /*----------------------------------------------------------------------------*/ 00210 /*----------------------------------------------------------------------------*/ 00211 static int kmos_extract_spec_destroy(cpl_plugin *plugin) 00212 { 00213 cpl_recipe *recipe; 00214 00215 /* Get the recipe out of the plugin */ 00216 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00217 recipe = (cpl_recipe *)plugin; 00218 else return -1 ; 00219 00220 cpl_parameterlist_delete(recipe->parameters); 00221 return 0 ; 00222 } 00223 00224 /*----------------------------------------------------------------------------*/ 00238 /*----------------------------------------------------------------------------*/ 00239 static int kmos_extract_spec( 00240 cpl_parameterlist * parlist, 00241 cpl_frameset * frameset) 00242 { 00243 const cpl_parameter * par ; 00244 const char * mask_method ; 00245 const char * cmethod ; 00246 const char * centre_txt ; 00247 cpl_vector * centre ; 00248 int cmin, cmax, valid_ifu, citer, save_mask, 00249 devnr1, index_data, index_noise, 00250 nr_devices ; 00251 double cpos_rej, cneg_rej, radius, r, x_lo, y_lo, 00252 x_hi, y_hi, cen_x, cen_y, loc_cen_x, loc_cen_y ; 00253 cpl_size auto_cen_x, auto_cen_y ; 00254 cpl_imagelist * data_in ; 00255 cpl_imagelist * noise_in ; 00256 cpl_image * mask ; 00257 cpl_image * made_data_img ; 00258 cpl_vector * spec_data_out ; 00259 cpl_vector * spec_noise_out ; 00260 cpl_vector * fit_par ; 00261 cpl_propertylist * sub_header_data ; 00262 cpl_propertylist * sub_header_noise ; 00263 cpl_propertylist * sub_header_mask ; 00264 cpl_propertylist * fit_pl ; 00265 cpl_frame * op1_frame ; 00266 cpl_frame * op2_frame ; 00267 float * pmask ; 00268 main_fits_desc desc1, desc2; 00269 int i, x, y ; 00270 00271 /* Check entries */ 00272 if (parlist == NULL || frameset == NULL) { 00273 cpl_msg_error(__func__, "Null Inputs") ; 00274 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00275 return -1 ; 00276 } 00277 00278 /* Initialise */ 00279 spec_data_out = spec_noise_out = NULL ; 00280 00281 /* Get parameters */ 00282 par = cpl_parameterlist_find_const(parlist, 00283 "kmos.kmos_extract_spec.mask_method"); 00284 mask_method = cpl_parameter_get_string(par) ; 00285 par = cpl_parameterlist_find_const(parlist, 00286 "kmos.kmos_extract_spec.save_mask"); 00287 save_mask = cpl_parameter_get_bool(par); 00288 if (!strcmp(mask_method, "integrated")) { 00289 par = cpl_parameterlist_find_const(parlist, 00290 "kmos.kmos_extract_spec.centre"); 00291 centre_txt = cpl_parameter_get_string(par) ; 00292 centre = kmo_identify_ranges(centre_txt); 00293 if (cpl_vector_get_size(centre) != 2) { 00294 cpl_msg_error(__func__, "centre must have 2 values like a,b") ; 00295 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00296 return -1 ; 00297 } 00298 cen_x = cpl_vector_get(centre, 0); 00299 cen_y = cpl_vector_get(centre, 1); 00300 cpl_vector_delete(centre); 00301 par = cpl_parameterlist_find_const(parlist, 00302 "kmos.kmos_extract_spec.radius"); 00303 radius = cpl_parameter_get_double(par) ; 00304 if (radius < 0.0) { 00305 cpl_msg_error(__func__, "radius must be greater than 0.0") ; 00306 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00307 return -1 ; 00308 } 00309 } else if (strcmp(mask_method, "optimal") == 0) { 00310 kmos_combine_pars_load(parlist, "kmos.kmos_extract_spec", &cmethod, 00311 &cpos_rej, &cneg_rej, &citer, &cmin, &cmax, FALSE); 00312 } else { 00313 cpl_msg_error(__func__, "Unsupported mask method: %s", mask_method) ; 00314 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00315 return -1 ; 00316 } 00317 00318 /* Identify the RAW and CALIB frames in the input frameset */ 00319 if (kmo_dfs_set_groups(frameset, "kmos_extract_spec") != 1) { 00320 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00321 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00322 return -1 ; 00323 } 00324 00325 /* Check Inputs */ 00326 if (cpl_frameset_get_size(frameset) != 1 && 00327 cpl_frameset_get_size(frameset) != 2) { 00328 cpl_msg_error(__func__, "1 or 2 frames expected") ; 00329 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00330 return -1 ; 00331 } 00332 00333 /* Load frames */ 00334 op1_frame = kmo_dfs_get_frame(frameset, "0"); 00335 kmo_init_fits_desc(&desc1); 00336 kmo_init_fits_desc(&desc2); 00337 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(op1_frame)); 00338 if (cpl_frameset_get_size(frameset) == 2) { 00339 op2_frame = kmo_dfs_get_frame(frameset, "1"); 00340 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(op2_frame)); 00341 } else { 00342 op2_frame = NULL ; 00343 } 00344 00345 /* --- load, update & save primary header --- */ 00346 kmo_dfs_save_main_header(frameset, EXTRACT_SPEC, "", op1_frame, NULL, 00347 parlist, cpl_func); 00348 if (save_mask) { 00349 kmo_dfs_save_main_header(frameset, EXTRACT_SPEC_MASK, "", op1_frame, 00350 NULL, parlist, cpl_func); 00351 } 00352 00353 /* Number of extensions to extract */ 00354 if (desc1.ex_noise == TRUE) { 00355 nr_devices = desc1.nr_ext / 2; 00356 } else { 00357 nr_devices = desc1.nr_ext; 00358 } 00359 00360 /* Loop on the devices */ 00361 for (i = 1; i <= nr_devices ; i++) { 00362 if (desc1.ex_noise == FALSE) { 00363 devnr1 = desc1.sub_desc[i - 1].device_nr; 00364 } else { 00365 devnr1 = desc1.sub_desc[2 * i - 1].device_nr; 00366 } 00367 00368 if (desc1.ex_badpix == FALSE) { 00369 index_data = kmo_identify_index_desc(desc1, devnr1, FALSE); 00370 } else { 00371 index_data = kmo_identify_index_desc(desc1, devnr1, 2); 00372 } 00373 if (desc1.ex_noise) { 00374 index_noise = kmo_identify_index_desc(desc1, devnr1, TRUE); 00375 } 00376 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr1, FALSE); 00377 00378 /* Check if IFU is valid */ 00379 valid_ifu = FALSE; 00380 if (desc1.sub_desc[index_data-1].valid_data == TRUE) { 00381 if ((strcmp(mask_method, "mask") != 0) || 00382 ((strcmp(mask_method, "mask") == 0) && 00383 (desc2.sub_desc[i - 1].valid_data == TRUE))) valid_ifu = TRUE; 00384 } 00385 if (desc1.ex_noise) { 00386 sub_header_noise = kmo_dfs_load_sub_header(frameset, "0", devnr1, 00387 TRUE); 00388 } 00389 00390 if (valid_ifu) { 00391 // load data 00392 data_in = kmo_dfs_load_cube(frameset, "0", devnr1, FALSE); 00393 00394 // load noise, if existing 00395 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) { 00396 noise_in = kmo_dfs_load_cube(frameset, "0", devnr1, TRUE); 00397 } else { 00398 noise_in = NULL ; 00399 } 00400 00401 /* Create the mask */ 00402 if (!strcmp(mask_method, "mask")) { 00403 mask = kmo_dfs_load_image(frameset, "1", 00404 desc2.sub_desc[i - 1].device_nr, FALSE, FALSE, NULL); 00405 } else if (!strcmp(mask_method, "optimal")) { 00406 kmclipm_make_image(data_in, NULL, &made_data_img, NULL, NULL, 00407 cmethod, cpos_rej, cneg_rej, citer, cmax, cmin); 00408 fit_par = kmo_fit_profile_2D(made_data_img, NULL, "gauss", 00409 &mask, &fit_pl); 00410 00411 /* Update subheader with fit parameters */ 00412 cpl_propertylist_append(sub_header_data, fit_pl); 00413 cpl_propertylist_delete(fit_pl); 00414 00415 /* Normalise mask */ 00416 cpl_image_subtract_scalar(mask, cpl_vector_get(fit_par, 0)); 00417 cpl_image_divide_scalar(mask, cpl_vector_get(fit_par, 1)); 00418 cpl_vector_delete(fit_par); 00419 cpl_image_delete(made_data_img); 00420 } else if (!strcmp(mask_method, "integrated")) { 00421 if (cen_x < 1.0 || cen_y < 1.0) { 00422 kmclipm_make_image(data_in, NULL, &made_data_img, NULL, 00423 NULL, "median", 3.0, 3.0, 3, 1, 1); 00424 cpl_image_get_maxpos(made_data_img,&auto_cen_x,&auto_cen_y); 00425 loc_cen_x = (double)auto_cen_x - 1.0 ; 00426 loc_cen_y = (double)auto_cen_y - 1.0 ; 00427 cpl_image_delete(made_data_img); 00428 } else { 00429 loc_cen_x = cen_x - 1.0 ; 00430 loc_cen_y = cen_y - 1.0 ; 00431 } 00432 mask = cpl_image_new(desc1.naxis1, desc1.naxis2,CPL_TYPE_FLOAT); 00433 kmo_image_fill(mask,0.0); 00434 pmask = cpl_image_get_data_float(mask); 00435 00436 /* draw circle */ 00437 x_lo = floor(loc_cen_x - radius); 00438 if (x_lo < 0) x_lo = 0; 00439 y_lo = floor(loc_cen_y - radius); 00440 if (y_lo < 0) y_lo = 0; 00441 x_hi = ceil(loc_cen_x + radius); 00442 if (x_hi > desc1.naxis1) x_hi = desc1.naxis1; 00443 y_hi = ceil(loc_cen_y + radius); 00444 if (y_hi > desc1.naxis2) y_hi = desc1.naxis2; 00445 for (x = x_lo; x < x_hi; x++) { 00446 for (y = y_lo; y < y_hi; y++) { 00447 r = sqrt(pow(x - loc_cen_x,2) + pow(y - loc_cen_y,2)); 00448 if (r <= radius) pmask[x + y * desc1.naxis1] = 1.0; 00449 } 00450 } 00451 } 00452 00453 /* Process & save data */ 00454 kmo_priv_extract_spec(data_in, noise_in, mask, &spec_data_out, 00455 &spec_noise_out); 00456 00457 sub_header_mask = cpl_propertylist_duplicate(sub_header_data); 00458 00459 /* Change WCS here (CRPIX3 goes to CRPIX1 etc...) */ 00460 sub_header_data = kmo_priv_update_header(sub_header_data); 00461 00462 kmclipm_vector *ddd = kmclipm_vector_create(spec_data_out); 00463 kmo_dfs_save_vector(ddd, EXTRACT_SPEC, "", sub_header_data, 0./0.); 00464 kmclipm_vector_delete(ddd); 00465 if (save_mask) { 00466 /* Delete WCS for 3rd dimension since mask is 2D */ 00467 cpl_propertylist_erase(sub_header_mask, CRPIX3); 00468 cpl_propertylist_erase(sub_header_mask, CRVAL3); 00469 cpl_propertylist_erase(sub_header_mask, CDELT3); 00470 cpl_propertylist_erase(sub_header_mask, CTYPE3); 00471 cpl_propertylist_erase(sub_header_mask, CD1_3); 00472 cpl_propertylist_erase(sub_header_mask, CD2_3); 00473 cpl_propertylist_erase(sub_header_mask, CD3_3); 00474 cpl_propertylist_erase(sub_header_mask, CD3_1); 00475 cpl_propertylist_erase(sub_header_mask, CD3_2); 00476 kmo_dfs_save_image(mask, EXTRACT_SPEC_MASK, "", 00477 sub_header_mask, 0.); 00478 } 00479 cpl_propertylist_delete(sub_header_mask); 00480 00481 /* Process & save noise, if existing */ 00482 if (desc1.ex_noise) { 00483 kmclipm_vector *nnn = NULL; 00484 if (spec_noise_out != NULL) { 00485 nnn = kmclipm_vector_create(spec_noise_out); 00486 } 00487 sub_header_noise = kmo_priv_update_header(sub_header_noise); 00488 00489 kmo_dfs_save_vector(nnn, EXTRACT_SPEC, "", sub_header_noise, 00490 0./0.); 00491 kmclipm_vector_delete(nnn); 00492 } 00493 cpl_imagelist_delete(data_in); 00494 cpl_imagelist_delete(noise_in); 00495 cpl_image_delete(mask); 00496 } else { 00497 /* Invalid IFU */ 00498 kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_data); 00499 if (desc1.ex_noise) { 00500 kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_noise); 00501 } 00502 } 00503 cpl_propertylist_delete(sub_header_data); 00504 if (desc1.ex_noise) cpl_propertylist_delete(sub_header_noise); 00505 } 00506 kmo_free_fits_desc(&desc1); 00507 kmo_free_fits_desc(&desc2); 00508 return 0 ; 00509 } 00510
1.7.6.1