FORS Pipeline Reference Manual 4.9.9
|
00001 /* $Id: fors_subtract_sky.c,v 1.6 2010/09/14 07:38:16 cizzo 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: cizzo $ 00023 * $Date: 2010/09/14 07:38:16 $ 00024 * $Revision: 1.6 $ 00025 * $Name: fors-4_9_9 $ 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_subtract_sky_create(cpl_plugin *); 00038 static int fors_subtract_sky_exec(cpl_plugin *); 00039 static int fors_subtract_sky_destroy(cpl_plugin *); 00040 static int fors_subtract_sky(cpl_parameterlist *, cpl_frameset *); 00041 00042 static char fors_subtract_sky_description[] = 00043 "This recipe is used to subtract the sky emission from unrebinned slit\n" 00044 "spectra. This is obtained by robust fitting (i.e., excluding the signal\n" 00045 "from possible point-like objects in slit) of the emission along the CCD\n" 00046 "columns within each spectrum). This method doesn't work if extended\n" 00047 "objects are in slit (it really destroys the object spectra), and is\n" 00048 "not applicable to LSS data. The input scientific frames are produced\n" 00049 "by the recipes fors_remove_bias and fors_flatfield.\n" 00050 "\n" 00051 "This recipe cannot be applied to LSS or long-slit like data (MOS/MXU with\n" 00052 "all slits at the same offset). No automatic recipe is available for this.\n" 00053 "Please refer to the FORS Pipeline User's Manual for more details.\n" 00054 "\n" 00055 "In the table below the MXU acronym can be alternatively read as MOS, and\n" 00056 "SCI as STD.\n\n" 00057 "Input files:\n\n" 00058 " DO category: Type: Explanation: Required:\n" 00059 " SCIENCE_UNBIAS_MXU\n" 00060 " or SCIENCE_UNFLAT_MXU\n" 00061 " or STANDARD_UNBIAS_MXU\n" 00062 " or STANDARD_UNFLAT_MXU Calib Frame with sky lines Y\n" 00063 " CURV_COEFF_MXU Calib Spectral curvature Y\n" 00064 " SLIT_LOCATION_MXU Calib Slit location on CCD Y\n" 00065 " GRISM_TABLE Calib Grism table .\n\n" 00066 "Output files:\n\n" 00067 " DO category: Data type: Explanation:\n" 00068 " UNMAPPED_SCI_MXU\n" 00069 " or UNMAPPED_STD_MXU FITS image Sky subtracted scientific frame\n" 00070 " UNMAPPED_SKY_SCI_MXU\n" 00071 " or UNMAPPED_SKY_STD_MXU FITS image Subtracted sky frame\n\n"; 00072 00073 #define fors_subtract_sky_exit(message) \ 00074 { \ 00075 if (message) cpl_msg_error(recipe, message); \ 00076 cpl_image_delete(spectra); \ 00077 cpl_image_delete(skymap); \ 00078 cpl_table_delete(grism_table); \ 00079 cpl_table_delete(maskslits); \ 00080 cpl_table_delete(slits); \ 00081 cpl_table_delete(polytraces); \ 00082 cpl_propertylist_delete(header); \ 00083 cpl_msg_indent_less(); \ 00084 return -1; \ 00085 } 00086 00087 #define fors_subtract_sky_exit_memcheck(message) \ 00088 { \ 00089 if (message) cpl_msg_info(recipe, message); \ 00090 printf("free spectra (%p)\n", spectra); \ 00091 cpl_image_delete(spectra); \ 00092 printf("free skymap (%p)\n", skymap); \ 00093 cpl_image_delete(skymap); \ 00094 printf("free grism_table (%p)\n", grism_table); \ 00095 cpl_table_delete(grism_table); \ 00096 printf("free maskslits (%p)\n", maskslits); \ 00097 cpl_table_delete(maskslits); \ 00098 printf("free slits (%p)\n", slits); \ 00099 cpl_table_delete(slits); \ 00100 printf("free polytraces (%p)\n", polytraces); \ 00101 cpl_table_delete(polytraces); \ 00102 printf("free header (%p)\n", header); \ 00103 cpl_propertylist_delete(header); \ 00104 cpl_msg_indent_less(); \ 00105 return 0; \ 00106 } 00107 00108 00120 int cpl_plugin_get_info(cpl_pluginlist *list) 00121 { 00122 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe ); 00123 cpl_plugin *plugin = &recipe->interface; 00124 00125 cpl_plugin_init(plugin, 00126 CPL_PLUGIN_API, 00127 FORS_BINARY_VERSION, 00128 CPL_PLUGIN_TYPE_RECIPE, 00129 "fors_subtract_sky", 00130 "Subtract sky from scientific spectra", 00131 fors_subtract_sky_description, 00132 "Carlo Izzo", 00133 PACKAGE_BUGREPORT, 00134 "This file is currently part of the FORS Instrument Pipeline\n" 00135 "Copyright (C) 2002-2010 European Southern Observatory\n\n" 00136 "This program is free software; you can redistribute it and/or modify\n" 00137 "it under the terms of the GNU General Public License as published by\n" 00138 "the Free Software Foundation; either version 2 of the License, or\n" 00139 "(at your option) any later version.\n\n" 00140 "This program is distributed in the hope that it will be useful,\n" 00141 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 00142 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 00143 "GNU General Public License for more details.\n\n" 00144 "You should have received a copy of the GNU General Public License\n" 00145 "along with this program; if not, write to the Free Software Foundation,\n" 00146 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n", 00147 fors_subtract_sky_create, 00148 fors_subtract_sky_exec, 00149 fors_subtract_sky_destroy); 00150 00151 cpl_pluginlist_append(list, plugin); 00152 00153 return 0; 00154 } 00155 00156 00167 static int fors_subtract_sky_create(cpl_plugin *plugin) 00168 { 00169 cpl_recipe *recipe; 00170 cpl_parameter *p; 00171 00172 /* 00173 * Check that the plugin is part of a valid recipe 00174 */ 00175 00176 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00177 recipe = (cpl_recipe *)plugin; 00178 else 00179 return -1; 00180 00181 /* 00182 * Create the (empty) parameters list in the cpl_recipe object 00183 */ 00184 00185 recipe->parameters = cpl_parameterlist_new(); 00186 00187 /* 00188 * Dispersion 00189 */ 00190 00191 p = cpl_parameter_new_value("fors.fors_subtract_sky.dispersion", 00192 CPL_TYPE_DOUBLE, 00193 "Expected spectral dispersion (Angstrom/pixel)", 00194 "fors.fors_subtract_sky", 00195 0.0); 00196 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion"); 00197 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00198 cpl_parameterlist_append(recipe->parameters, p); 00199 00200 /* 00201 * Start wavelength for spectral extraction 00202 */ 00203 00204 p = cpl_parameter_new_value("fors.fors_subtract_sky.startwavelength", 00205 CPL_TYPE_DOUBLE, 00206 "Start wavelength in spectral extraction", 00207 "fors.fors_subtract_sky", 00208 0.0); 00209 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength"); 00210 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00211 cpl_parameterlist_append(recipe->parameters, p); 00212 00213 /* 00214 * End wavelength for spectral extraction 00215 */ 00216 00217 p = cpl_parameter_new_value("fors.fors_subtract_sky.endwavelength", 00218 CPL_TYPE_DOUBLE, 00219 "End wavelength in spectral extraction", 00220 "fors.fors_subtract_sky", 00221 0.0); 00222 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength"); 00223 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00224 cpl_parameterlist_append(recipe->parameters, p); 00225 00226 /* 00227 * Cosmic rays removal 00228 */ 00229 00230 p = cpl_parameter_new_value("fors.fors_subtract_sky.cosmics", 00231 CPL_TYPE_BOOL, 00232 "Eliminate cosmic rays hits", 00233 "fors.fors_subtract_sky", 00234 FALSE); 00235 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics"); 00236 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); 00237 cpl_parameterlist_append(recipe->parameters, p); 00238 00239 return 0; 00240 } 00241 00242 00251 static int fors_subtract_sky_exec(cpl_plugin *plugin) 00252 { 00253 cpl_recipe *recipe; 00254 00255 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00256 recipe = (cpl_recipe *)plugin; 00257 else 00258 return -1; 00259 00260 return fors_subtract_sky(recipe->parameters, recipe->frames); 00261 } 00262 00263 00272 static int fors_subtract_sky_destroy(cpl_plugin *plugin) 00273 { 00274 cpl_recipe *recipe; 00275 00276 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 00277 recipe = (cpl_recipe *)plugin; 00278 else 00279 return -1; 00280 00281 cpl_parameterlist_delete(recipe->parameters); 00282 00283 return 0; 00284 } 00285 00286 00296 static int fors_subtract_sky(cpl_parameterlist *parlist, 00297 cpl_frameset *frameset) 00298 { 00299 00300 const char *recipe = "fors_subtract_sky"; 00301 00302 00303 /* 00304 * Input parameters 00305 */ 00306 00307 double dispersion; 00308 double startwavelength; 00309 double endwavelength; 00310 int cosmics; 00311 00312 /* 00313 * CPL objects 00314 */ 00315 00316 cpl_image *spectra = NULL; 00317 cpl_image *skymap = NULL; 00318 cpl_table *grism_table = NULL; 00319 cpl_table *polytraces = NULL; 00320 cpl_table *slits = NULL; 00321 cpl_table *maskslits = NULL; 00322 cpl_propertylist *header = NULL; 00323 00324 /* 00325 * Auxiliary variables 00326 */ 00327 00328 char version[80]; 00329 const char *slit_location_tag; 00330 const char *input_tag; 00331 const char *curv_coeff_tag; 00332 const char *unmapped_tag; 00333 const char *unmapped_sky_tag; 00334 int nframes; 00335 int rebin; 00336 int nslits; 00337 int treat_as_lss; 00338 int i; 00339 double reference; 00340 double gain; 00341 double *xpos; 00342 double mxpos; 00343 int mxu, mos, lss; 00344 int rec_scib; 00345 int rec_stdb; 00346 int rec_scif; 00347 int rec_stdf; 00348 00349 char *instrume = NULL; 00350 00351 00352 cpl_msg_set_indentation(2); 00353 00354 if (dfs_files_dont_exist(frameset)) 00355 fors_subtract_sky_exit(NULL); 00356 00357 00358 /* 00359 * Get configuration parameters 00360 */ 00361 00362 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe); 00363 cpl_msg_indent_more(); 00364 00365 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1) 00366 fors_subtract_sky_exit("Too many in input: GRISM_TABLE"); 00367 00368 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1); 00369 00370 dispersion = dfs_get_parameter_double(parlist, 00371 "fors.fors_subtract_sky.dispersion", grism_table); 00372 00373 if (dispersion <= 0.0) 00374 fors_subtract_sky_exit("Invalid spectral dispersion value"); 00375 00376 startwavelength = dfs_get_parameter_double(parlist, 00377 "fors.fors_subtract_sky.startwavelength", grism_table); 00378 if (startwavelength > 1.0) 00379 if (startwavelength < 3000.0 || startwavelength > 13000.0) 00380 fors_subtract_sky_exit("Invalid wavelength"); 00381 00382 endwavelength = dfs_get_parameter_double(parlist, 00383 "fors.fors_subtract_sky.endwavelength", grism_table); 00384 if (endwavelength > 1.0) { 00385 if (endwavelength < 3000.0 || endwavelength > 13000.0) 00386 fors_subtract_sky_exit("Invalid wavelength"); 00387 if (startwavelength < 1.0) 00388 fors_subtract_sky_exit("Invalid wavelength interval"); 00389 } 00390 00391 if (startwavelength > 1.0) 00392 if (endwavelength - startwavelength <= 0.0) 00393 fors_subtract_sky_exit("Invalid wavelength interval"); 00394 00395 cosmics = dfs_get_parameter_bool(parlist, 00396 "fors.fors_subtract_sky.cosmics", NULL); 00397 00398 cpl_table_delete(grism_table); grism_table = NULL; 00399 00400 if (cpl_error_get_code()) 00401 fors_subtract_sky_exit("Failure reading the configuration parameters"); 00402 00403 00404 cpl_msg_indent_less(); 00405 cpl_msg_info(recipe, "Check input set-of-frames:"); 00406 cpl_msg_indent_more(); 00407 00408 mxu = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MXU"); 00409 mos = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MOS"); 00410 lss = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_LSS"); 00411 00412 if (lss) 00413 fors_subtract_sky_exit("Use this recipe just with MOS/MXU data."); 00414 00415 nframes = mos + mxu; 00416 00417 if (nframes == 0) { 00418 fors_subtract_sky_exit("Missing input slit location table"); 00419 } 00420 if (nframes > 1) { 00421 cpl_msg_error(recipe, 00422 "Too many input slit location tables (%d > 1)", nframes); 00423 fors_subtract_sky_exit(NULL); 00424 } 00425 00426 if (mxu) 00427 curv_coeff_tag = "CURV_COEFF_MXU"; 00428 else 00429 curv_coeff_tag = "CURV_COEFF_MXU"; 00430 00431 00432 nframes = cpl_frameset_count_tags(frameset, curv_coeff_tag); 00433 00434 if (nframes == 0) { 00435 cpl_msg_error(recipe, "Missing input %s", curv_coeff_tag); 00436 fors_subtract_sky_exit(NULL); 00437 } 00438 if (nframes > 1) { 00439 cpl_msg_error(recipe, "Too many input %s (%d > 1)", curv_coeff_tag, 00440 nframes); 00441 fors_subtract_sky_exit(NULL); 00442 } 00443 00444 if (mxu) { 00445 rec_scib = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MXU"); 00446 rec_stdb = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MXU"); 00447 rec_scif = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MXU"); 00448 rec_stdf = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MXU"); 00449 } 00450 else { 00451 rec_scib = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MOS"); 00452 rec_stdb = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MOS"); 00453 rec_scif = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MOS"); 00454 rec_stdf = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MOS"); 00455 } 00456 00457 nframes = rec_scib + rec_stdb + rec_scif + rec_stdf; 00458 00459 if (nframes == 0) { 00460 fors_subtract_sky_exit("Missing input scientific spectra"); 00461 } 00462 if (nframes > 1) { 00463 cpl_msg_error(recipe, "Too many input scientific spectra (%d > 1)", 00464 nframes); 00465 fors_subtract_sky_exit(NULL); 00466 } 00467 00468 if (rec_scib) { 00469 if (mxu) { 00470 input_tag = "SCIENCE_UNBIAS_MXU"; 00471 slit_location_tag = "SLIT_LOCATION_MXU"; 00472 unmapped_tag = "UNMAPPED_SCI_MXU"; 00473 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MXU"; 00474 } 00475 else { 00476 input_tag = "SCIENCE_UNBIAS_MOS"; 00477 slit_location_tag = "SLIT_LOCATION_MOS"; 00478 unmapped_tag = "UNMAPPED_SCI_MOS"; 00479 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MOS"; 00480 } 00481 } 00482 else if (rec_stdb) { 00483 if (mxu) { 00484 input_tag = "STANDARD_UNBIAS_MXU"; 00485 slit_location_tag = "SLIT_LOCATION_MXU"; 00486 unmapped_tag = "UNMAPPED_STD_MXU"; 00487 unmapped_sky_tag = "UNMAPPED_SKY_STD_MXU"; 00488 } 00489 else { 00490 input_tag = "STANDARD_UNBIAS_MOS"; 00491 slit_location_tag = "SLIT_LOCATION_MOS"; 00492 unmapped_tag = "UNMAPPED_STD_MOS"; 00493 unmapped_sky_tag = "UNMAPPED_SKY_STD_MOS"; 00494 } 00495 } 00496 else if (rec_scif) { 00497 if (mxu) { 00498 input_tag = "SCIENCE_UNFLAT_MXU"; 00499 slit_location_tag = "SLIT_LOCATION_MXU"; 00500 unmapped_tag = "UNMAPPED_SCI_MXU"; 00501 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MXU"; 00502 } 00503 else { 00504 input_tag = "SCIENCE_UNFLAT_MOS"; 00505 slit_location_tag = "SLIT_LOCATION_MOS"; 00506 unmapped_tag = "UNMAPPED_SCI_MOS"; 00507 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MOS"; 00508 } 00509 } 00510 else if (rec_stdf) { 00511 if (mxu) { 00512 input_tag = "STANDARD_UNFLAT_MXU"; 00513 slit_location_tag = "SLIT_LOCATION_MXU"; 00514 unmapped_tag = "UNMAPPED_STD_MXU"; 00515 unmapped_sky_tag = "UNMAPPED_SKY_STD_MXU"; 00516 } 00517 else { 00518 input_tag = "STANDARD_UNFLAT_MOS"; 00519 slit_location_tag = "SLIT_LOCATION_MOS"; 00520 unmapped_tag = "UNMAPPED_STD_MOS"; 00521 unmapped_sky_tag = "UNMAPPED_SKY_STD_MOS"; 00522 } 00523 } 00524 00525 00526 header = dfs_load_header(frameset, input_tag, 0); 00527 00528 if (header == NULL) 00529 fors_subtract_sky_exit("Cannot load scientific frame header"); 00530 00531 if (mos) 00532 maskslits = mos_load_slits_fors_mos(header); 00533 else 00534 maskslits = mos_load_slits_fors_mxu(header); 00535 00536 /* 00537 * Check if all slits have the same X offset: if not, abort! 00538 */ 00539 00540 mxpos = cpl_table_get_column_median(maskslits, "xtop"); 00541 xpos = cpl_table_get_data_double(maskslits, "xtop"); 00542 nslits = cpl_table_get_nrow(maskslits); 00543 00544 treat_as_lss = 1; 00545 for (i = 0; i < nslits; i++) { 00546 if (fabs(mxpos-xpos[i]) > 0.01) { 00547 treat_as_lss = 0; 00548 break; 00549 } 00550 } 00551 00552 cpl_table_delete(maskslits); maskslits = NULL; 00553 00554 if (treat_as_lss) 00555 fors_subtract_sky_exit("This recipe cannot process MOS/MXU " 00556 "data with all slits at the same offset."); 00557 00558 00559 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID")) 00560 fors_subtract_sky_exit("Input frames are not from the same grism"); 00561 00562 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID")) 00563 fors_subtract_sky_exit("Input frames are not from the same filter"); 00564 00565 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID")) 00566 fors_subtract_sky_exit("Input frames are not from the same chip"); 00567 00568 00569 /* 00570 * Get the reference wavelength and the rebin factor along the 00571 * dispersion direction from the reference frame 00572 */ 00573 00574 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME"); 00575 if (instrume == NULL) 00576 fors_subtract_sky_exit("Missing keyword INSTRUME in reference frame " 00577 "header"); 00578 00579 if (instrume[4] == '1') 00580 snprintf(version, 80, "%s/%s", "fors1", VERSION); 00581 if (instrume[4] == '2') 00582 snprintf(version, 80, "%s/%s", "fors2", VERSION); 00583 00584 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN"); 00585 00586 if (cpl_error_get_code() != CPL_ERROR_NONE) 00587 fors_subtract_sky_exit("Missing keyword ESO INS GRIS1 WLEN " 00588 "in reference frame header"); 00589 00590 if (reference < 3000.0) /* Perhaps in nanometers... */ 00591 reference *= 10; 00592 00593 if (reference < 3000.0 || reference > 13000.0) { 00594 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from " 00595 "keyword ESO INS GRIS1 WLEN in reference frame header", 00596 reference); 00597 fors_subtract_sky_exit(NULL); 00598 } 00599 00600 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference); 00601 00602 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX"); 00603 00604 if (cpl_error_get_code() != CPL_ERROR_NONE) 00605 fors_subtract_sky_exit("Missing keyword ESO DET WIN1 BINX " 00606 "in reference frame header"); 00607 00608 if (rebin != 1) { 00609 dispersion *= rebin; 00610 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the " 00611 "working dispersion used is %f A/pixel", rebin, 00612 dispersion); 00613 } 00614 00615 if (cosmics) { 00616 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD"); 00617 00618 if (cpl_error_get_code() != CPL_ERROR_NONE) 00619 fors_subtract_sky_exit("Missing keyword ESO DET OUT1 CONAD in " 00620 "scientific frame header"); 00621 00622 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain); 00623 } 00624 00625 00626 cpl_msg_indent_less(); 00627 cpl_msg_info(recipe, "Load input frames..."); 00628 cpl_msg_indent_more(); 00629 00630 spectra = dfs_load_image(frameset, input_tag, CPL_TYPE_FLOAT, 0, 0); 00631 if (spectra == NULL) 00632 fors_subtract_sky_exit("Cannot load input scientific frame"); 00633 00634 slits = dfs_load_table(frameset, slit_location_tag, 1); 00635 if (slits == NULL) 00636 fors_subtract_sky_exit("Cannot load slits location table"); 00637 00638 polytraces = dfs_load_table(frameset, curv_coeff_tag, 1); 00639 if (polytraces == NULL) 00640 fors_subtract_sky_exit("Cannot load spectral curvature table"); 00641 00642 cpl_msg_indent_less(); 00643 cpl_msg_info(recipe, "Local sky determination..."); 00644 cpl_msg_indent_more(); 00645 skymap = mos_subtract_sky(spectra, slits, polytraces, reference, 00646 startwavelength, endwavelength, dispersion); 00647 00648 cpl_table_delete(polytraces); polytraces = NULL; 00649 cpl_table_delete(slits); slits = NULL; 00650 00651 if (cosmics) { 00652 cpl_msg_info(recipe, "Removing cosmic rays..."); 00653 mos_clean_cosmics(spectra, gain, -1., -1.); 00654 } 00655 00656 if (dfs_save_image(frameset, spectra, unmapped_tag, 00657 header, parlist, recipe, version)) 00658 fors_subtract_sky_exit(NULL); 00659 00660 cpl_image_delete(spectra); spectra = NULL; 00661 00662 if (dfs_save_image(frameset, skymap, unmapped_sky_tag, 00663 header, parlist, recipe, version)) 00664 fors_subtract_sky_exit(NULL); 00665 00666 cpl_image_delete(skymap); skymap = NULL; 00667 00668 cpl_propertylist_delete(header); header = NULL; 00669 00670 return 0; 00671 }