FORS Pipeline Reference Manual 4.9.20
|
00001 /* $Id: fors_align_sky.c,v 1.6 2013/02/28 15:13:15 cgarcia Exp $ 00002 * 00003 * This file is part of the FORS Data Reduction Pipeline 00004 * Copyright (C) 2002-2010 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 /* 00022 * $Author: cgarcia $ 00023 * $Date: 2013/02/28 15:13:15 $ 00024 * $Revision: 1.6 $ 00025 * $Name: fors-4_9_20 $ 00026 */ 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <math.h> 00033 #include <cpl.h> 00034 #include <moses.h> 00035 #include <fors_dfs.h> 00036 00037 static int fors_align_sky_create(cpl_plugin *); 00038 static int fors_align_sky_exec(cpl_plugin *); 00039 static int fors_align_sky_destroy(cpl_plugin *); 00040 static int fors_align_sky(cpl_parameterlist *, cpl_frameset *); 00041 00042 static char fors_align_sky_description[] = 00043 "This recipe is used to align the wavelength solution based on the arc\n" 00044 "lamp exposure on a set of sky lines observed on a scientific exposure.\n" 00045 "The input rectified frames are produced by the recipe fors_extract_slits.\n" 00046 "An input catalog of sky lines can be specified, otherwise an internal one\n" 00047 "is used.\n" 00048 "\n" 00049 "This recipe should be applied to multi-slit MOS/MXU data: for LSS or\n" 00050 "long-slit like data (MOS/MXU with all slits at the same offset) use recipe\n" 00051 "fors_align_sky_lss instead. Please refer to the FORS Pipeline User's Manual\n" 00052 "for more details.\n" 00053 "\n" 00054 "In the table below the MXU acronym can be alternatively read as MOS, and\n" 00055 "SCI as STD.\n\n" 00056 "Input files:\n\n" 00057 " DO category: Type: Explanation: Required:\n" 00058 " RECTIFIED_ALL_SCI_MXU\n" 00059 " or RECTIFIED_SKY_SCI_MXU Calib Frame with sky lines Y\n" 00060 " SPATIAL_MAP_MXU Calib Spatial coordinate map Y\n" 00061 " CURV_COEFF_MXU Calib Spectral curvature Y\n" 00062 " SLIT_LOCATION_MXU Calib Slit location on CCD Y\n" 00063 " DISP_COEFF_MXU Calib Dispersion solution Y\n" 00064 " MASTER_SKYLINECAT Calib Catalog of sky lines .\n" 00065 " GRISM_TABLE Calib Grism table .\n\n" 00066 "Output files:\n\n" 00067 " DO category: Data type: Explanation:\n" 00068 " SKY_SHIFTS_SLIT_SCI_MXU FITS table Observed sky lines offsets\n" 00069 " WAVELENGTH_MAP_SCI_MXU FITS image Wavelength mapped on CCD\n" 00070 " DISP_COEFF_SCI_MXU FITS image Upgraded dispersion solution\n\n"; 00071 00072 #define fors_align_sky_exit(message) \ 00073 { \ 00074 if (message) cpl_msg_error(recipe, message); \ 00075 cpl_image_delete(wavemap); \ 00076 cpl_image_delete(coordinate); \ 00077 cpl_image_delete(rainbow); \ 00078 cpl_image_delete(smapped); \ 00079 cpl_table_delete(grism_table); \ 00080 cpl_table_delete(maskslits); \ 00081 cpl_table_delete(wavelengths); \ 00082 cpl_table_delete(offsets); \ 00083 cpl_table_delete(slits); \ 00084 cpl_table_delete(polytraces); \ 00085 cpl_table_delete(idscoeff); \ 00086 cpl_vector_delete(lines); \ 00087 cpl_propertylist_delete(header); \ 00088 cpl_msg_indent_less(); \ 00089 return -1; \ 00090 } 00091 00092 #define fors_align_sky_exit_memcheck(message) \ 00093 { \ 00094 if (message) cpl_msg_info(recipe, message); \ 00095 printf("free wavemap (%p)\n", wavemap); \ 00096 cpl_image_delete(wavemap); \ 00097 printf("free coordinate (%p)\n", coordinate); \ 00098 cpl_image_delete(coordinate); \ 00099 printf("free rainbow (%p)\n", rainbow); \ 00100 cpl_image_delete(rainbow); \ 00101 printf("free smapped (%p)\n", smapped); \ 00102 cpl_image_delete(smapped); \ 00103 printf("free grism_table (%p)\n", grism_table); \ 00104 cpl_table_delete(grism_table); \ 00105 printf("free maskslits (%p)\n", maskslits); \ 00106 cpl_table_delete(maskslits); \ 00107 printf("free wavelengths (%p)\n", wavelengths); \ 00108 cpl_table_delete(wavelengths); \ 00109 printf("free offsets (%p)\n", offsets); \ 00110 cpl_table_delete(offsets); \ 00111 printf("free idscoeff (%p)\n", idscoeff); \ 00112 cpl_table_delete(idscoeff); \ 00113 printf("free slits (%p)\n", slits); \ 00114 cpl_table_delete(slits); \ 00115 printf("free polytraces (%p)\n", polytraces); \ 00116 cpl_table_delete(polytraces); \ 00117 printf("free lines (%p)\n", lines); \ 00118 cpl_vector_delete(lines); \ 00119 printf("free header (%p)\n", header); \ 00120 cpl_propertylist_delete(header); \ 00121 cpl_msg_indent_less(); \ 00122 return 0; \ 00123 } 00124 00125 00137 int cpl_plugin_get_info(cpl_pluginlist *list) 00138 { 00139 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe ); 00140 cpl_plugin *plugin = &recipe->interface; 00141 00142 cpl_plugin_init(plugin, 00143 CPL_PLUGIN_API, 00144 FORS_BINARY_VERSION, 00145 CPL_PLUGIN_TYPE_RECIPE, 00146 "fors_align_sky", 00147 "Upgrade wavelength solution using sky lines", 00148 fors_align_sky_description, 00149 "Carlo Izzo", 00150 PACKAGE_BUGREPORT, 00151 "This file is currently part of the FORS Instrument Pipeline\n" 00152 "Copyright (C) 2002-2010 European Southern Observatory\n\n" 00153 "This program is free software; you can redistribute it and/or modify\n" 00154 "it under the terms of the GNU General Public License as published by\n" 00155 "the Free Software Foundation; either version 2 of the License, or\n" 00156 "(at your option) any later version.\n\n" 00157 "This program is distributed in the hope that it will be useful,\n" 00158 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 00159 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 00160 "GNU General Public License for more details.\n\n" 00161 "You should have received a copy of the GNU General Public License\n" 00162 "along with this program; if not, write to the Free Software Foundation,\n" 00163 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n", 00164 fors_align_sky_create, 00165 fors_align_sky_exec, 00166 fors_align_sky_destroy); 00167 00168 cpl_pluginlist_append(list, plugin); 00169 00170 return 0; 00171 } 00172 00173 00184 static int fors_align_sky_create(cpl_plugin *plugin) 00185 { 00186 cpl_recipe *recipe; 00187 cpl_parameter *p; 00188 00189 /* 00190 * Check that the plugin is part of a valid recipe 00191 */ 00192 00193 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00194 recipe = (cpl_recipe *)plugin; 00195 else 00196 return -1; 00197 00198 /* 00199 * Create the (empty) parameters list in the cpl_recipe object 00200 */ 00201 00202 recipe->parameters = cpl_parameterlist_new(); 00203 00204 /* 00205 * Dispersion 00206 */ 00207 00208 p = cpl_parameter_new_value("fors.fors_align_sky.dispersion", 00209 CPL_TYPE_DOUBLE, 00210 "Expected spectral dispersion (Angstrom/pixel)", 00211 "fors.fors_align_sky", 00212 0.0); 00213 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion"); 00214 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00215 cpl_parameterlist_append(recipe->parameters, p); 00216 00217 /* 00218 * Start wavelength for spectral extraction 00219 */ 00220 00221 p = cpl_parameter_new_value("fors.fors_align_sky.startwavelength", 00222 CPL_TYPE_DOUBLE, 00223 "Start wavelength in spectral extraction", 00224 "fors.fors_align_sky", 00225 0.0); 00226 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength"); 00227 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00228 cpl_parameterlist_append(recipe->parameters, p); 00229 00230 /* 00231 * End wavelength for spectral extraction 00232 */ 00233 00234 p = cpl_parameter_new_value("fors.fors_align_sky.endwavelength", 00235 CPL_TYPE_DOUBLE, 00236 "End wavelength in spectral extraction", 00237 "fors.fors_align_sky", 00238 0.0); 00239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength"); 00240 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00241 cpl_parameterlist_append(recipe->parameters, p); 00242 00243 /* 00244 * Sky lines alignment 00245 */ 00246 00247 p = cpl_parameter_new_value("fors.fors_align_sky.skyalign", 00248 CPL_TYPE_INT, 00249 "Polynomial order for sky lines alignment", 00250 "fors.fors_align_sky", 00251 0); 00252 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign"); 00253 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00254 cpl_parameterlist_append(recipe->parameters, p); 00255 00256 /* 00257 * Line catalog table column containing the sky reference wavelengths 00258 */ 00259 00260 p = cpl_parameter_new_value("fors.fors_align_sky.wcolumn", 00261 CPL_TYPE_STRING, 00262 "Name of sky line catalog table column " 00263 "with wavelengths", 00264 "fors.fors_align_sky", 00265 "WLEN"); 00266 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn"); 00267 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00268 cpl_parameterlist_append(recipe->parameters, p); 00269 00270 return 0; 00271 } 00272 00273 00282 static int fors_align_sky_exec(cpl_plugin *plugin) 00283 { 00284 cpl_recipe *recipe; 00285 00286 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00287 recipe = (cpl_recipe *)plugin; 00288 else 00289 return -1; 00290 00291 return fors_align_sky(recipe->parameters, recipe->frames); 00292 } 00293 00294 00303 static int fors_align_sky_destroy(cpl_plugin *plugin) 00304 { 00305 cpl_recipe *recipe; 00306 00307 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00308 recipe = (cpl_recipe *)plugin; 00309 else 00310 return -1; 00311 00312 cpl_parameterlist_delete(recipe->parameters); 00313 00314 return 0; 00315 } 00316 00317 00327 static int fors_align_sky(cpl_parameterlist *parlist, 00328 cpl_frameset *frameset) 00329 { 00330 00331 const char *recipe = "fors_align_sky"; 00332 00333 00334 /* 00335 * Input parameters 00336 */ 00337 00338 double dispersion; 00339 double startwavelength; 00340 double endwavelength; 00341 int skyalign; 00342 const char *wcolumn; 00343 00344 /* 00345 * CPL objects 00346 */ 00347 00348 cpl_image *rainbow = NULL; 00349 cpl_image *wavemap = NULL; 00350 cpl_image *smapped = NULL; 00351 cpl_image *coordinate = NULL; 00352 cpl_table *grism_table = NULL; 00353 cpl_table *wavelengths = NULL; 00354 cpl_table *slits = NULL; 00355 cpl_table *idscoeff = NULL; 00356 cpl_table *polytraces = NULL; 00357 cpl_table *maskslits = NULL; 00358 cpl_table *offsets = NULL; 00359 cpl_vector *lines = NULL; 00360 cpl_propertylist *header = NULL; 00361 00362 /* 00363 * Auxiliary variables 00364 */ 00365 00366 char version[80]; 00367 const char *slit_location_tag; 00368 const char *curv_coeff_tag; 00369 const char *rectified_tag; 00370 const char *wavemap_tag; 00371 const char *shifts_tag; 00372 const char *disp_ali_tag; 00373 const char *disp_coeff_tag; 00374 const char *spatial_map_tag; 00375 int nframes; 00376 int rebin; 00377 int nslits; 00378 int nlines; 00379 int nx; 00380 int highres; 00381 int treat_as_lss; 00382 int i; 00383 double reference; 00384 double *xpos; 00385 double mxpos; 00386 double *line; 00387 int mxu, mos; 00388 int rec_scia; 00389 int rec_stda; 00390 int rec_scis; 00391 int rec_stds; 00392 int nslits_out_det = 0; 00393 00394 00395 char *instrume = NULL; 00396 00397 00398 cpl_msg_set_indentation(2); 00399 00400 if (dfs_files_dont_exist(frameset)) 00401 fors_align_sky_exit(NULL); 00402 00403 00404 /* 00405 * Get configuration parameters 00406 */ 00407 00408 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe); 00409 cpl_msg_indent_more(); 00410 00411 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1) 00412 fors_align_sky_exit("Too many in input: GRISM_TABLE"); 00413 00414 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1); 00415 00416 dispersion = dfs_get_parameter_double(parlist, 00417 "fors.fors_align_sky.dispersion", grism_table); 00418 00419 if (dispersion <= 0.0) 00420 fors_align_sky_exit("Invalid spectral dispersion value"); 00421 00422 startwavelength = dfs_get_parameter_double(parlist, 00423 "fors.fors_align_sky.startwavelength", grism_table); 00424 if (startwavelength > 1.0) 00425 if (startwavelength < 3000.0 || startwavelength > 13000.0) 00426 fors_align_sky_exit("Invalid wavelength"); 00427 00428 endwavelength = dfs_get_parameter_double(parlist, 00429 "fors.fors_align_sky.endwavelength", grism_table); 00430 if (endwavelength > 1.0) { 00431 if (endwavelength < 3000.0 || endwavelength > 13000.0) 00432 fors_align_sky_exit("Invalid wavelength"); 00433 if (startwavelength < 1.0) 00434 fors_align_sky_exit("Invalid wavelength interval"); 00435 } 00436 00437 if (startwavelength > 1.0) 00438 if (endwavelength - startwavelength <= 0.0) 00439 fors_align_sky_exit("Invalid wavelength interval"); 00440 00441 skyalign = dfs_get_parameter_int(parlist, 00442 "fors.fors_align_sky.skyalign", NULL); 00443 00444 if (skyalign < 0) 00445 fors_align_sky_exit("Invalid polynomial degree"); 00446 if (skyalign > 2) 00447 fors_align_sky_exit("Max polynomial degree for sky alignment is 2"); 00448 00449 wcolumn = dfs_get_parameter_string(parlist, 00450 "fors.fors_align_sky.wcolumn", NULL); 00451 00452 cpl_table_delete(grism_table); grism_table = NULL; 00453 00454 if (cpl_error_get_code()) 00455 fors_align_sky_exit("Failure reading the configuration parameters"); 00456 00457 00458 cpl_msg_indent_less(); 00459 cpl_msg_info(recipe, "Check input set-of-frames:"); 00460 cpl_msg_indent_more(); 00461 00462 mxu = cpl_frameset_count_tags(frameset, "SPATIAL_MAP_MXU"); 00463 mos = cpl_frameset_count_tags(frameset, "SPATIAL_MAP_MOS"); 00464 00465 nframes = mos + mxu; 00466 00467 if (nframes == 0) { 00468 fors_align_sky_exit("Missing input spatial map"); 00469 } 00470 if (nframes > 1) { 00471 cpl_msg_error(recipe, 00472 "Too many input spatial maps (%d > 1)", nframes); 00473 fors_align_sky_exit(NULL); 00474 } 00475 00476 if (mxu) { 00477 rec_scia = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_SCI_MXU"); 00478 rec_stda = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_STD_MXU"); 00479 rec_scis = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_SCI_MXU"); 00480 rec_stds = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_STD_MXU"); 00481 } 00482 else { 00483 rec_scia = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_SCI_MOS"); 00484 rec_stda = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_STD_MOS"); 00485 rec_scis = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_SCI_MOS"); 00486 rec_stds = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_STD_MOS"); 00487 } 00488 00489 nframes = rec_scia + rec_stda + rec_scis + rec_stds; 00490 00491 if (nframes == 0) { 00492 fors_align_sky_exit("Missing input rectified scientific spectra"); 00493 } 00494 if (nframes > 1) { 00495 cpl_msg_error(recipe, 00496 "Too many input rectified scientific spectra (%d > 1)", 00497 nframes); 00498 fors_align_sky_exit(NULL); 00499 } 00500 00501 if (cpl_frameset_count_tags(frameset, "MASTER_SKYLINECAT") > 1) 00502 fors_align_sky_exit("Too many in input: MASTER_SKYLINECAT"); 00503 00504 if (rec_scia) { 00505 if (mxu) { 00506 rectified_tag = "RECTIFIED_ALL_SCI_MXU"; 00507 wavemap_tag = "WAVELENGTH_MAP_SCI_MXU"; 00508 shifts_tag = "SKY_SHIFTS_SLIT_SCI_MXU"; 00509 disp_ali_tag = "DISP_COEFF_SCI_MXU"; 00510 } 00511 else { 00512 rectified_tag = "RECTIFIED_ALL_SCI_MOS"; 00513 wavemap_tag = "WAVELENGTH_MAP_SCI_MOS"; 00514 shifts_tag = "SKY_SHIFTS_SLIT_SCI_MOS"; 00515 disp_ali_tag = "DISP_COEFF_SCI_MOS"; 00516 } 00517 } 00518 else if (rec_stda) { 00519 if (mxu) { 00520 rectified_tag = "RECTIFIED_ALL_STD_MXU"; 00521 wavemap_tag = "WAVELENGTH_MAP_STD_MXU"; 00522 shifts_tag = "SKY_SHIFTS_SLIT_STD_MXU"; 00523 disp_ali_tag = "DISP_COEFF_STD_MXU"; 00524 } 00525 else { 00526 rectified_tag = "RECTIFIED_ALL_STD_MOS"; 00527 wavemap_tag = "WAVELENGTH_MAP_STD_MOS"; 00528 shifts_tag = "SKY_SHIFTS_SLIT_STD_MOS"; 00529 disp_ali_tag = "DISP_COEFF_STD_MOS"; 00530 } 00531 } 00532 else if (rec_scis) { 00533 if (mxu) { 00534 rectified_tag = "RECTIFIED_SKY_SCI_MXU"; 00535 wavemap_tag = "WAVELENGTH_MAP_SCI_MXU"; 00536 shifts_tag = "SKY_SHIFTS_SLIT_SCI_MXU"; 00537 disp_ali_tag = "DISP_COEFF_SCI_MXU"; 00538 } 00539 else { 00540 rectified_tag = "RECTIFIED_SKY_SCI_MOS"; 00541 wavemap_tag = "WAVELENGTH_MAP_SCI_MOS"; 00542 shifts_tag = "SKY_SHIFTS_SLIT_SCI_MOS"; 00543 disp_ali_tag = "DISP_COEFF_SCI_MOS"; 00544 } 00545 } 00546 else if (rec_stds) { 00547 if (mxu) { 00548 rectified_tag = "RECTIFIED_SKY_STD_MXU"; 00549 wavemap_tag = "WAVELENGTH_MAP_STD_MXU"; 00550 shifts_tag = "SKY_SHIFTS_SLIT_STD_MXU"; 00551 disp_ali_tag = "DISP_COEFF_STD_MXU"; 00552 } 00553 else { 00554 rectified_tag = "RECTIFIED_SKY_STD_MOS"; 00555 wavemap_tag = "WAVELENGTH_MAP_STD_MOS"; 00556 shifts_tag = "SKY_SHIFTS_SLIT_STD_MOS"; 00557 disp_ali_tag = "DISP_COEFF_STD_MOS"; 00558 } 00559 } 00560 00561 00562 if (mxu) { 00563 disp_coeff_tag = "DISP_COEFF_MXU"; 00564 curv_coeff_tag = "CURV_COEFF_MXU"; 00565 slit_location_tag = "SLIT_LOCATION_MXU"; 00566 spatial_map_tag = "SPATIAL_MAP_MXU"; 00567 } 00568 else { 00569 disp_coeff_tag = "DISP_COEFF_MOS"; 00570 curv_coeff_tag = "CURV_COEFF_MOS"; 00571 slit_location_tag = "SLIT_LOCATION_MOS"; 00572 spatial_map_tag = "SPATIAL_MAP_MOS"; 00573 } 00574 00575 nframes = cpl_frameset_count_tags(frameset, disp_coeff_tag); 00576 00577 if (nframes == 0) { 00578 cpl_msg_error(recipe, "Missing input %s\n", disp_coeff_tag); 00579 fors_align_sky_exit(NULL); 00580 } 00581 if (nframes > 1) { 00582 cpl_msg_error(recipe, 00583 "Too many input %s (%d > 1)", disp_coeff_tag, nframes); 00584 fors_align_sky_exit(NULL); 00585 } 00586 00587 nframes = cpl_frameset_count_tags(frameset, curv_coeff_tag); 00588 00589 if (nframes == 0) { 00590 cpl_msg_error(recipe, "Missing input %s\n", curv_coeff_tag); 00591 fors_align_sky_exit(NULL); 00592 } 00593 if (nframes > 1) { 00594 cpl_msg_error(recipe, 00595 "Too many input %s (%d > 1)", curv_coeff_tag, nframes); 00596 fors_align_sky_exit(NULL); 00597 } 00598 00599 nframes = cpl_frameset_count_tags(frameset, spatial_map_tag); 00600 00601 if (nframes == 0) { 00602 cpl_msg_error(recipe, "Missing input %s\n", spatial_map_tag); 00603 fors_align_sky_exit(NULL); 00604 } 00605 if (nframes > 1) { 00606 cpl_msg_error(recipe, 00607 "Too many input %s (%d > 1)", spatial_map_tag, nframes); 00608 fors_align_sky_exit(NULL); 00609 } 00610 00611 00612 header = dfs_load_header(frameset, spatial_map_tag, 0); 00613 00614 if (header == NULL) 00615 fors_align_sky_exit("Cannot load spatial map header"); 00616 00617 if (mos) 00618 maskslits = mos_load_slits_fors_mos(header, &nslits_out_det); 00619 else 00620 maskslits = mos_load_slits_fors_mxu(header); 00621 00622 /* 00623 * Check if all slits have the same X offset: in such case, abort! 00624 */ 00625 00626 treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det); 00627 00628 cpl_table_delete(maskslits); maskslits = NULL; 00629 00630 if (treat_as_lss) { 00631 cpl_msg_error(recipe, "All slits have the same offset: %.2f mm\n" 00632 "The LSS data reduction strategy must be applied. " 00633 "Please use recipe fors_align_sky_lss.", mxpos); 00634 fors_align_sky_exit(NULL); 00635 } 00636 00637 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID")) 00638 fors_align_sky_exit("Input frames are not from the same grism"); 00639 00640 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID")) 00641 fors_align_sky_exit("Input frames are not from the same filter"); 00642 00643 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID")) 00644 fors_align_sky_exit("Input frames are not from the same chip"); 00645 00646 00647 /* 00648 * Get the reference wavelength and the rebin factor along the 00649 * dispersion direction from the reference frame 00650 */ 00651 00652 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME"); 00653 if (instrume == NULL) 00654 fors_align_sky_exit("Missing keyword INSTRUME in reference frame " 00655 "header"); 00656 00657 if (instrume[4] == '1') 00658 snprintf(version, 80, "%s/%s", "fors1", VERSION); 00659 if (instrume[4] == '2') 00660 snprintf(version, 80, "%s/%s", "fors2", VERSION); 00661 00662 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN"); 00663 00664 if (cpl_error_get_code() != CPL_ERROR_NONE) 00665 fors_align_sky_exit("Missing keyword ESO INS GRIS1 WLEN " 00666 "in reference frame header"); 00667 00668 if (reference < 3000.0) /* Perhaps in nanometers... */ 00669 reference *= 10; 00670 00671 if (reference < 3000.0 || reference > 13000.0) { 00672 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from " 00673 "keyword ESO INS GRIS1 WLEN in reference frame header", 00674 reference); 00675 fors_align_sky_exit(NULL); 00676 } 00677 00678 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference); 00679 00680 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX"); 00681 00682 if (cpl_error_get_code() != CPL_ERROR_NONE) 00683 fors_align_sky_exit("Missing keyword ESO DET WIN1 BINX " 00684 "in reference frame header"); 00685 00686 if (rebin != 1) { 00687 dispersion *= rebin; 00688 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the " 00689 "working dispersion used is %f A/pixel", rebin, 00690 dispersion); 00691 } 00692 00693 cpl_msg_indent_less(); 00694 cpl_msg_info(recipe, "Load input frames..."); 00695 cpl_msg_indent_more(); 00696 00697 coordinate = dfs_load_image(frameset, spatial_map_tag, 00698 CPL_TYPE_FLOAT, 0, 0); 00699 if (coordinate == NULL) 00700 fors_align_sky_exit("Cannot load input reference frame"); 00701 00702 slits = dfs_load_table(frameset, slit_location_tag, 1); 00703 if (slits == NULL) 00704 fors_align_sky_exit("Cannot load slits location table"); 00705 00706 polytraces = dfs_load_table(frameset, curv_coeff_tag, 1); 00707 if (polytraces == NULL) 00708 fors_align_sky_exit("Cannot load spectral curvature table"); 00709 00710 idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1); 00711 if (idscoeff == NULL) 00712 fors_align_sky_exit("Cannot load dispersion solution"); 00713 00714 smapped = dfs_load_image(frameset, rectified_tag, CPL_TYPE_FLOAT, 0, 0); 00715 if (smapped == NULL) 00716 fors_align_sky_exit("Cannot load input rectified frame"); 00717 00718 wavelengths = dfs_load_table(frameset, "MASTER_SKYLINECAT", 1); 00719 00720 if (wavelengths) { 00721 00722 /* 00723 * Cast the wavelengths into a (double precision) CPL vector 00724 */ 00725 00726 nlines = cpl_table_get_nrow(wavelengths); 00727 00728 if (nlines == 0) 00729 fors_align_sky_exit("Empty input sky line catalog"); 00730 00731 if (cpl_table_has_column(wavelengths, wcolumn) != 1) { 00732 cpl_msg_error(recipe, "Missing column %s in input line " 00733 "catalog table", wcolumn); 00734 fors_align_sky_exit(NULL); 00735 } 00736 00737 line = cpl_malloc(nlines * sizeof(double)); 00738 00739 for (i = 0; i < nlines; i++) 00740 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL); 00741 00742 cpl_table_delete(wavelengths); wavelengths = NULL; 00743 00744 lines = cpl_vector_wrap(nlines, line); 00745 } 00746 else { 00747 cpl_msg_info(recipe, "No sky line catalog found in input - fine!"); 00748 } 00749 00750 if (skyalign) { 00751 cpl_msg_info(recipe, "Align wavelength solution to reference " 00752 "skylines applying %d order residual fit...", skyalign); 00753 } 00754 else { 00755 cpl_msg_info(recipe, "Align wavelength solution to reference " 00756 "skylines applying median offset..."); 00757 } 00758 00759 if (dispersion > 1.0) 00760 highres = 0; 00761 else 00762 highres = 1; 00763 00764 nx = cpl_image_get_size_x(coordinate); 00765 00766 rainbow = mos_map_idscoeff(idscoeff, nx, reference, startwavelength, 00767 endwavelength); 00768 00769 offsets = mos_wavelength_align(smapped, slits, reference, 00770 startwavelength, endwavelength, 00771 idscoeff, lines, highres, skyalign, 00772 rainbow, 4); 00773 00774 cpl_vector_delete(lines); lines = NULL; 00775 cpl_image_delete(smapped); smapped = NULL; 00776 00777 if (offsets) { 00778 if (dfs_save_table(frameset, offsets, shifts_tag, NULL, 00779 parlist, recipe, version)) 00780 fors_align_sky_exit(NULL); 00781 00782 cpl_table_delete(offsets); offsets = NULL; 00783 } 00784 else 00785 fors_align_sky_exit("Alignment of the wavelength solution " 00786 "to reference sky lines could not be done!"); 00787 00788 if (dfs_save_table(frameset, idscoeff, disp_ali_tag, NULL, 00789 parlist, recipe, version)) 00790 fors_align_sky_exit(NULL); 00791 00792 cpl_table_delete(idscoeff); idscoeff = NULL; 00793 00794 wavemap = mos_map_wavelengths(coordinate, rainbow, slits, 00795 polytraces, reference, 00796 startwavelength, endwavelength, 00797 dispersion); 00798 00799 cpl_image_delete(rainbow); rainbow = NULL; 00800 cpl_image_delete(coordinate); coordinate = NULL; 00801 cpl_table_delete(polytraces); polytraces = NULL; 00802 cpl_table_delete(slits); slits = NULL; 00803 00804 if (dfs_save_image(frameset, wavemap, wavemap_tag, 00805 header, parlist, recipe, version)) 00806 fors_align_sky_exit(NULL); 00807 00808 cpl_image_delete(wavemap); wavemap = NULL; 00809 cpl_propertylist_delete(header); header = NULL; 00810 00811 return 0; 00812 }