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