00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032 #include <string.h>
00033 #include <math.h>
00034 #include <cpl.h>
00035 #include <moses.h>
00036 #include <fors_dfs.h>
00037
00038 static int fors_extract_create(cpl_plugin *);
00039 static int fors_extract_exec(cpl_plugin *);
00040 static int fors_extract_destroy(cpl_plugin *);
00041 static int fors_extract(cpl_parameterlist *, cpl_frameset *);
00042
00043 static char fors_extract_description[] =
00044 "This recipe is used to reduce scientific spectra using the global\n"
00045 "distortion table created by the recipe fors_calib. The spectra are\n"
00046 "bias subtracted, flat fielded (if a normalised flat field is specified)\n"
00047 "and remapped eliminating the optical distortions. The wavelength calibration\n"
00048 "can be optionally upgraded using a number of sky lines: if no sky lines\n"
00049 "catalog of wavelengths is specified, an internal one is used instead.\n"
00050 "If the alignment to the sky lines is performed, the applied dispersion\n"
00051 "coefficient table is upgraded and saved to disk, and a new CCD wavelengths\n"
00052 "map is created.\n"
00053 "This recipe accepts both FORS1 and FORS2 frames. A grism table (typically\n"
00054 "depending on the instrument mode, and in particular on the grism used)\n"
00055 "may also be specified: this table contains a default recipe parameter\n"
00056 "setting to control the way spectra are extracted for a specific instrument\n"
00057 "mode, as it is used for automatic run of the pipeline on Paranal and in\n"
00058 "Garching. If this table is specified, it will modify the default recipe\n"
00059 "parameter setting, with the exception of those parameters which have been\n"
00060 "explicitly modifyed on the command line. If a grism table is not specified,\n"
00061 "the input recipe parameters values will always be read from the command\n"
00062 "line, or from an esorex configuration file if present, or from their\n"
00063 "generic default values (that are rarely meaningful).\n"
00064 "In the table below the MXU acronym can be read alternatively as MOS\n"
00065 "and LSS, depending on the instrument mode of the input data. Either a\n"
00066 "scientific or a standard star exposure can be specified in input (not\n"
00067 "both).\n\n"
00068 "Input files:\n\n"
00069 " DO category: Type: Explanation: Required:\n"
00070 " SCIENCE_MXU Raw Scientific exposure Y\n"
00071 " or STANDARD_MXU Raw Standard star exposure Y\n"
00072 " MASTER_BIAS Calib Master bias Y\n"
00073 " GRISM_TABLE Calib Grism table .\n"
00074 " MASTER_SKYLINECAT Calib Sky lines catalog .\n"
00075 "\n"
00076 " MASTER_NORM_FLAT_MXU Calib Normalised flat field .\n"
00077 " MASTER_DISTORTION_TABLE Calib Global distortion model .\n"
00078 "\n"
00079 " or, in case of LSS-like MOS/MXU data,\n"
00080 "\n"
00081 " MASTER_NORM_FLAT_LONG_MXU Calib Normalised flat field .\n"
00082 "Output files:\n\n"
00083 " DO category: Data type: Explanation:\n"
00084 " REDUCED_SCI_MXU FITS image Extracted scientific spectra\n"
00085 " REDUCED_SKY_SCI_MXU FITS image Extracted sky spectra\n"
00086 " REDUCED_ERROR_SCI_MXU FITS image Errors on extracted spectra\n"
00087 " UNMAPPED_SCI_MXU FITS image Sky subtracted scientific spectra\n"
00088 " MAPPED_SCI_MXU FITS image Rectified scientific spectra\n"
00089 " MAPPED_ALL_SCI_MXU FITS image Rectified science spectra with sky\n"
00090 " MAPPED_SKY_SCI_MXU FITS image Rectified sky spectra\n"
00091 " UNMAPPED_SKY_SCI_MXU FITS image Sky on CCD\n"
00092 " GLOBAL_SKY_SPECTRUM_MXU FITS table Global sky spectrum\n"
00093 " OBJECT_TABLE_SCI_MXU FITS table Positions of detected objects\n"
00094 "\n"
00095 " Only if the sky-alignment of the wavelength solution is requested:\n"
00096 " SKY_SHIFTS_LONG_SCI_MXU FITS table Sky lines offsets (LSS-like data)\n"
00097 " or SKY_SHIFTS_SLIT_SCI_MXU FITS table Sky lines offsets (MOS-like data)\n"
00098 " DISP_COEFF_SCI_MXU FITS table Upgraded dispersion coefficients\n"
00099 " WAVELENGTH_MAP_SCI_MXU FITS image Upgraded wavelength map\n\n";
00100
00101 #define fors_extract_exit(message) \
00102 { \
00103 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
00104 cpl_free(exptime); \
00105 cpl_free(instrume); \
00106 cpl_image_delete(dummy); \
00107 cpl_image_delete(mapped); \
00108 cpl_image_delete(mapped_sky); \
00109 cpl_image_delete(mapped_cleaned); \
00110 cpl_image_delete(skylocalmap); \
00111 cpl_image_delete(skymap); \
00112 cpl_image_delete(smapped); \
00113 cpl_table_delete(offsets); \
00114 cpl_table_delete(global); \
00115 cpl_table_delete(sky); \
00116 cpl_image_delete(bias); \
00117 cpl_image_delete(spectra); \
00118 cpl_image_delete(coordinate); \
00119 cpl_image_delete(norm_flat); \
00120 cpl_image_delete(rainbow); \
00121 cpl_image_delete(rectified); \
00122 cpl_image_delete(wavemap); \
00123 cpl_propertylist_delete(header); \
00124 cpl_propertylist_delete(save_header); \
00125 cpl_table_delete(grism_table); \
00126 cpl_table_delete(idscoeff); \
00127 cpl_table_delete(maskslits); \
00128 cpl_table_delete(overscans); \
00129 cpl_table_delete(polytraces); \
00130 cpl_table_delete(slits); \
00131 cpl_table_delete(wavelengths); \
00132 cpl_vector_delete(lines); \
00133 cpl_msg_indent_less(); \
00134 return -1; \
00135 }
00136
00137
00138 #define fors_extract_exit_memcheck(message) \
00139 { \
00140 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
00141 printf("free exptime (%p)\n", exptime); \
00142 cpl_free(exptime); \
00143 printf("free instrume (%p)\n", instrume); \
00144 cpl_free(instrume); \
00145 printf("free dummy (%p)\n", dummy); \
00146 cpl_image_delete(dummy); \
00147 printf("free mapped (%p)\n", mapped); \
00148 cpl_image_delete(mapped); \
00149 printf("free mapped_cleaned (%p)\n", mapped_cleaned); \
00150 cpl_image_delete(mapped_cleaned); \
00151 printf("free mapped_sky (%p)\n", mapped_sky); \
00152 cpl_image_delete(mapped_sky); \
00153 printf("free skylocalmap (%p)\n", skylocalmap); \
00154 cpl_image_delete(skylocalmap); \
00155 printf("free skymap (%p)\n", skymap); \
00156 cpl_image_delete(skymap); \
00157 printf("free smapped (%p)\n", smapped); \
00158 cpl_image_delete(smapped); \
00159 printf("free offsets (%p)\n", offsets); \
00160 cpl_table_delete(offsets); \
00161 printf("free global (%p)\n", global); \
00162 cpl_table_delete(global); \
00163 printf("free sky (%p)\n", sky); \
00164 cpl_table_delete(sky); \
00165 printf("free bias (%p)\n", bias); \
00166 cpl_image_delete(bias); \
00167 printf("free spectra (%p)\n", spectra); \
00168 cpl_image_delete(spectra); \
00169 printf("free coordinate (%p)\n", coordinate); \
00170 cpl_image_delete(coordinate); \
00171 printf("free norm_flat (%p)\n", norm_flat); \
00172 cpl_image_delete(norm_flat); \
00173 printf("free rainbow (%p)\n", rainbow); \
00174 cpl_image_delete(rainbow); \
00175 printf("free rectified (%p)\n", rectified); \
00176 cpl_image_delete(rectified); \
00177 printf("free wavemap (%p)\n", wavemap); \
00178 cpl_image_delete(wavemap); \
00179 printf("free header (%p)\n", header); \
00180 cpl_propertylist_delete(header); \
00181 printf("free save_header (%p)\n", save_header); \
00182 cpl_propertylist_delete(save_header); \
00183 printf("free grism_table (%p)\n", grism_table); \
00184 cpl_table_delete(grism_table); \
00185 printf("free idscoeff (%p)\n", idscoeff); \
00186 cpl_table_delete(idscoeff); \
00187 printf("free maskslits (%p)\n", maskslits); \
00188 cpl_table_delete(maskslits); \
00189 printf("free overscans (%p)\n", overscans); \
00190 cpl_table_delete(overscans); \
00191 printf("free polytraces (%p)\n", polytraces); \
00192 cpl_table_delete(polytraces); \
00193 printf("free slits (%p)\n", slits); \
00194 cpl_table_delete(slits); \
00195 printf("free wavelengths (%p)\n", wavelengths); \
00196 cpl_table_delete(wavelengths); \
00197 printf("free lines (%p)\n", lines); \
00198 cpl_vector_delete(lines); \
00199 cpl_msg_indent_less(); \
00200 return 0; \
00201 }
00202
00203
00215 int cpl_plugin_get_info(cpl_pluginlist *list)
00216 {
00217 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00218 cpl_plugin *plugin = &recipe->interface;
00219
00220 cpl_plugin_init(plugin,
00221 CPL_PLUGIN_API,
00222 FORS_BINARY_VERSION,
00223 CPL_PLUGIN_TYPE_RECIPE,
00224 "fors_extract",
00225 "Extraction of scientific spectra",
00226 fors_extract_description,
00227 "Carlo Izzo",
00228 PACKAGE_BUGREPORT,
00229 "This file is currently part of the FORS Instrument Pipeline\n"
00230 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00231 "This program is free software; you can redistribute it and/or modify\n"
00232 "it under the terms of the GNU General Public License as published by\n"
00233 "the Free Software Foundation; either version 2 of the License, or\n"
00234 "(at your option) any later version.\n\n"
00235 "This program is distributed in the hope that it will be useful,\n"
00236 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00237 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00238 "GNU General Public License for more details.\n\n"
00239 "You should have received a copy of the GNU General Public License\n"
00240 "along with this program; if not, write to the Free Software Foundation,\n"
00241 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00242 fors_extract_create,
00243 fors_extract_exec,
00244 fors_extract_destroy);
00245
00246 cpl_pluginlist_append(list, plugin);
00247
00248 return 0;
00249 }
00250
00251
00262 static int fors_extract_create(cpl_plugin *plugin)
00263 {
00264 cpl_recipe *recipe;
00265 cpl_parameter *p;
00266
00267
00268
00269
00270
00271
00272 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00273 recipe = (cpl_recipe *)plugin;
00274 else
00275 return -1;
00276
00277
00278
00279
00280
00281 recipe->parameters = cpl_parameterlist_new();
00282
00283
00284
00285
00286
00287
00288 p = cpl_parameter_new_value("fors.fors_extract.dispersion",
00289 CPL_TYPE_DOUBLE,
00290 "Resampling step (Angstrom/pixel)",
00291 "fors.fors_extract",
00292 0.0);
00293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00294 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00295 cpl_parameterlist_append(recipe->parameters, p);
00296
00297
00298
00299
00300
00301 p = cpl_parameter_new_value("fors.fors_extract.skyalign",
00302 CPL_TYPE_INT,
00303 "Polynomial order for sky lines alignment, "
00304 "or -1 to avoid alignment",
00305 "fors.fors_extract",
00306 0);
00307 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign");
00308 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00309 cpl_parameterlist_append(recipe->parameters, p);
00310
00311
00312
00313
00314
00315 p = cpl_parameter_new_value("fors.fors_extract.wcolumn",
00316 CPL_TYPE_STRING,
00317 "Name of sky line catalog table column "
00318 "with wavelengths",
00319 "fors.fors_extract",
00320 "WLEN");
00321 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00322 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00323 cpl_parameterlist_append(recipe->parameters, p);
00324
00325
00326
00327
00328
00329 p = cpl_parameter_new_value("fors.fors_extract.startwavelength",
00330 CPL_TYPE_DOUBLE,
00331 "Start wavelength in spectral extraction",
00332 "fors.fors_extract",
00333 0.0);
00334 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00335 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00336 cpl_parameterlist_append(recipe->parameters, p);
00337
00338
00339
00340
00341
00342 p = cpl_parameter_new_value("fors.fors_extract.endwavelength",
00343 CPL_TYPE_DOUBLE,
00344 "End wavelength in spectral extraction",
00345 "fors.fors_extract",
00346 0.0);
00347 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00348 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00349 cpl_parameterlist_append(recipe->parameters, p);
00350
00351
00352
00353
00354
00355 p = cpl_parameter_new_value("fors.fors_extract.flux",
00356 CPL_TYPE_BOOL,
00357 "Apply flux conservation",
00358 "fors.fors_extract",
00359 TRUE);
00360 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00361 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00362 cpl_parameterlist_append(recipe->parameters, p);
00363
00364
00365
00366
00367
00368 p = cpl_parameter_new_value("fors.fors_extract.flatfield",
00369 CPL_TYPE_BOOL,
00370 "Apply flat field",
00371 "fors.fors_extract",
00372 FALSE);
00373 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flatfield");
00374 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00375 cpl_parameterlist_append(recipe->parameters, p);
00376
00377
00378
00379
00380
00381 p = cpl_parameter_new_value("fors.fors_extract.skyglobal",
00382 CPL_TYPE_BOOL,
00383 "Subtract global sky spectrum from CCD",
00384 "fors.fors_extract",
00385 FALSE);
00386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyglobal");
00387 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00388 cpl_parameterlist_append(recipe->parameters, p);
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 p = cpl_parameter_new_value("fors.fors_extract.skymedian",
00408 CPL_TYPE_BOOL,
00409 "Sky subtraction from extracted slit spectra",
00410 "fors.fors_extract",
00411 FALSE);
00412 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skymedian");
00413 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00414 cpl_parameterlist_append(recipe->parameters, p);
00415
00416
00417
00418
00419
00420 p = cpl_parameter_new_value("fors.fors_extract.skylocal",
00421 CPL_TYPE_BOOL,
00422 "Sky subtraction from CCD slit spectra",
00423 "fors.fors_extract",
00424 TRUE);
00425 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skylocal");
00426 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00427 cpl_parameterlist_append(recipe->parameters, p);
00428
00429
00430
00431
00432
00433 p = cpl_parameter_new_value("fors.fors_extract.cosmics",
00434 CPL_TYPE_BOOL,
00435 "Eliminate cosmic rays hits (only if global "
00436 "sky subtraction is also requested)",
00437 "fors.fors_extract",
00438 FALSE);
00439 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics");
00440 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00441 cpl_parameterlist_append(recipe->parameters, p);
00442
00443
00444
00445
00446
00447 p = cpl_parameter_new_value("fors.fors_extract.slit_margin",
00448 CPL_TYPE_INT,
00449 "Number of pixels to exclude at each slit "
00450 "in object detection and extraction",
00451 "fors.fors_extract",
00452 3);
00453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_margin");
00454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00455 cpl_parameterlist_append(recipe->parameters, p);
00456
00457
00458
00459
00460
00461 p = cpl_parameter_new_value("fors.fors_extract.ext_radius",
00462 CPL_TYPE_INT,
00463 "Maximum extraction radius for detected "
00464 "objects (pixel)",
00465 "fors.fors_extract",
00466 6);
00467 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_radius");
00468 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00469 cpl_parameterlist_append(recipe->parameters, p);
00470
00471
00472
00473
00474
00475 p = cpl_parameter_new_value("fors.fors_extract.cont_radius",
00476 CPL_TYPE_INT,
00477 "Minimum distance at which two objects "
00478 "of equal luminosity do not contaminate "
00479 "each other (pixel)",
00480 "fors.fors_extract",
00481 0);
00482 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cont_radius");
00483 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00484 cpl_parameterlist_append(recipe->parameters, p);
00485
00486
00487
00488
00489
00490 p = cpl_parameter_new_value("fors.fors_extract.ext_mode",
00491 CPL_TYPE_INT,
00492 "Object extraction method: 0 = aperture, "
00493 "1 = Horne optimal extraction",
00494 "fors.fors_extract",
00495 1);
00496 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_mode");
00497 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00498 cpl_parameterlist_append(recipe->parameters, p);
00499
00500
00501
00502
00503
00504 p = cpl_parameter_new_value("fors.fors_extract.time_normalise",
00505 CPL_TYPE_BOOL,
00506 "Normalise output spectra by the exposure time",
00507 "fors.fors_extract",
00508 TRUE);
00509 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "time_normalise");
00510 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00511 cpl_parameterlist_append(recipe->parameters, p);
00512
00513 return 0;
00514 }
00515
00516
00525 static int fors_extract_exec(cpl_plugin *plugin)
00526 {
00527 cpl_recipe *recipe;
00528
00529 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00530 recipe = (cpl_recipe *)plugin;
00531 else
00532 return -1;
00533
00534 return fors_extract(recipe->parameters, recipe->frames);
00535 }
00536
00537
00546 static int fors_extract_destroy(cpl_plugin *plugin)
00547 {
00548 cpl_recipe *recipe;
00549
00550 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00551 recipe = (cpl_recipe *)plugin;
00552 else
00553 return -1;
00554
00555 cpl_parameterlist_delete(recipe->parameters);
00556
00557 return 0;
00558 }
00559
00560
00570 static int fors_extract(cpl_parameterlist *parlist, cpl_frameset *frameset)
00571 {
00572
00573 const char *recipe = "fors_extract";
00574
00575
00576
00577
00578
00579
00580 double dispersion;
00581 int skyalign;
00582 const char *wcolumn;
00583 double startwavelength;
00584 double endwavelength;
00585 int flux;
00586 int flatfield;
00587 int skyglobal;
00588 int skylocal;
00589 int skymedian;
00590 int cosmics;
00591 int slit_margin;
00592 int ext_radius;
00593 int cont_radius;
00594 int ext_mode;
00595 int time_normalise;
00596
00597
00598
00599
00600
00601
00602 cpl_imagelist *all_science;
00603 cpl_image **images;
00604
00605 cpl_image *bias = NULL;
00606 cpl_image *norm_flat = NULL;
00607 cpl_image *spectra = NULL;
00608 cpl_image *rectified = NULL;
00609 cpl_image *coordinate = NULL;
00610 cpl_image *rainbow = NULL;
00611 cpl_image *mapped = NULL;
00612 cpl_image *mapped_sky = NULL;
00613 cpl_image *mapped_cleaned = NULL;
00614 cpl_image *smapped = NULL;
00615 cpl_image *wavemap = NULL;
00616 cpl_image *skymap = NULL;
00617 cpl_image *skylocalmap = NULL;
00618 cpl_image *dummy = NULL;
00619
00620 cpl_table *grism_table = NULL;
00621 cpl_table *overscans = NULL;
00622 cpl_table *wavelengths = NULL;
00623 cpl_table *idscoeff = NULL;
00624 cpl_table *slits = NULL;
00625 cpl_table *maskslits = NULL;
00626 cpl_table *polytraces = NULL;
00627 cpl_table *offsets = NULL;
00628 cpl_table *sky = NULL;
00629 cpl_table *global = NULL;
00630
00631 cpl_vector *lines = NULL;
00632
00633 cpl_propertylist *header = NULL;
00634 cpl_propertylist *save_header = NULL;
00635
00636
00637
00638
00639
00640 char version[80];
00641 char *instrume = NULL;
00642 char *wheel4 = NULL;
00643 const char *science_tag;
00644 const char *master_norm_flat_tag;
00645 const char *disp_coeff_sky_tag;
00646 const char *wavelength_map_sky_tag;
00647 const char *reduced_science_tag;
00648 const char *reduced_sky_tag;
00649 const char *reduced_error_tag;
00650 const char *mapped_science_tag;
00651 const char *unmapped_science_tag;
00652 const char *mapped_science_sky_tag;
00653 const char *mapped_sky_tag;
00654 const char *unmapped_sky_tag;
00655 const char *global_sky_spectrum_tag;
00656 const char *object_table_tag;
00657 const char *skylines_offsets_tag;
00658 const char *global_distortion_tag = "MASTER_DISTORTION_TABLE";
00659 char *coll;
00660 int mxu, mos, lss;
00661 int nscience;
00662 double *exptime = NULL;
00663 double alltime;
00664 double mean_rms;
00665 int nlines;
00666 int rebin;
00667 double *line;
00668 int nx, ny;
00669 double reference;
00670 double gain;
00671 double ron;
00672 int standard;
00673 int highres;
00674 int narrow = 0;
00675 int i;
00676
00677
00678 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00679
00680 cpl_msg_set_indentation(2);
00681
00682
00683
00684
00685
00686 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00687 cpl_msg_indent_more();
00688
00689 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00690 fors_extract_exit("Too many in input: GRISM_TABLE");
00691
00692 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00693
00694 dispersion = dfs_get_parameter_double(parlist,
00695 "fors.fors_extract.dispersion", grism_table);
00696
00697 if (dispersion <= 0.0)
00698 fors_extract_exit("Invalid resampling step");
00699
00700 skyalign = dfs_get_parameter_int(parlist,
00701 "fors.fors_extract.skyalign", NULL);
00702
00703 if (skyalign > 2)
00704 fors_extract_exit("Max polynomial degree for sky alignment is 2");
00705
00706 wcolumn = dfs_get_parameter_string(parlist,
00707 "fors.fors_extract.wcolumn", NULL);
00708
00709 startwavelength = dfs_get_parameter_double(parlist,
00710 "fors.fors_extract.startwavelength", grism_table);
00711 if (startwavelength < 3000.0 || startwavelength > 13000.0)
00712 fors_extract_exit("Invalid wavelength");
00713
00714 endwavelength = dfs_get_parameter_double(parlist,
00715 "fors.fors_extract.endwavelength", grism_table);
00716 if (endwavelength < 3000.0 || endwavelength > 13000.0)
00717 fors_extract_exit("Invalid wavelength");
00718
00719 if (endwavelength - startwavelength <= 0.0)
00720 fors_extract_exit("Invalid wavelength interval");
00721
00722 flux = dfs_get_parameter_bool(parlist, "fors.fors_extract.flux", NULL);
00723
00724 flatfield = dfs_get_parameter_bool(parlist, "fors.fors_extract.flatfield",
00725 NULL);
00726
00727 skyglobal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skyglobal",
00728 NULL);
00729 skylocal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skylocal",
00730 NULL);
00731 skymedian = dfs_get_parameter_bool(parlist, "fors.fors_extract.skymedian",
00732 NULL);
00733
00734
00735
00736
00737
00738 if (skylocal && skyglobal)
00739 fors_extract_exit("Cannot apply both local and global sky subtraction");
00740
00741 if (skylocal && skymedian)
00742 fors_extract_exit("Cannot apply sky subtraction both on extracted "
00743 "and non-extracted spectra");
00744
00745 cosmics = dfs_get_parameter_bool(parlist,
00746 "fors.fors_extract.cosmics", NULL);
00747
00748 if (cosmics)
00749 if (!(skyglobal || skylocal))
00750 fors_extract_exit("Cosmic rays correction requires "
00751 "either skylocal=true or skyglobal=true");
00752
00753 slit_margin = dfs_get_parameter_int(parlist,
00754 "fors.fors_extract.slit_margin",
00755 NULL);
00756 if (slit_margin < 0)
00757 fors_extract_exit("Value must be zero or positive");
00758
00759 ext_radius = dfs_get_parameter_int(parlist,
00760 "fors.fors_extract.ext_radius",
00761 NULL);
00762 if (ext_radius < 0)
00763 fors_extract_exit("Value must be zero or positive");
00764
00765 cont_radius = dfs_get_parameter_int(parlist,
00766 "fors.fors_extract.cont_radius",
00767 NULL);
00768 if (cont_radius < 0)
00769 fors_extract_exit("Value must be zero or positive");
00770
00771 ext_mode = dfs_get_parameter_int(parlist, "fors.fors_extract.ext_mode",
00772 NULL);
00773 if (ext_mode < 0 || ext_mode > 1)
00774 fors_extract_exit("Invalid object extraction mode");
00775
00776 time_normalise = dfs_get_parameter_bool(parlist,
00777 "fors.fors_extract.time_normalise", NULL);
00778
00779 cpl_table_delete(grism_table); grism_table = NULL;
00780
00781 if (cpl_error_get_code())
00782 fors_extract_exit("Failure getting the configuration parameters");
00783
00784
00785
00786
00787
00788
00789 cpl_msg_indent_less();
00790 cpl_msg_info(recipe, "Check input set-of-frames:");
00791 cpl_msg_indent_more();
00792
00793 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00794 cpl_msg_warning(cpl_func,"Input frames are not from the same grism");
00795
00796 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00797 cpl_msg_warning(cpl_func,"Input frames are not from the same filter");
00798
00799 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00800 cpl_msg_warning(cpl_func,"Input frames are not from the same chip");
00801
00802 mxu = cpl_frameset_count_tags(frameset, "SCIENCE_MXU");
00803 mos = cpl_frameset_count_tags(frameset, "SCIENCE_MOS");
00804 lss = cpl_frameset_count_tags(frameset, "SCIENCE_LSS");
00805 standard = 0;
00806
00807 if (mxu + mos + lss == 0) {
00808 mxu = cpl_frameset_count_tags(frameset, "STANDARD_MXU");
00809 mos = cpl_frameset_count_tags(frameset, "STANDARD_MOS");
00810 lss = cpl_frameset_count_tags(frameset, "STANDARD_LSS");
00811 standard = 1;
00812 }
00813
00814 if (mxu + mos + lss == 0)
00815 fors_extract_exit("Missing input scientific frame");
00816
00817 nscience = mxu + mos + lss;
00818
00819 if (mxu && mxu < nscience)
00820 fors_extract_exit("Input scientific frames must be of the same type");
00821
00822 if (mos && mos < nscience)
00823 fors_extract_exit("Input scientific frames must be of the same type");
00824
00825 if (lss && lss < nscience)
00826 fors_extract_exit("Input scientific frames must be of the same type");
00827
00828 if (mxu) {
00829 if (standard) {
00830 cpl_msg_info(recipe, "MXU data found");
00831 science_tag = "STANDARD_MXU";
00832 reduced_science_tag = "REDUCED_STD_MXU";
00833 unmapped_science_tag = "UNMAPPED_STD_MXU";
00834 mapped_science_tag = "MAPPED_STD_MXU";
00835 mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
00836 skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MXU";
00837 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MXU";
00838 disp_coeff_sky_tag = "DISP_COEFF_STD_MXU";
00839 mapped_sky_tag = "MAPPED_SKY_STD_MXU";
00840 unmapped_sky_tag = "UNMAPPED_SKY_STD_MXU";
00841 object_table_tag = "OBJECT_TABLE_STD_MXU";
00842 reduced_sky_tag = "REDUCED_SKY_STD_MXU";
00843 reduced_error_tag = "REDUCED_ERROR_STD_MXU";
00844 }
00845 else {
00846 cpl_msg_info(recipe, "MXU data found");
00847 science_tag = "SCIENCE_MXU";
00848 reduced_science_tag = "REDUCED_SCI_MXU";
00849 unmapped_science_tag = "UNMAPPED_SCI_MXU";
00850 mapped_science_tag = "MAPPED_SCI_MXU";
00851 mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
00852 skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MXU";
00853 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MXU";
00854 disp_coeff_sky_tag = "DISP_COEFF_SCI_MXU";
00855 mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
00856 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MXU";
00857 object_table_tag = "OBJECT_TABLE_SCI_MXU";
00858 reduced_sky_tag = "REDUCED_SKY_SCI_MXU";
00859 reduced_error_tag = "REDUCED_ERROR_SCI_MXU";
00860 }
00861
00862 master_norm_flat_tag = "MASTER_NORM_FLAT_MXU";
00863 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MXU";
00864
00865 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
00866 master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MXU";
00867 }
00868 }
00869
00870 if (lss) {
00871
00872 if (cosmics && !skyglobal)
00873 fors_extract_exit("Cosmic rays correction for LSS "
00874 "data requires --skyglobal=true");
00875
00876 cpl_msg_info(recipe, "LSS data found");
00877
00878 if (standard) {
00879 science_tag = "STANDARD_LSS";
00880 reduced_science_tag = "REDUCED_STD_LSS";
00881 unmapped_science_tag = "UNMAPPED_STD_LSS";
00882 mapped_science_tag = "MAPPED_STD_LSS";
00883 mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
00884 skylines_offsets_tag = "SKY_SHIFTS_LONG_STD_LSS";
00885 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_LSS";
00886 disp_coeff_sky_tag = "DISP_COEFF_STD_LSS";
00887 mapped_sky_tag = "MAPPED_SKY_STD_LSS";
00888 unmapped_sky_tag = "UNMAPPED_SKY_STD_LSS";
00889 object_table_tag = "OBJECT_TABLE_STD_LSS";
00890 reduced_sky_tag = "REDUCED_SKY_STD_LSS";
00891 reduced_error_tag = "REDUCED_ERROR_STD_LSS";
00892 }
00893 else {
00894 science_tag = "SCIENCE_LSS";
00895 reduced_science_tag = "REDUCED_SCI_LSS";
00896 unmapped_science_tag = "UNMAPPED_SCI_LSS";
00897 mapped_science_tag = "MAPPED_SCI_LSS";
00898 mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
00899 skylines_offsets_tag = "SKY_SHIFTS_LONG_SCI_LSS";
00900 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_LSS";
00901 disp_coeff_sky_tag = "DISP_COEFF_SCI_LSS";
00902 mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
00903 unmapped_sky_tag = "UNMAPPED_SKY_SCI_LSS";
00904 object_table_tag = "OBJECT_TABLE_SCI_LSS";
00905 reduced_sky_tag = "REDUCED_SKY_SCI_LSS";
00906 reduced_error_tag = "REDUCED_ERROR_SCI_LSS";
00907 }
00908
00909 master_norm_flat_tag = "MASTER_NORM_FLAT_LSS";
00910 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_LSS";
00911 }
00912
00913 if (mos) {
00914 cpl_msg_info(recipe, "MOS data found");
00915 if (standard) {
00916 science_tag = "STANDARD_MOS";
00917 reduced_science_tag = "REDUCED_STD_MOS";
00918 unmapped_science_tag = "UNMAPPED_STD_MOS";
00919 mapped_science_tag = "MAPPED_STD_MOS";
00920 mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
00921 skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MOS";
00922 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MOS";
00923 disp_coeff_sky_tag = "DISP_COEFF_STD_MOS";
00924 mapped_sky_tag = "MAPPED_SKY_STD_MOS";
00925 unmapped_sky_tag = "UNMAPPED_SKY_STD_MOS";
00926 object_table_tag = "OBJECT_TABLE_STD_MOS";
00927 reduced_sky_tag = "REDUCED_SKY_STD_MOS";
00928 reduced_error_tag = "REDUCED_ERROR_STD_MOS";
00929 }
00930 else {
00931 science_tag = "SCIENCE_MOS";
00932 reduced_science_tag = "REDUCED_SCI_MOS";
00933 unmapped_science_tag = "UNMAPPED_SCI_MOS";
00934 mapped_science_tag = "MAPPED_SCI_MOS";
00935 mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
00936 skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MOS";
00937 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MOS";
00938 disp_coeff_sky_tag = "DISP_COEFF_SCI_MOS";
00939 mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
00940 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MOS";
00941 object_table_tag = "OBJECT_TABLE_SCI_MOS";
00942 reduced_sky_tag = "REDUCED_SKY_SCI_MOS";
00943 reduced_error_tag = "REDUCED_ERROR_SCI_MOS";
00944 }
00945
00946 master_norm_flat_tag = "MASTER_NORM_FLAT_MOS";
00947 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MOS";
00948
00949 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
00950 master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MOS";
00951 }
00952 }
00953
00954 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0)
00955 fors_extract_exit("Missing required input: MASTER_BIAS");
00956
00957 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
00958 fors_extract_exit("Too many in input: MASTER_BIAS");
00959
00960 if (skyalign >= 0)
00961 if (cpl_frameset_count_tags(frameset, "MASTER_SKYLINECAT") > 1)
00962 fors_extract_exit("Too many in input: MASTER_SKYLINECAT");
00963
00964 if (cpl_frameset_count_tags(frameset, global_distortion_tag) == 0)
00965 fors_extract_exit("Missing required input: MASTER_DISTORTION_TABLE");
00966
00967 if (cpl_frameset_count_tags(frameset, global_distortion_tag) > 1)
00968 fors_extract_exit("Too many in input: MASTER_DISTORTION_TABLE");
00969
00970 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
00971 if (flatfield) {
00972 cpl_msg_error(recipe, "Too many in input: %s",
00973 master_norm_flat_tag);
00974 fors_extract_exit(NULL);
00975 }
00976 else {
00977 cpl_msg_warning(recipe, "%s in input are ignored, "
00978 "since flat field correction was not requested",
00979 master_norm_flat_tag);
00980 }
00981 }
00982
00983 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
00984 if (!flatfield) {
00985 cpl_msg_warning(recipe, "%s in input is ignored, "
00986 "since flat field correction was not requested",
00987 master_norm_flat_tag);
00988 }
00989 }
00990
00991 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
00992 if (flatfield) {
00993 cpl_msg_error(recipe, "Flat field correction was requested, "
00994 "but no %s are found in input",
00995 master_norm_flat_tag);
00996 fors_extract_exit(NULL);
00997 }
00998 }
00999
01000 cpl_msg_indent_less();
01001
01002
01003
01004
01005
01006
01007 exptime = cpl_calloc(nscience, sizeof(double));
01008
01009 if (nscience > 1) {
01010
01011 cpl_msg_info(recipe, "Load %d scientific frames and median them...",
01012 nscience);
01013 cpl_msg_indent_more();
01014
01015 all_science = cpl_imagelist_new();
01016
01017 header = dfs_load_header(frameset, science_tag, 0);
01018
01019 if (header == NULL)
01020 fors_extract_exit("Cannot load scientific frame header");
01021
01022 alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
01023
01024 if (cpl_error_get_code() != CPL_ERROR_NONE)
01025 fors_extract_exit("Missing keyword EXPTIME in scientific "
01026 "frame header");
01027
01028 cpl_propertylist_delete(header); header = NULL;
01029
01030 cpl_msg_info(recipe, "Scientific frame 1 exposure time: %.2f s",
01031 exptime[0]);
01032
01033 for (i = 1; i < nscience; i++) {
01034
01035 header = dfs_load_header(frameset, NULL, 0);
01036
01037 if (header == NULL)
01038 fors_extract_exit("Cannot load scientific frame header");
01039
01040 exptime[i] = cpl_propertylist_get_double(header, "EXPTIME");
01041
01042 alltime += exptime[i];
01043
01044 if (cpl_error_get_code() != CPL_ERROR_NONE)
01045 fors_extract_exit("Missing keyword EXPTIME in scientific "
01046 "frame header");
01047
01048 cpl_propertylist_delete(header); header = NULL;
01049
01050 cpl_msg_info(recipe, "Scientific frame %d exposure time: %.2f s",
01051 i+1, exptime[i]);
01052 }
01053
01054 spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
01055
01056 if (spectra == NULL)
01057 fors_extract_exit("Cannot load scientific frame");
01058
01059 cpl_image_divide_scalar(spectra, exptime[0]);
01060 cpl_imagelist_set(all_science, spectra, 0); spectra = NULL;
01061
01062 for (i = 1; i < nscience; i++) {
01063
01064 spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01065
01066 if (spectra) {
01067 cpl_image_divide_scalar(spectra, exptime[i]);
01068 cpl_imagelist_set(all_science, spectra, i); spectra = NULL;
01069 }
01070 else
01071 fors_extract_exit("Cannot load scientific frame");
01072
01073 }
01074
01075 spectra = cpl_imagelist_collapse_median_create(all_science);
01076 cpl_image_multiply_scalar(spectra, alltime);
01077
01078 cpl_imagelist_delete(all_science);
01079 }
01080 else {
01081 cpl_msg_info(recipe, "Load scientific exposure...");
01082 cpl_msg_indent_more();
01083
01084 header = dfs_load_header(frameset, science_tag, 0);
01085
01086 if (header == NULL)
01087 fors_extract_exit("Cannot load scientific frame header");
01088
01089
01090
01091
01092
01093
01094 wheel4 = (char *)cpl_propertylist_get_string(header,
01095 "ESO INS OPTI9 TYPE");
01096 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01097 fors_extract_exit("Missing ESO INS OPTI9 TYPE in flat header");
01098 }
01099
01100 if (strcmp("FILT", wheel4) == 0) {
01101 wheel4 = (char *)cpl_propertylist_get_string(header,
01102 "ESO INS OPTI9 NAME");
01103 cpl_msg_error(recipe, "Unsupported filter: %s", wheel4);
01104 fors_extract_exit(NULL);
01105 }
01106
01107
01108 alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
01109
01110 if (cpl_error_get_code() != CPL_ERROR_NONE)
01111 fors_extract_exit("Missing keyword EXPTIME in scientific "
01112 "frame header");
01113
01114 cpl_propertylist_delete(header); header = NULL;
01115
01116 cpl_msg_info(recipe, "Scientific frame exposure time: %.2f s",
01117 exptime[0]);
01118
01119 spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
01120 }
01121
01122 if (spectra == NULL)
01123 fors_extract_exit("Cannot load scientific frame");
01124
01125 cpl_free(exptime); exptime = NULL;
01126
01127 cpl_msg_indent_less();
01128
01129
01130
01131
01132
01133
01134
01135 header = dfs_load_header(frameset, science_tag, 0);
01136
01137 if (header == NULL)
01138 fors_extract_exit("Cannot load scientific frame header");
01139
01140 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
01141 if (instrume == NULL)
01142 fors_extract_exit("Missing keyword INSTRUME in sientific header");
01143 instrume = cpl_strdup(instrume);
01144
01145 if (instrume[4] == '1')
01146 snprintf(version, 80, "%s/%s", "fors1", VERSION);
01147 if (instrume[4] == '2')
01148 snprintf(version, 80, "%s/%s", "fors2", VERSION);
01149
01150 cpl_free(instrume); instrume = NULL;
01151
01152 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
01153
01154 if (cpl_error_get_code() != CPL_ERROR_NONE)
01155 fors_extract_exit("Missing keyword ESO INS GRIS1 WLEN in scientific "
01156 "frame header");
01157
01158 if (reference < 3000.0)
01159 reference *= 10;
01160
01161 if (reference < 3000.0 || reference > 13000.0) {
01162 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
01163 "keyword ESO INS GRIS1 WLEN in scientific frame header",
01164 reference);
01165 fors_extract_exit(NULL);
01166 }
01167
01168 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
01169
01170 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
01171
01172 if (cpl_error_get_code() != CPL_ERROR_NONE)
01173 fors_extract_exit("Missing keyword ESO DET WIN1 BINX in scientific "
01174 "frame header");
01175
01176 if (rebin != 1) {
01177 dispersion *= rebin;
01178 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
01179 "resampling step used is %f A/pixel", rebin,
01180 dispersion);
01181 }
01182
01183 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
01184
01185 if (cpl_error_get_code() != CPL_ERROR_NONE)
01186 fors_extract_exit("Missing keyword ESO DET OUT1 CONAD in scientific "
01187 "frame header");
01188
01189 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
01190
01191 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
01192
01193 if (cpl_error_get_code() != CPL_ERROR_NONE)
01194 fors_extract_exit("Missing keyword ESO DET OUT1 RON in scientific "
01195 "frame header");
01196
01197 ron /= gain;
01198
01199 cpl_msg_info(recipe, "The read-out-noise is: %.2f ADU", ron);
01200
01201 coll = (char *)cpl_propertylist_get_string(header, "ESO INS COLL NAME");
01202
01203 if (cpl_error_get_code() != CPL_ERROR_NONE)
01204 fors_extract_exit("Missing keyword ESO INS COLL NAME in scientific "
01205 "frame header");
01206
01207 cpl_msg_info(recipe, "The collimator is : %s", coll);
01208
01209 if (strcmp(coll, "COLL_HR") == 0)
01210 fors_extract_exit("HR collimator is not yet supported by this recipe");
01211
01212
01213 if (mos)
01214 {
01215 int nslits_out_det;
01216 maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
01217 }
01218 else if (lss)
01219 maskslits = mos_load_slits_fors_lss(header);
01220 else
01221 maskslits = mos_load_slits_fors_mxu(header);
01222
01223 if (lss) {
01224 if (skylocal) {
01225 if (cosmics)
01226 fors_extract_exit("Cosmic rays correction for LSS "
01227 "data requires --skyglobal=true");
01228 skymedian = skylocal;
01229 skylocal = 0;
01230 }
01231 }
01232
01233 global = dfs_load_table(frameset, global_distortion_tag, 1);
01234 if (global == NULL)
01235 fors_extract_exit("Cannot load global distortion table");
01236
01237
01238
01239
01240
01241
01242
01243
01244 cpl_msg_info(recipe, "Remove the master bias...");
01245
01246 bias = dfs_load_image(frameset, "MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
01247
01248 if (bias == NULL)
01249 fors_extract_exit("Cannot load master bias");
01250
01251 overscans = mos_load_overscans_vimos(header, 1);
01252 cpl_propertylist_delete(header); header = NULL;
01253 dummy = mos_remove_bias(spectra, bias, overscans);
01254 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
01255 cpl_image_delete(bias); bias = NULL;
01256 cpl_table_delete(overscans); overscans = NULL;
01257
01258 if (spectra == NULL)
01259 fors_extract_exit("Cannot remove bias from scientific frame");
01260
01261 nx = cpl_image_get_size_x(spectra);
01262 ny = cpl_image_get_size_y(spectra);
01263
01264 if (ny == 400 && nx == 2048)
01265 narrow = 1;
01266
01267 if (narrow) {
01268 ny = 2048;
01269 dummy = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01270 cpl_image_copy(dummy, spectra, 1, 825);
01271 if (cpl_error_get_code())
01272 fors_extract_exit("Problems expanding scientific image");
01273 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
01274 }
01275
01276 cpl_msg_indent_less();
01277 cpl_msg_info(recipe, "Load normalised flat field (if present)...");
01278 cpl_msg_indent_more();
01279
01280 if (flatfield) {
01281
01282 norm_flat = dfs_load_image(frameset, master_norm_flat_tag,
01283 CPL_TYPE_FLOAT, 0, 1);
01284
01285 if (norm_flat) {
01286 if (narrow) {
01287 dummy = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01288 cpl_image_copy(dummy, norm_flat, 1, 825);
01289 if (cpl_error_get_code())
01290 fors_extract_exit("Problems expanding flat image");
01291 cpl_image_delete(norm_flat); norm_flat = dummy; dummy = NULL;
01292 }
01293 cpl_msg_info(recipe, "Apply flat field correction...");
01294 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
01295 cpl_msg_error(recipe, "Failure of flat field correction: %s",
01296 cpl_error_get_message());
01297 fors_extract_exit(NULL);
01298 }
01299 cpl_image_delete(norm_flat); norm_flat = NULL;
01300 }
01301 else {
01302 cpl_msg_error(recipe, "Cannot load input %s for flat field "
01303 "correction", master_norm_flat_tag);
01304 fors_extract_exit(NULL);
01305 }
01306
01307 }
01308
01309
01310 if (skyalign >= 0) {
01311 cpl_msg_indent_less();
01312 cpl_msg_info(recipe, "Load input sky line catalog...");
01313 cpl_msg_indent_more();
01314
01315 wavelengths = dfs_load_table(frameset, "MASTER_SKYLINECAT", 1);
01316
01317 if (wavelengths) {
01318
01319
01320
01321
01322
01323 nlines = cpl_table_get_nrow(wavelengths);
01324
01325 if (nlines == 0)
01326 fors_extract_exit("Empty input sky line catalog");
01327
01328 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
01329 cpl_msg_error(recipe, "Missing column %s in input line "
01330 "catalog table", wcolumn);
01331 fors_extract_exit(NULL);
01332 }
01333
01334 line = cpl_malloc(nlines * sizeof(double));
01335
01336 for (i = 0; i < nlines; i++)
01337 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
01338
01339 cpl_table_delete(wavelengths); wavelengths = NULL;
01340
01341 lines = cpl_vector_wrap(nlines, line);
01342 }
01343 else {
01344 cpl_msg_info(recipe, "No sky line catalog found in input - fine!");
01345 }
01346 }
01347
01348
01349
01350
01351
01352
01353
01354 slits = mos_build_slit_location(global, maskslits, ny);
01355 if (slits == NULL)
01356 fors_extract_exit("Cannot create slits location table");
01357
01358
01359
01360
01361
01362
01363 polytraces = mos_build_curv_coeff(global, maskslits, slits);
01364 if (polytraces == NULL)
01365 fors_extract_exit("Cannot create spectral curvature table");
01366
01367 cpl_table_delete(maskslits); maskslits = NULL;
01368
01369 cpl_msg_indent_less();
01370 cpl_msg_info(recipe, "Processing scientific spectra...");
01371 cpl_msg_indent_more();
01372
01373
01374
01375
01376
01377
01378 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01379
01380 smapped = mos_spatial_calibration(spectra, slits, polytraces, reference,
01381 startwavelength, endwavelength,
01382 dispersion, flux, coordinate);
01383
01384
01385
01386
01387
01388
01389 idscoeff = mos_build_disp_coeff(global, slits);
01390 if (idscoeff == NULL)
01391 fors_extract_exit("Cannot create wavelength calibration table");
01392
01393 cpl_table_delete(global); global = NULL;
01394
01395
01396
01397
01398
01399
01400
01401 rainbow = mos_map_idscoeff(idscoeff, nx, reference, startwavelength,
01402 endwavelength);
01403
01404 if (dispersion > 1.0)
01405 highres = 0;
01406 else
01407 highres = 1;
01408
01409 if (skyalign >= 0) {
01410 if (skyalign) {
01411 cpl_msg_info(recipe, "Align wavelength solution to reference "
01412 "skylines applying %d order residual fit...", skyalign);
01413 }
01414 else {
01415 cpl_msg_info(recipe, "Align wavelength solution to reference "
01416 "skylines applying median offset...");
01417 }
01418
01419 if (lss) {
01420 offsets = mos_wavelength_align_lss(smapped, reference,
01421 startwavelength, endwavelength,
01422 idscoeff, lines, highres,
01423 skyalign, rainbow, 4);
01424 }
01425 else {
01426 offsets = mos_wavelength_align(smapped, slits, reference,
01427 startwavelength, endwavelength,
01428 idscoeff, lines, highres, skyalign,
01429 rainbow, 4);
01430 }
01431
01432 cpl_vector_delete(lines); lines = NULL;
01433
01434 if (offsets) {
01435 if (standard)
01436 cpl_msg_warning(recipe, "Alignment of the wavelength solution "
01437 "to reference sky lines may be unreliable in "
01438 "this case!");
01439
01440 if (dfs_save_table(frameset, offsets, skylines_offsets_tag, NULL,
01441 parlist, recipe, version))
01442 fors_extract_exit(NULL);
01443
01444 cpl_table_delete(offsets); offsets = NULL;
01445 }
01446 else {
01447 cpl_msg_warning(recipe, "Alignment of the wavelength solution "
01448 "to reference sky lines could not be done!");
01449 skyalign = -1;
01450 }
01451
01452 }
01453
01454 wavemap = mos_map_wavelengths(coordinate, rainbow, slits,
01455 polytraces, reference,
01456 startwavelength, endwavelength,
01457 dispersion);
01458
01459 cpl_image_delete(rainbow); rainbow = NULL;
01460 cpl_image_delete(coordinate); coordinate = NULL;
01461
01462
01463
01464
01465
01466
01467 mapped_sky = mos_wavelength_calibration(smapped, reference,
01468 startwavelength, endwavelength,
01469 dispersion, idscoeff, flux);
01470
01471 cpl_msg_indent_less();
01472 cpl_msg_info(recipe, "Check applied wavelength against skylines...");
01473 cpl_msg_indent_more();
01474
01475 mean_rms = mos_distortions_rms(mapped_sky, NULL, startwavelength,
01476 dispersion, 6, highres);
01477
01478 cpl_msg_info(recipe, "Mean residual: %f", mean_rms);
01479
01480 mean_rms = cpl_table_get_column_mean(idscoeff, "error");
01481
01482 header = cpl_propertylist_new();
01483 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01484 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01485 cpl_propertylist_update_double(header, "CRVAL1",
01486 startwavelength + dispersion/2);
01487 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01488
01489
01490 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01491 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01492 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01493 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01494 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01495 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01496
01497 if (time_normalise) {
01498 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
01499 if (dfs_save_image(frameset, dummy, mapped_science_sky_tag, header,
01500 parlist, recipe, version))
01501 fors_extract_exit(NULL);
01502 cpl_image_delete(dummy); dummy = NULL;
01503 }
01504 else {
01505 if (dfs_save_image(frameset, mapped_sky, mapped_science_sky_tag,
01506 header, parlist, recipe, version))
01507 fors_extract_exit(NULL);
01508 }
01509
01510
01511 if (skyglobal == 0 && skymedian == 0 && skylocal == 0) {
01512 cpl_image_delete(mapped_sky); mapped_sky = NULL;
01513 }
01514
01515 if (skyglobal || skylocal) {
01516
01517 cpl_msg_indent_less();
01518
01519 if (skyglobal) {
01520 cpl_msg_info(recipe, "Global sky determination...");
01521 cpl_msg_indent_more();
01522 skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01523 sky = mos_sky_map_super(spectra, wavemap, dispersion,
01524 2.0, 50, skymap);
01525 if (sky)
01526 cpl_image_subtract(spectra, skymap);
01527 else
01528 cpl_image_delete(skymap); skymap = NULL;
01529 }
01530 else {
01531 cpl_msg_info(recipe, "Local sky determination...");
01532 cpl_msg_indent_more();
01533 skymap = mos_subtract_sky(spectra, slits, polytraces, reference,
01534 startwavelength, endwavelength, dispersion);
01535 }
01536
01537 if (skymap) {
01538 if (skyglobal) {
01539 if (time_normalise)
01540 cpl_table_divide_scalar(sky, "sky", alltime);
01541 if (dfs_save_table(frameset, sky, global_sky_spectrum_tag,
01542 NULL, parlist, recipe, version))
01543 fors_extract_exit(NULL);
01544
01545 cpl_table_delete(sky); sky = NULL;
01546 }
01547
01548 save_header = dfs_load_header(frameset, science_tag, 0);
01549
01550 if (time_normalise)
01551 cpl_image_divide_scalar(skymap, alltime);
01552 if (dfs_save_image(frameset, skymap, unmapped_sky_tag,
01553 save_header, parlist, recipe, version))
01554 fors_extract_exit(NULL);
01555
01556 cpl_image_delete(skymap); skymap = NULL;
01557
01558 if (dfs_save_image(frameset, spectra, unmapped_science_tag,
01559 save_header, parlist, recipe, version))
01560 fors_extract_exit(NULL);
01561
01562 cpl_propertylist_delete(save_header); save_header = NULL;
01563
01564 if (cosmics) {
01565 cpl_msg_info(recipe, "Removing cosmic rays...");
01566 mos_clean_cosmics(spectra, gain, -1., -1.);
01567 }
01568
01569
01570
01571
01572
01573
01574 cpl_image_delete(smapped); smapped = NULL;
01575
01576 if (lss) {
01577 smapped = cpl_image_duplicate(spectra);
01578 }
01579 else {
01580 smapped = mos_spatial_calibration(spectra, slits, polytraces,
01581 reference, startwavelength,
01582 endwavelength, dispersion,
01583 flux, NULL);
01584 }
01585 }
01586 else {
01587 cpl_msg_warning(recipe, "Sky subtraction failure");
01588 if (cosmics)
01589 cpl_msg_warning(recipe, "Cosmic rays removal not performed!");
01590 cosmics = skylocal = skyglobal = 0;
01591 }
01592 }
01593
01594 cpl_image_delete(spectra); spectra = NULL;
01595 cpl_table_delete(polytraces); polytraces = NULL;
01596
01597 if (skyalign >= 0) {
01598 save_header = dfs_load_header(frameset, science_tag, 0);
01599 if (dfs_save_image(frameset, wavemap, wavelength_map_sky_tag,
01600 save_header, parlist, recipe, version))
01601 fors_extract_exit(NULL);
01602 cpl_propertylist_delete(save_header); save_header = NULL;
01603 }
01604
01605 cpl_image_delete(wavemap); wavemap = NULL;
01606
01607 mapped = mos_wavelength_calibration(smapped, reference,
01608 startwavelength, endwavelength,
01609 dispersion, idscoeff, flux);
01610
01611 cpl_image_delete(smapped); smapped = NULL;
01612
01613
01614 if (skymedian) {
01615 cpl_msg_indent_less();
01616 cpl_msg_info(recipe, "Local sky determination...");
01617 cpl_msg_indent_more();
01618
01619
01620
01621 skylocalmap = mos_sky_local_old(mapped, slits);
01622 cpl_image_subtract(mapped, skylocalmap);
01623
01624
01625
01626
01627
01628 cpl_image_delete(skylocalmap); skylocalmap = NULL;
01629 }
01630
01631
01632 if (skyglobal || skymedian || skylocal) {
01633
01634 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
01635
01636 cpl_image_delete(mapped_sky); mapped_sky = NULL;
01637
01638 if (time_normalise) {
01639 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
01640 if (dfs_save_image(frameset, dummy, mapped_sky_tag, header,
01641 parlist, recipe, version))
01642 fors_extract_exit(NULL);
01643 cpl_image_delete(dummy); dummy = NULL;
01644 }
01645 else {
01646 if (dfs_save_image(frameset, skylocalmap, mapped_sky_tag, header,
01647 parlist, recipe, version))
01648 fors_extract_exit(NULL);
01649 }
01650
01651 cpl_msg_indent_less();
01652 cpl_msg_info(recipe, "Object detection...");
01653 cpl_msg_indent_more();
01654
01655 if (cosmics || nscience > 1) {
01656 dummy = mos_detect_objects(mapped, slits, slit_margin, ext_radius,
01657 cont_radius);
01658 }
01659 else {
01660 mapped_cleaned = cpl_image_duplicate(mapped);
01661 mos_clean_cosmics(mapped_cleaned, gain, -1., -1.);
01662 dummy = mos_detect_objects(mapped_cleaned, slits, slit_margin,
01663 ext_radius, cont_radius);
01664
01665 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
01666 }
01667
01668 cpl_image_delete(dummy); dummy = NULL;
01669
01670 if (dfs_save_table(frameset, slits, object_table_tag, NULL, parlist,
01671 recipe, version))
01672 fors_extract_exit(NULL);
01673
01674 cpl_msg_indent_less();
01675 cpl_msg_info(recipe, "Object extraction...");
01676 cpl_msg_indent_more();
01677
01678
01679
01680 images = mos_extract_objects(mapped, NULL, skylocalmap, slits,
01681 ext_mode, ron, gain, 1);
01682
01683 cpl_image_delete(skylocalmap); skylocalmap = NULL;
01684
01685 if (images) {
01686 if (time_normalise)
01687 cpl_image_divide_scalar(images[0], alltime);
01688 if (dfs_save_image(frameset, images[0], reduced_science_tag, header,
01689 parlist, recipe, version))
01690 fors_extract_exit(NULL);
01691 cpl_image_delete(images[0]);
01692
01693 if (time_normalise)
01694 cpl_image_divide_scalar(images[1], alltime);
01695 if (dfs_save_image(frameset, images[1], reduced_sky_tag, header,
01696 parlist, recipe, version))
01697 fors_extract_exit(NULL);
01698 cpl_image_delete(images[1]);
01699
01700 if (time_normalise)
01701 cpl_image_divide_scalar(images[2], alltime);
01702 if (dfs_save_image(frameset, images[2], reduced_error_tag, header,
01703 parlist, recipe, version))
01704 fors_extract_exit(NULL);
01705 cpl_image_delete(images[2]);
01706
01707 cpl_free(images);
01708 }
01709 else {
01710 cpl_msg_warning(recipe, "No objects found: the products "
01711 "%s, %s, and %s are not created",
01712 reduced_science_tag, reduced_sky_tag,
01713 reduced_error_tag);
01714 }
01715
01716 }
01717
01718 cpl_table_delete(slits); slits = NULL;
01719
01720 if (skyalign >= 0) {
01721 if (dfs_save_table(frameset, idscoeff, disp_coeff_sky_tag, NULL,
01722 parlist, recipe, version))
01723 fors_extract_exit(NULL);
01724 }
01725
01726 cpl_table_delete(idscoeff); idscoeff = NULL;
01727
01728
01729 if (skyglobal || skymedian || skylocal) {
01730 if (time_normalise)
01731 cpl_image_divide_scalar(mapped, alltime);
01732 if (dfs_save_image(frameset, mapped, mapped_science_tag, header,
01733 parlist, recipe, version))
01734 fors_extract_exit(NULL);
01735 }
01736
01737 cpl_image_delete(mapped); mapped = NULL;
01738 cpl_propertylist_delete(header); header = NULL;
01739
01740 if (cpl_error_get_code()) {
01741 cpl_msg_error(cpl_error_get_where(), "%s", cpl_error_get_message());
01742 fors_extract_exit(NULL);
01743 }
01744
01745 return 0;
01746 }