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 (message) 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 (message) 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 if (dfs_files_dont_exist(frameset))
00683 fors_extract_exit(NULL);
00684
00685
00686
00687
00688
00689 cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00690 cpl_msg_indent_more();
00691
00692 if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00693 fors_extract_exit("Too many in input: GRISM_TABLE");
00694
00695 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00696
00697 dispersion = dfs_get_parameter_double(parlist,
00698 "fors.fors_extract.dispersion", grism_table);
00699
00700 if (dispersion <= 0.0)
00701 fors_extract_exit("Invalid resampling step");
00702
00703 skyalign = dfs_get_parameter_int(parlist,
00704 "fors.fors_extract.skyalign", NULL);
00705
00706 if (skyalign > 2)
00707 fors_extract_exit("Max polynomial degree for sky alignment is 2");
00708
00709 wcolumn = dfs_get_parameter_string(parlist,
00710 "fors.fors_extract.wcolumn", NULL);
00711
00712 startwavelength = dfs_get_parameter_double(parlist,
00713 "fors.fors_extract.startwavelength", grism_table);
00714 if (startwavelength < 3000.0 || startwavelength > 13000.0)
00715 fors_extract_exit("Invalid wavelength");
00716
00717 endwavelength = dfs_get_parameter_double(parlist,
00718 "fors.fors_extract.endwavelength", grism_table);
00719 if (endwavelength < 3000.0 || endwavelength > 13000.0)
00720 fors_extract_exit("Invalid wavelength");
00721
00722 if (endwavelength - startwavelength <= 0.0)
00723 fors_extract_exit("Invalid wavelength interval");
00724
00725 flux = dfs_get_parameter_bool(parlist, "fors.fors_extract.flux", NULL);
00726
00727 flatfield = dfs_get_parameter_bool(parlist, "fors.fors_extract.flatfield",
00728 NULL);
00729
00730 skyglobal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skyglobal",
00731 NULL);
00732 skylocal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skylocal",
00733 NULL);
00734 skymedian = dfs_get_parameter_bool(parlist, "fors.fors_extract.skymedian",
00735 NULL);
00736
00737
00738
00739
00740
00741 if (skylocal && skyglobal)
00742 fors_extract_exit("Cannot apply both local and global sky subtraction");
00743
00744 if (skylocal && skymedian)
00745 fors_extract_exit("Cannot apply sky subtraction both on extracted "
00746 "and non-extracted spectra");
00747
00748 cosmics = dfs_get_parameter_bool(parlist,
00749 "fors.fors_extract.cosmics", NULL);
00750
00751 if (cosmics)
00752 if (!(skyglobal || skylocal))
00753 fors_extract_exit("Cosmic rays correction requires "
00754 "either skylocal=true or skyglobal=true");
00755
00756 slit_margin = dfs_get_parameter_int(parlist,
00757 "fors.fors_extract.slit_margin",
00758 NULL);
00759 if (slit_margin < 0)
00760 fors_extract_exit("Value must be zero or positive");
00761
00762 ext_radius = dfs_get_parameter_int(parlist,
00763 "fors.fors_extract.ext_radius",
00764 NULL);
00765 if (ext_radius < 0)
00766 fors_extract_exit("Value must be zero or positive");
00767
00768 cont_radius = dfs_get_parameter_int(parlist,
00769 "fors.fors_extract.cont_radius",
00770 NULL);
00771 if (cont_radius < 0)
00772 fors_extract_exit("Value must be zero or positive");
00773
00774 ext_mode = dfs_get_parameter_int(parlist, "fors.fors_extract.ext_mode",
00775 NULL);
00776 if (ext_mode < 0 || ext_mode > 1)
00777 fors_extract_exit("Invalid object extraction mode");
00778
00779 time_normalise = dfs_get_parameter_bool(parlist,
00780 "fors.fors_extract.time_normalise", NULL);
00781
00782 cpl_table_delete(grism_table); grism_table = NULL;
00783
00784 if (cpl_error_get_code())
00785 fors_extract_exit("Failure getting the configuration parameters");
00786
00787
00788
00789
00790
00791
00792 cpl_msg_indent_less();
00793 cpl_msg_info(recipe, "Check input set-of-frames:");
00794 cpl_msg_indent_more();
00795
00796 if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
00797 fors_extract_exit("Input frames are not from the same grism");
00798
00799 if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
00800 fors_extract_exit("Input frames are not from the same filter");
00801
00802 if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
00803 fors_extract_exit("Input frames are not from the same chip");
00804
00805 mxu = cpl_frameset_count_tags(frameset, "SCIENCE_MXU");
00806 mos = cpl_frameset_count_tags(frameset, "SCIENCE_MOS");
00807 lss = cpl_frameset_count_tags(frameset, "SCIENCE_LSS");
00808 standard = 0;
00809
00810 if (mxu + mos + lss == 0) {
00811 mxu = cpl_frameset_count_tags(frameset, "STANDARD_MXU");
00812 mos = cpl_frameset_count_tags(frameset, "STANDARD_MOS");
00813 lss = cpl_frameset_count_tags(frameset, "STANDARD_LSS");
00814 standard = 1;
00815 }
00816
00817 if (mxu + mos + lss == 0)
00818 fors_extract_exit("Missing input scientific frame");
00819
00820 nscience = mxu + mos + lss;
00821
00822 if (mxu && mxu < nscience)
00823 fors_extract_exit("Input scientific frames must be of the same type");
00824
00825 if (mos && mos < nscience)
00826 fors_extract_exit("Input scientific frames must be of the same type");
00827
00828 if (lss && lss < nscience)
00829 fors_extract_exit("Input scientific frames must be of the same type");
00830
00831 if (mxu) {
00832 if (standard) {
00833 cpl_msg_info(recipe, "MXU data found");
00834 science_tag = "STANDARD_MXU";
00835 reduced_science_tag = "REDUCED_STD_MXU";
00836 unmapped_science_tag = "UNMAPPED_STD_MXU";
00837 mapped_science_tag = "MAPPED_STD_MXU";
00838 mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
00839 skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MXU";
00840 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MXU";
00841 disp_coeff_sky_tag = "DISP_COEFF_STD_MXU";
00842 mapped_sky_tag = "MAPPED_SKY_STD_MXU";
00843 unmapped_sky_tag = "UNMAPPED_SKY_STD_MXU";
00844 object_table_tag = "OBJECT_TABLE_STD_MXU";
00845 reduced_sky_tag = "REDUCED_SKY_STD_MXU";
00846 reduced_error_tag = "REDUCED_ERROR_STD_MXU";
00847 }
00848 else {
00849 cpl_msg_info(recipe, "MXU data found");
00850 science_tag = "SCIENCE_MXU";
00851 reduced_science_tag = "REDUCED_SCI_MXU";
00852 unmapped_science_tag = "UNMAPPED_SCI_MXU";
00853 mapped_science_tag = "MAPPED_SCI_MXU";
00854 mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
00855 skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MXU";
00856 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MXU";
00857 disp_coeff_sky_tag = "DISP_COEFF_SCI_MXU";
00858 mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
00859 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MXU";
00860 object_table_tag = "OBJECT_TABLE_SCI_MXU";
00861 reduced_sky_tag = "REDUCED_SKY_SCI_MXU";
00862 reduced_error_tag = "REDUCED_ERROR_SCI_MXU";
00863 }
00864
00865 master_norm_flat_tag = "MASTER_NORM_FLAT_MXU";
00866 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MXU";
00867
00868 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
00869 master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MXU";
00870 }
00871 }
00872
00873 if (lss) {
00874
00875 if (cosmics && !skyglobal)
00876 fors_extract_exit("Cosmic rays correction for LSS "
00877 "data requires --skyglobal=true");
00878
00879 cpl_msg_info(recipe, "LSS data found");
00880
00881 if (standard) {
00882 science_tag = "STANDARD_LSS";
00883 reduced_science_tag = "REDUCED_STD_LSS";
00884 unmapped_science_tag = "UNMAPPED_STD_LSS";
00885 mapped_science_tag = "MAPPED_STD_LSS";
00886 mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
00887 skylines_offsets_tag = "SKY_SHIFTS_LONG_STD_LSS";
00888 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_LSS";
00889 disp_coeff_sky_tag = "DISP_COEFF_STD_LSS";
00890 mapped_sky_tag = "MAPPED_SKY_STD_LSS";
00891 unmapped_sky_tag = "UNMAPPED_SKY_STD_LSS";
00892 object_table_tag = "OBJECT_TABLE_STD_LSS";
00893 reduced_sky_tag = "REDUCED_SKY_STD_LSS";
00894 reduced_error_tag = "REDUCED_ERROR_STD_LSS";
00895 }
00896 else {
00897 science_tag = "SCIENCE_LSS";
00898 reduced_science_tag = "REDUCED_SCI_LSS";
00899 unmapped_science_tag = "UNMAPPED_SCI_LSS";
00900 mapped_science_tag = "MAPPED_SCI_LSS";
00901 mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
00902 skylines_offsets_tag = "SKY_SHIFTS_LONG_SCI_LSS";
00903 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_LSS";
00904 disp_coeff_sky_tag = "DISP_COEFF_SCI_LSS";
00905 mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
00906 unmapped_sky_tag = "UNMAPPED_SKY_SCI_LSS";
00907 object_table_tag = "OBJECT_TABLE_SCI_LSS";
00908 reduced_sky_tag = "REDUCED_SKY_SCI_LSS";
00909 reduced_error_tag = "REDUCED_ERROR_SCI_LSS";
00910 }
00911
00912 master_norm_flat_tag = "MASTER_NORM_FLAT_LSS";
00913 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_LSS";
00914 }
00915
00916 if (mos) {
00917 cpl_msg_info(recipe, "MOS data found");
00918 if (standard) {
00919 science_tag = "STANDARD_MOS";
00920 reduced_science_tag = "REDUCED_STD_MOS";
00921 unmapped_science_tag = "UNMAPPED_STD_MOS";
00922 mapped_science_tag = "MAPPED_STD_MOS";
00923 mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
00924 skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MOS";
00925 wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MOS";
00926 disp_coeff_sky_tag = "DISP_COEFF_STD_MOS";
00927 mapped_sky_tag = "MAPPED_SKY_STD_MOS";
00928 unmapped_sky_tag = "UNMAPPED_SKY_STD_MOS";
00929 object_table_tag = "OBJECT_TABLE_STD_MOS";
00930 reduced_sky_tag = "REDUCED_SKY_STD_MOS";
00931 reduced_error_tag = "REDUCED_ERROR_STD_MOS";
00932 }
00933 else {
00934 science_tag = "SCIENCE_MOS";
00935 reduced_science_tag = "REDUCED_SCI_MOS";
00936 unmapped_science_tag = "UNMAPPED_SCI_MOS";
00937 mapped_science_tag = "MAPPED_SCI_MOS";
00938 mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
00939 skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MOS";
00940 wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MOS";
00941 disp_coeff_sky_tag = "DISP_COEFF_SCI_MOS";
00942 mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
00943 unmapped_sky_tag = "UNMAPPED_SKY_SCI_MOS";
00944 object_table_tag = "OBJECT_TABLE_SCI_MOS";
00945 reduced_sky_tag = "REDUCED_SKY_SCI_MOS";
00946 reduced_error_tag = "REDUCED_ERROR_SCI_MOS";
00947 }
00948
00949 master_norm_flat_tag = "MASTER_NORM_FLAT_MOS";
00950 global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MOS";
00951
00952 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
00953 master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MOS";
00954 }
00955 }
00956
00957 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0)
00958 fors_extract_exit("Missing required input: MASTER_BIAS");
00959
00960 if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
00961 fors_extract_exit("Too many in input: MASTER_BIAS");
00962
00963 if (skyalign >= 0)
00964 if (cpl_frameset_count_tags(frameset, "MASTER_SKYLINECAT") > 1)
00965 fors_extract_exit("Too many in input: MASTER_SKYLINECAT");
00966
00967 if (cpl_frameset_count_tags(frameset, global_distortion_tag) == 0)
00968 fors_extract_exit("Missing required input: MASTER_DISTORTION_TABLE");
00969
00970 if (cpl_frameset_count_tags(frameset, global_distortion_tag) > 1)
00971 fors_extract_exit("Too many in input: MASTER_DISTORTION_TABLE");
00972
00973 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
00974 if (flatfield) {
00975 cpl_msg_error(recipe, "Too many in input: %s",
00976 master_norm_flat_tag);
00977 fors_extract_exit(NULL);
00978 }
00979 else {
00980 cpl_msg_warning(recipe, "%s in input are ignored, "
00981 "since flat field correction was not requested",
00982 master_norm_flat_tag);
00983 }
00984 }
00985
00986 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
00987 if (!flatfield) {
00988 cpl_msg_warning(recipe, "%s in input is ignored, "
00989 "since flat field correction was not requested",
00990 master_norm_flat_tag);
00991 }
00992 }
00993
00994 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
00995 if (flatfield) {
00996 cpl_msg_error(recipe, "Flat field correction was requested, "
00997 "but no %s are found in input",
00998 master_norm_flat_tag);
00999 fors_extract_exit(NULL);
01000 }
01001 }
01002
01003 cpl_msg_indent_less();
01004
01005
01006
01007
01008
01009
01010 exptime = cpl_calloc(nscience, sizeof(double));
01011
01012 if (nscience > 1) {
01013
01014 cpl_msg_info(recipe, "Load %d scientific frames and median them...",
01015 nscience);
01016 cpl_msg_indent_more();
01017
01018 all_science = cpl_imagelist_new();
01019
01020 header = dfs_load_header(frameset, science_tag, 0);
01021
01022 if (header == NULL)
01023 fors_extract_exit("Cannot load scientific frame header");
01024
01025 alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
01026
01027 if (cpl_error_get_code() != CPL_ERROR_NONE)
01028 fors_extract_exit("Missing keyword EXPTIME in scientific "
01029 "frame header");
01030
01031 cpl_propertylist_delete(header); header = NULL;
01032
01033 cpl_msg_info(recipe, "Scientific frame 1 exposure time: %.2f s",
01034 exptime[0]);
01035
01036 for (i = 1; i < nscience; i++) {
01037
01038 header = dfs_load_header(frameset, NULL, 0);
01039
01040 if (header == NULL)
01041 fors_extract_exit("Cannot load scientific frame header");
01042
01043 exptime[i] = cpl_propertylist_get_double(header, "EXPTIME");
01044
01045 alltime += exptime[i];
01046
01047 if (cpl_error_get_code() != CPL_ERROR_NONE)
01048 fors_extract_exit("Missing keyword EXPTIME in scientific "
01049 "frame header");
01050
01051 cpl_propertylist_delete(header); header = NULL;
01052
01053 cpl_msg_info(recipe, "Scientific frame %d exposure time: %.2f s",
01054 i+1, exptime[i]);
01055 }
01056
01057 spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
01058
01059 if (spectra == NULL)
01060 fors_extract_exit("Cannot load scientific frame");
01061
01062 cpl_image_divide_scalar(spectra, exptime[0]);
01063 cpl_imagelist_set(all_science, spectra, 0); spectra = NULL;
01064
01065 for (i = 1; i < nscience; i++) {
01066
01067 spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
01068
01069 if (spectra) {
01070 cpl_image_divide_scalar(spectra, exptime[i]);
01071 cpl_imagelist_set(all_science, spectra, i); spectra = NULL;
01072 }
01073 else
01074 fors_extract_exit("Cannot load scientific frame");
01075
01076 }
01077
01078 spectra = cpl_imagelist_collapse_median_create(all_science);
01079 cpl_image_multiply_scalar(spectra, alltime);
01080
01081 cpl_imagelist_delete(all_science);
01082 }
01083 else {
01084 cpl_msg_info(recipe, "Load scientific exposure...");
01085 cpl_msg_indent_more();
01086
01087 header = dfs_load_header(frameset, science_tag, 0);
01088
01089 if (header == NULL)
01090 fors_extract_exit("Cannot load scientific frame header");
01091
01092
01093
01094
01095
01096
01097 wheel4 = (char *)cpl_propertylist_get_string(header,
01098 "ESO INS OPTI9 TYPE");
01099 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01100 fors_extract_exit("Missing ESO INS OPTI9 TYPE in flat header");
01101 }
01102
01103 if (strcmp("FILT", wheel4) == 0) {
01104 wheel4 = (char *)cpl_propertylist_get_string(header,
01105 "ESO INS OPTI9 NAME");
01106 cpl_msg_error(recipe, "Unsupported filter: %s", wheel4);
01107 fors_extract_exit(NULL);
01108 }
01109
01110
01111 alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
01112
01113 if (cpl_error_get_code() != CPL_ERROR_NONE)
01114 fors_extract_exit("Missing keyword EXPTIME in scientific "
01115 "frame header");
01116
01117 cpl_propertylist_delete(header); header = NULL;
01118
01119 cpl_msg_info(recipe, "Scientific frame exposure time: %.2f s",
01120 exptime[0]);
01121
01122 spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
01123 }
01124
01125 if (spectra == NULL)
01126 fors_extract_exit("Cannot load scientific frame");
01127
01128 cpl_free(exptime); exptime = NULL;
01129
01130 cpl_msg_indent_less();
01131
01132
01133
01134
01135
01136
01137
01138 header = dfs_load_header(frameset, science_tag, 0);
01139
01140 if (header == NULL)
01141 fors_extract_exit("Cannot load scientific frame header");
01142
01143 instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
01144 if (instrume == NULL)
01145 fors_extract_exit("Missing keyword INSTRUME in sientific header");
01146 instrume = cpl_strdup(instrume);
01147
01148 if (instrume[4] == '1')
01149 snprintf(version, 80, "%s/%s", "fors1", VERSION);
01150 if (instrume[4] == '2')
01151 snprintf(version, 80, "%s/%s", "fors2", VERSION);
01152
01153 cpl_free(instrume); instrume = NULL;
01154
01155 reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
01156
01157 if (cpl_error_get_code() != CPL_ERROR_NONE)
01158 fors_extract_exit("Missing keyword ESO INS GRIS1 WLEN in scientific "
01159 "frame header");
01160
01161 if (reference < 3000.0)
01162 reference *= 10;
01163
01164 if (reference < 3000.0 || reference > 13000.0) {
01165 cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
01166 "keyword ESO INS GRIS1 WLEN in scientific frame header",
01167 reference);
01168 fors_extract_exit(NULL);
01169 }
01170
01171 cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
01172
01173 rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
01174
01175 if (cpl_error_get_code() != CPL_ERROR_NONE)
01176 fors_extract_exit("Missing keyword ESO DET WIN1 BINX in scientific "
01177 "frame header");
01178
01179 if (rebin != 1) {
01180 dispersion *= rebin;
01181 cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
01182 "resampling step used is %f A/pixel", rebin,
01183 dispersion);
01184 }
01185
01186 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
01187
01188 if (cpl_error_get_code() != CPL_ERROR_NONE)
01189 fors_extract_exit("Missing keyword ESO DET OUT1 CONAD in scientific "
01190 "frame header");
01191
01192 cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
01193
01194 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
01195
01196 if (cpl_error_get_code() != CPL_ERROR_NONE)
01197 fors_extract_exit("Missing keyword ESO DET OUT1 RON in scientific "
01198 "frame header");
01199
01200 ron /= gain;
01201
01202 cpl_msg_info(recipe, "The read-out-noise is: %.2f ADU", ron);
01203
01204 coll = (char *)cpl_propertylist_get_string(header, "ESO INS COLL NAME");
01205
01206 if (cpl_error_get_code() != CPL_ERROR_NONE)
01207 fors_extract_exit("Missing keyword ESO INS COLL NAME in scientific "
01208 "frame header");
01209
01210 cpl_msg_info(recipe, "The collimator is : %s", coll);
01211
01212 if (strcmp(coll, "COLL_HR") == 0)
01213 fors_extract_exit("HR collimator is not yet supported by this recipe");
01214
01215
01216 if (mos)
01217 maskslits = mos_load_slits_fors_mos(header);
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 images = mos_extract_objects(mapped, skylocalmap, slits,
01679 ext_mode, ron, gain, 1);
01680
01681 cpl_image_delete(skylocalmap); skylocalmap = NULL;
01682
01683 if (images) {
01684 if (time_normalise)
01685 cpl_image_divide_scalar(images[0], alltime);
01686 if (dfs_save_image(frameset, images[0], reduced_science_tag, header,
01687 parlist, recipe, version))
01688 fors_extract_exit(NULL);
01689 cpl_image_delete(images[0]);
01690
01691 if (time_normalise)
01692 cpl_image_divide_scalar(images[1], alltime);
01693 if (dfs_save_image(frameset, images[1], reduced_sky_tag, header,
01694 parlist, recipe, version))
01695 fors_extract_exit(NULL);
01696 cpl_image_delete(images[1]);
01697
01698 if (time_normalise)
01699 cpl_image_divide_scalar(images[2], alltime);
01700 if (dfs_save_image(frameset, images[2], reduced_error_tag, header,
01701 parlist, recipe, version))
01702 fors_extract_exit(NULL);
01703 cpl_image_delete(images[2]);
01704
01705 cpl_free(images);
01706 }
01707 else {
01708 cpl_msg_warning(recipe, "No objects found: the products "
01709 "%s, %s, and %s are not created",
01710 reduced_science_tag, reduced_sky_tag,
01711 reduced_error_tag);
01712 }
01713
01714 }
01715
01716 cpl_table_delete(slits); slits = NULL;
01717
01718 if (skyalign >= 0) {
01719 if (dfs_save_table(frameset, idscoeff, disp_coeff_sky_tag, NULL,
01720 parlist, recipe, version))
01721 fors_extract_exit(NULL);
01722 }
01723
01724 cpl_table_delete(idscoeff); idscoeff = NULL;
01725
01726
01727 if (skyglobal || skymedian || skylocal) {
01728 if (time_normalise)
01729 cpl_image_divide_scalar(mapped, alltime);
01730 if (dfs_save_image(frameset, mapped, mapped_science_tag, header,
01731 parlist, recipe, version))
01732 fors_extract_exit(NULL);
01733 }
01734
01735 cpl_image_delete(mapped); mapped = NULL;
01736 cpl_propertylist_delete(header); header = NULL;
01737
01738 if (cpl_error_get_code()) {
01739 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
01740 fors_extract_exit(NULL);
01741 }
01742
01743 return 0;
01744 }