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 #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, devnr2, index_data, index_noise ; 00250 double cpos_rej, cneg_rej, radius, r, x_lo, y_lo, 00251 x_hi, y_hi, cen_x, cen_y ; 00252 cpl_imagelist * data_in ; 00253 cpl_imagelist * noise_in ; 00254 cpl_image * mask ; 00255 cpl_image * made_data_img ; 00256 cpl_vector * spec_data_out ; 00257 cpl_vector * spec_noise_out ; 00258 cpl_vector * fit_par ; 00259 cpl_propertylist * sub_header_data ; 00260 cpl_propertylist * sub_header_noise ; 00261 cpl_propertylist * sub_header_mask ; 00262 cpl_propertylist * fit_pl ; 00263 cpl_frame * op1_frame ; 00264 cpl_frame * op2_frame ; 00265 float * pmask ; 00266 main_fits_desc desc1, desc2; 00267 int i, x, y ; 00268 00269 /* Check entries */ 00270 if (parlist == NULL || frameset == NULL) { 00271 cpl_msg_error(__func__, "Null Inputs") ; 00272 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT) ; 00273 return -1 ; 00274 } 00275 00276 /* Initialise */ 00277 spec_data_out = spec_noise_out = NULL ; 00278 00279 /* Get parameters */ 00280 par = cpl_parameterlist_find_const(parlist, 00281 "kmos.kmos_extract_spec.mask_method"); 00282 mask_method = cpl_parameter_get_string(par) ; 00283 00284 if (!strcmp(mask_method, "integrated")) { 00285 par = cpl_parameterlist_find_const(parlist, 00286 "kmos.kmos_extract_spec.centre"); 00287 centre_txt = cpl_parameter_get_string(par) ; 00288 centre = kmo_identify_ranges(centre_txt); 00289 if (cpl_vector_get_size(centre) != 2) { 00290 cpl_msg_error(__func__, "centre must have 2 values like a,b") ; 00291 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00292 return -1 ; 00293 } 00294 cen_x = cpl_vector_get(centre, 0); 00295 cen_y = cpl_vector_get(centre, 1); 00296 cpl_vector_delete(centre); 00297 if (cen_x < 0.0 || cen_y < 0.0) { 00298 cpl_msg_error(__func__, "centre must be greater than 0.0") ; 00299 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00300 return -1 ; 00301 } 00302 par = cpl_parameterlist_find_const(parlist, 00303 "kmos.kmos_extract_spec.radius"); 00304 radius = cpl_parameter_get_double(par) ; 00305 if (radius < 0.0) { 00306 cpl_msg_error(__func__, "radius must be greater than 0.0") ; 00307 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00308 return -1 ; 00309 } 00310 } else if (strcmp(mask_method, "optimal") == 0) { 00311 kmos_combine_pars_load(parlist, "kmos.kmos_extract_spec", &cmethod, 00312 &cpos_rej, &cneg_rej, &citer, &cmin, &cmax, FALSE); 00313 par = cpl_parameterlist_find_const(parlist, 00314 "kmos.kmos_extract_spec.save_mask"); 00315 save_mask = cpl_parameter_get_bool(par); 00316 } else { 00317 cpl_msg_error(__func__, "Unsupported mask method: %s", mask_method) ; 00318 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00319 return -1 ; 00320 } 00321 00322 /* Identify the RAW and CALIB frames in the input frameset */ 00323 if (kmo_dfs_set_groups(frameset, "kmos_extract_spec") != 1) { 00324 cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ; 00325 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00326 return -1 ; 00327 } 00328 00329 /* Check Inputs */ 00330 if (cpl_frameset_get_size(frameset) != 1 && 00331 cpl_frameset_get_size(frameset) != 2) { 00332 cpl_msg_error(__func__, "1 or 2 frames expected") ; 00333 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ; 00334 return -1 ; 00335 } 00336 00337 /* Load frames */ 00338 op1_frame = kmo_dfs_get_frame(frameset, "0"); 00339 kmo_init_fits_desc(&desc1); 00340 kmo_init_fits_desc(&desc2); 00341 desc1 = kmo_identify_fits_header(cpl_frame_get_filename(op1_frame)); 00342 if (cpl_frameset_get_size(frameset) == 2) { 00343 op2_frame = kmo_dfs_get_frame(frameset, "1"); 00344 desc2 = kmo_identify_fits_header(cpl_frame_get_filename(op2_frame)); 00345 } else { 00346 op2_frame = NULL ; 00347 } 00348 00349 /* --- load, update & save primary header --- */ 00350 kmo_dfs_save_main_header(frameset, EXTRACT_SPEC, "", op1_frame, NULL, 00351 parlist, cpl_func); 00352 if (save_mask) { 00353 kmo_dfs_save_main_header(frameset, EXTRACT_SPEC_MASK, "", op1_frame, 00354 NULL, parlist, cpl_func); 00355 } 00356 00357 /* Create mask for integrated-method */ 00358 if (!strcmp(mask_method, "integrated")) { 00359 mask = cpl_image_new(desc1.naxis1, desc1.naxis2, CPL_TYPE_FLOAT); 00360 kmo_image_fill(mask,0.0); 00361 pmask = cpl_image_get_data_float(mask); 00362 00363 /* draw circle */ 00364 x_lo = floor(cen_x - radius); 00365 if (x_lo < 0) x_lo = 0; 00366 y_lo = floor(cen_y - radius); 00367 if (y_lo < 0) y_lo = 0; 00368 x_hi = ceil(cen_x + radius); 00369 if (x_hi > desc1.naxis1) x_hi = desc1.naxis1; 00370 y_hi = ceil(cen_y + radius); 00371 if (y_hi > desc1.naxis2) y_hi = desc1.naxis2; 00372 for (x = x_lo; x < x_hi; x++) { 00373 for (y = y_lo; y < y_hi; y++) { 00374 r = sqrt(pow(x - cen_x,2) + pow(y - cen_y,2)); 00375 if (r <= radius) pmask[x + y * desc1.naxis1] = 1.0; 00376 } 00377 } 00378 } 00379 00380 /* Loop on detectors */ 00381 for (i = 1; i <= KMOS_NR_IFUS ; i++) { 00382 if (desc1.ex_noise == FALSE) { 00383 devnr1 = desc1.sub_desc[i - 1].device_nr; 00384 } else { 00385 devnr1 = desc1.sub_desc[2 * i - 1].device_nr; 00386 } 00387 /* Mask doesn't contain any noise extensions */ 00388 if (strcmp(mask_method, "mask") == 0) { 00389 devnr2 = desc2.sub_desc[i - 1].device_nr; 00390 } 00391 00392 if (desc1.ex_badpix == FALSE) { 00393 index_data = kmo_identify_index_desc(desc1, devnr1, FALSE); 00394 } else { 00395 index_data = kmo_identify_index_desc(desc1, devnr1, 2); 00396 } 00397 if (desc1.ex_noise) { 00398 index_noise = kmo_identify_index_desc(desc1, devnr1, TRUE); 00399 } 00400 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr1, FALSE); 00401 00402 /* Check if IFU is valid */ 00403 valid_ifu = FALSE; 00404 if (desc1.sub_desc[index_data-1].valid_data == TRUE) { 00405 if ((strcmp(mask_method, "mask") != 0) || 00406 ((strcmp(mask_method, "mask") == 0) && 00407 (desc2.sub_desc[i - 1].valid_data == TRUE))) valid_ifu = TRUE; 00408 } 00409 if (desc1.ex_noise) { 00410 sub_header_noise = kmo_dfs_load_sub_header(frameset, "0", devnr1, 00411 TRUE); 00412 } 00413 00414 if (valid_ifu) { 00415 // load data 00416 data_in = kmo_dfs_load_cube(frameset, "0", devnr1, FALSE); 00417 00418 // load noise, if existing 00419 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) { 00420 noise_in = kmo_dfs_load_cube(frameset, "0", devnr1, TRUE); 00421 } else { 00422 noise_in = NULL ; 00423 } 00424 00425 // create or load mask (for integrated-method already 00426 // done outside the for-loop) 00427 if (!strcmp(mask_method, "mask")) { 00428 mask = kmo_dfs_load_image(frameset, "1", devnr2, FALSE, 00429 FALSE, NULL); 00430 } else if (!strcmp(mask_method, "optimal")) { 00431 kmclipm_make_image(data_in, NULL, &made_data_img, NULL, NULL, 00432 cmethod, cpos_rej, cneg_rej, citer, cmax, cmin); 00433 fit_par = kmo_fit_profile_2D(made_data_img, NULL, "gauss", 00434 &mask, &fit_pl); 00435 00436 /* Update subheader with fit parameters */ 00437 cpl_propertylist_append(sub_header_data, fit_pl); 00438 cpl_propertylist_delete(fit_pl); 00439 00440 /* Normalise mask */ 00441 cpl_image_subtract_scalar(mask, cpl_vector_get(fit_par, 0)); 00442 cpl_image_divide_scalar(mask, cpl_vector_get(fit_par, 1)); 00443 cpl_vector_delete(fit_par); 00444 cpl_image_delete(made_data_img); 00445 } 00446 00447 /* Process & save data */ 00448 kmo_priv_extract_spec(data_in, noise_in, mask, &spec_data_out, 00449 &spec_noise_out); 00450 00451 sub_header_mask = cpl_propertylist_duplicate(sub_header_data); 00452 00453 /* Change WCS here (CRPIX3 goes to CRPIX1 etc...) */ 00454 sub_header_data = kmo_priv_update_header(sub_header_data); 00455 00456 kmclipm_vector *ddd = kmclipm_vector_create(spec_data_out); 00457 kmo_dfs_save_vector(ddd, EXTRACT_SPEC, "", sub_header_data, 0./0.); 00458 kmclipm_vector_delete(ddd); 00459 if (save_mask) { 00460 /* Delete WCS for 3rd dimension since mask is 2D */ 00461 cpl_propertylist_erase(sub_header_mask, CRPIX3); 00462 cpl_propertylist_erase(sub_header_mask, CRVAL3); 00463 cpl_propertylist_erase(sub_header_mask, CDELT3); 00464 cpl_propertylist_erase(sub_header_mask, CTYPE3); 00465 cpl_propertylist_erase(sub_header_mask, CD1_3); 00466 cpl_propertylist_erase(sub_header_mask, CD2_3); 00467 cpl_propertylist_erase(sub_header_mask, CD3_3); 00468 cpl_propertylist_erase(sub_header_mask, CD3_1); 00469 cpl_propertylist_erase(sub_header_mask, CD3_2); 00470 kmo_dfs_save_image(mask, EXTRACT_SPEC_MASK, "", 00471 sub_header_mask, 0.); 00472 } 00473 cpl_propertylist_delete(sub_header_mask); 00474 00475 /* Process & save noise, if existing */ 00476 if (desc1.ex_noise) { 00477 kmclipm_vector *nnn = NULL; 00478 if (spec_noise_out != NULL) { 00479 nnn = kmclipm_vector_create(spec_noise_out); 00480 } 00481 sub_header_noise = kmo_priv_update_header(sub_header_noise); 00482 00483 kmo_dfs_save_vector(nnn, EXTRACT_SPEC, "", sub_header_noise, 00484 0./0.); 00485 kmclipm_vector_delete(nnn); 00486 } 00487 cpl_imagelist_delete(data_in); 00488 cpl_imagelist_delete(noise_in); 00489 if (strcmp(mask_method, "integrated")) cpl_image_delete(mask); 00490 } else { 00491 /* Invalid IFU */ 00492 kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_data); 00493 if (desc1.ex_noise) { 00494 kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_noise); 00495 } 00496 } 00497 cpl_propertylist_delete(sub_header_data); 00498 if (desc1.ex_noise) cpl_propertylist_delete(sub_header_noise); 00499 } 00500 if (!strcmp(mask_method, "integrated")) cpl_image_delete(mask); 00501 kmo_free_fits_desc(&desc1); 00502 kmo_free_fits_desc(&desc2); 00503 return 0 ; 00504 } 00505