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 <math.h>
00033 #include <string.h>
00034 #include <vimos_science_impl.h>
00035 #include <cpl.h>
00036 #include <moses.h>
00037 #include <fors_stack.h>
00038 #include <fors_tools.h>
00039 #include <fors_dfs.h>
00040 #include <fors_qc.h>
00041
00042 static int vimos_science_create(cpl_plugin *);
00043 static int vimos_science_exec(cpl_plugin *);
00044 static int vimos_science_destroy(cpl_plugin *);
00045 static int vimos_science(cpl_parameterlist *, cpl_frameset *);
00046
00047 static char vimos_science_description[] =
00048 "This recipe is used to reduce scientific spectra using the extraction\n"
00049 "mask and the products created by the recipe vimos_calib. The spectra are\n"
00050 "bias subtracted, flat fielded (if a normalised flat field is specified)\n"
00051 "and remapped eliminating the optical distortions. The wavelength calibration\n"
00052 "can be optionally upgraded using a number of sky lines: if no sky lines\n"
00053 "catalog of wavelengths is specified, an internal one is used instead.\n"
00054 "If the alignment to the sky lines is performed, the input dispersion\n"
00055 "coefficients table is upgraded and saved to disk, and a new CCD wavelengths\n"
00056 "map is created. A grism table (typically depending on the grism used)\n"
00057 "may also be specified: this table contains a default recipe parameter\n"
00058 "setting to control the way spectra are extracted for a specific instrument\n"
00059 "mode, as it is used for automatic run of the pipeline on Paranal and in\n"
00060 "Garching. If this table is specified, it will modify the default recipe\n"
00061 "parameter setting, with the exception of those parameters which have been\n"
00062 "explicitly modifyed on the command line. If a grism table is not specified,\n"
00063 "the input recipe parameters values will always be read from the command\n"
00064 "line, or from an esorex configuration file if present, or from their\n"
00065 "generic default values (that are rarely meaningful).\n"
00066 "MOS_SLIT_LOCATION and MOS_CURV_COEFF tables are not (yet) expected for\n"
00067 "long-slit-like data.\n"
00068 "Only in case of a standard star exposure input, the atmospheric extinction\n"
00069 "table and a table with the physical fluxes of the observed standard star\n"
00070 "must be specified in input.\n\n"
00071 "Input files:\n\n"
00072 " DO category: Type: Explanation: Required:\n"
00073 " MOS_SCIENCE Raw Scientific exposure Y\n"
00074 " or MOS_STANDARD Raw Standard star exposure Y\n"
00075 "\n"
00076 " MASTER_BIAS Calib Master bias Y\n"
00077 " SKY_LINE_CATALOG Calib Sky lines catalog .\n"
00078 " MOS_MASTER_SCREEN_FLAT Calib Normalised flat field .\n"
00079 " MOS_DISP_COEFF Calib Inverse dispersion Y\n"
00080 " MOS_CURV_COEFF Calib Spectral curvature Y\n"
00081 " MOS_SLIT_LOCATION Calib Slits positions table Y\n"
00082 " GRISM_TABLE Calib Grism table .\n"
00083 "\n"
00084 " In case MOS_STANDARD is specified in input,\n"
00085 "\n"
00086 " EXTINCT_TABLE Calib Atmospheric extinction Y\n"
00087 " STD_FLUX_TABLE Calib Standard star flux Y\n"
00088 "\n"
00089 "Output files:\n\n"
00090 " DO category: Data type: Explanation:\n"
00091 " MOS_SCIENCE_REDUCED FITS image Extracted scientific spectra\n"
00092 " or MOS_STANDARD_REDUCED FITS image Extracted standard star spectrum\n"
00093 " MOS_SKY_REDUCED FITS image Extracted sky spectra\n"
00094 " MOS_ERROR_REDUCED FITS image Errors on extracted spectra\n"
00095 "\n"
00096 " MOS_UNMAPPED_SCIENCE FITS image Sky subtracted scientific spectra\n"
00097 " or MOS_UNMAPPED_STANDARD FITS image Sky subtracted standard spectrum\n"
00098 "\n"
00099 " MOS_SCIENCE_EXTRACTED FITS image Rectified scientific spectra\n"
00100 " or MOS_STANDARD_EXTRACTED FITS image Rectified standard star spectrum\n"
00101 "\n"
00102 " MOS_SCIENCE_SKY_EXTRACTED FITS image Rectified science spectra with sky\n"
00103 "or MOS_STANDARD_SKY_EXTRACTED FITS image Rectified std spectrum with sky\n"
00104 "\n"
00105 " MOS_SCIENCE_SKY FITS image Rectified sky spectra\n"
00106 " MOS_UNMAPPED_SKY FITS image Sky on CCD\n"
00107 " MOS_GLOBAL_SKY_SPECTRUM FITS table Global sky spectrum\n"
00108 " OBJECT_TABLE FITS table Positions of detected objects\n"
00109 "\n"
00110 " Only if the sky-alignment of the wavelength solution is requested:\n"
00111 " MOS_SKYLINES_OFFSETS_LONG FITS table Sky lines offsets (LSS-like data)\n"
00112 "or MOS_SKYLINES_OFFSETS_SLIT FITS table Sky lines offsets (MOS-like data)\n"
00113 " MOS_DISP_COEFF_SKY FITS table Upgraded dispersion coefficients\n"
00114 " MOS_WAVELENGTH_MAP_SKY FITS image Upgraded wavelength map\n"
00115 "\n"
00116 " Only if a MOS_STANDARD is specified in input:\n"
00117 " MOS_SPECPHOT_TABLE FITS table Efficiency and response curves\n\n";
00118
00130 int cpl_plugin_get_info(cpl_pluginlist *list)
00131 {
00132 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
00133 cpl_plugin *plugin = &recipe->interface;
00134
00135 cpl_plugin_init(plugin,
00136 CPL_PLUGIN_API,
00137 FORS_BINARY_VERSION,
00138 CPL_PLUGIN_TYPE_RECIPE,
00139 "vimos_science",
00140 "Extraction of scientific spectra",
00141 vimos_science_description,
00142 "Carlo Izzo",
00143 PACKAGE_BUGREPORT,
00144 "This file is currently part of the FORS Instrument Pipeline\n"
00145 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
00146 "This program is free software; you can redistribute it and/or modify\n"
00147 "it under the terms of the GNU General Public License as published by\n"
00148 "the Free Software Foundation; either version 2 of the License, or\n"
00149 "(at your option) any later version.\n\n"
00150 "This program is distributed in the hope that it will be useful,\n"
00151 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00152 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00153 "GNU General Public License for more details.\n\n"
00154 "You should have received a copy of the GNU General Public License\n"
00155 "along with this program; if not, write to the Free Software Foundation,\n"
00156 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
00157 vimos_science_create,
00158 vimos_science_exec,
00159 vimos_science_destroy);
00160
00161 cpl_pluginlist_append(list, plugin);
00162
00163 return 0;
00164 }
00165
00166
00177 static int vimos_science_create(cpl_plugin *plugin)
00178 {
00179 cpl_recipe *recipe;
00180 cpl_parameter *p;
00181
00182
00183
00184
00185
00186
00187 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00188 recipe = (cpl_recipe *)plugin;
00189 else
00190 return -1;
00191
00192
00193
00194
00195
00196 recipe->parameters = cpl_parameterlist_new();
00197
00198
00199
00200
00201
00202
00203 p = cpl_parameter_new_value("fors.vimos_science.dispersion",
00204 CPL_TYPE_DOUBLE,
00205 "Resampling step (Angstrom/pixel)",
00206 "fors.vimos_science",
00207 0.0);
00208 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
00209 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00210 cpl_parameterlist_append(recipe->parameters, p);
00211
00212
00213
00214
00215
00216 p = cpl_parameter_new_value("fors.vimos_science.skyalign",
00217 CPL_TYPE_INT,
00218 "Polynomial order for sky lines alignment, "
00219 "or -1 to avoid alignment",
00220 "fors.vimos_science",
00221 0);
00222 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign");
00223 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00224 cpl_parameterlist_append(recipe->parameters, p);
00225
00226
00227
00228
00229
00230 p = cpl_parameter_new_value("fors.vimos_science.wcolumn",
00231 CPL_TYPE_STRING,
00232 "Name of sky line catalog table column "
00233 "with wavelengths",
00234 "fors.vimos_science",
00235 "WLEN");
00236 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
00237 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00238 cpl_parameterlist_append(recipe->parameters, p);
00239
00240
00241
00242
00243
00244 p = cpl_parameter_new_value("fors.vimos_science.startwavelength",
00245 CPL_TYPE_DOUBLE,
00246 "Start wavelength in spectral extraction",
00247 "fors.vimos_science",
00248 0.0);
00249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
00250 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00251 cpl_parameterlist_append(recipe->parameters, p);
00252
00253
00254
00255
00256
00257 p = cpl_parameter_new_value("fors.vimos_science.endwavelength",
00258 CPL_TYPE_DOUBLE,
00259 "End wavelength in spectral extraction",
00260 "fors.vimos_science",
00261 0.0);
00262 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
00263 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00264 cpl_parameterlist_append(recipe->parameters, p);
00265
00266
00267
00268
00269
00270 p = cpl_parameter_new_value("fors.vimos_science.reference",
00271 CPL_TYPE_DOUBLE,
00272 "Reference wavelength for calibration",
00273 "fors.vimos_science",
00274 0.0);
00275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "reference");
00276 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00277 cpl_parameterlist_append(recipe->parameters, p);
00278
00279
00280
00281
00282
00283 p = cpl_parameter_new_value("fors.vimos_science.flux",
00284 CPL_TYPE_BOOL,
00285 "Apply flux conservation",
00286 "fors.vimos_science",
00287 TRUE);
00288 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00289 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00290 cpl_parameterlist_append(recipe->parameters, p);
00291
00292
00293
00294
00295
00296 p = cpl_parameter_new_value("fors.vimos_science.flatfield",
00297 CPL_TYPE_BOOL,
00298 "Apply flat field",
00299 "fors.vimos_science",
00300 TRUE);
00301 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flatfield");
00302 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00303 cpl_parameterlist_append(recipe->parameters, p);
00304
00305
00306
00307
00308
00309 p = cpl_parameter_new_value("fors.vimos_science.skyglobal",
00310 CPL_TYPE_BOOL,
00311 "Subtract global sky spectrum from CCD",
00312 "fors.vimos_science",
00313 FALSE);
00314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyglobal");
00315 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00316 cpl_parameterlist_append(recipe->parameters, p);
00317
00318
00319
00320
00321
00322 p = cpl_parameter_new_value("fors.vimos_science.skymedian",
00323 CPL_TYPE_BOOL,
00324 "Sky subtraction from extracted slit spectra",
00325 "fors.vimos_science",
00326 FALSE);
00327 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skymedian");
00328 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00329 cpl_parameterlist_append(recipe->parameters, p);
00330
00331
00332
00333
00334
00335 p = cpl_parameter_new_value("fors.vimos_science.skylocal",
00336 CPL_TYPE_BOOL,
00337 "Sky subtraction from CCD slit spectra",
00338 "fors.vimos_science",
00339 TRUE);
00340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skylocal");
00341 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00342 cpl_parameterlist_append(recipe->parameters, p);
00343
00344
00345
00346
00347
00348 p = cpl_parameter_new_value("fors.vimos_science.cosmics",
00349 CPL_TYPE_BOOL,
00350 "Eliminate cosmic rays hits (only if global "
00351 "or local sky subtraction is also requested)",
00352 "fors.vimos_science",
00353 TRUE);
00354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics");
00355 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00356 cpl_parameterlist_append(recipe->parameters, p);
00357
00358
00359
00360
00361
00362 p = cpl_parameter_new_value("fors.vimos_science.slit_margin",
00363 CPL_TYPE_INT,
00364 "Number of pixels to exclude at each slit "
00365 "in object detection and extraction",
00366 "fors.vimos_science",
00367 3);
00368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_margin");
00369 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00370 cpl_parameterlist_append(recipe->parameters, p);
00371
00372
00373
00374
00375
00376 p = cpl_parameter_new_value("fors.vimos_science.ext_radius",
00377 CPL_TYPE_INT,
00378 "Maximum extraction radius for detected "
00379 "objects (pixel)",
00380 "fors.vimos_science",
00381 6);
00382 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_radius");
00383 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00384 cpl_parameterlist_append(recipe->parameters, p);
00385
00386
00387
00388
00389
00390 p = cpl_parameter_new_value("fors.vimos_science.cont_radius",
00391 CPL_TYPE_INT,
00392 "Minimum distance at which two objects "
00393 "of equal luminosity do not contaminate "
00394 "each other (pixel)",
00395 "fors.vimos_science",
00396 0);
00397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cont_radius");
00398 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00399 cpl_parameterlist_append(recipe->parameters, p);
00400
00401
00402
00403
00404
00405 p = cpl_parameter_new_value("fors.vimos_science.ext_mode",
00406 CPL_TYPE_INT,
00407 "Object extraction method: 0 = aperture, "
00408 "1 = Horne optimal extraction",
00409 "fors.vimos_science",
00410 1);
00411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_mode");
00412 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00413 cpl_parameterlist_append(recipe->parameters, p);
00414
00415
00416
00417
00418
00419 p = cpl_parameter_new_value("fors.vimos_science.time_normalise",
00420 CPL_TYPE_BOOL,
00421 "Normalise output spectra by the exposure time",
00422 "fors.vimos_science",
00423 TRUE);
00424 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "time_normalise");
00425 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00426 cpl_parameterlist_append(recipe->parameters, p);
00427
00428
00429
00430
00431
00432 p = cpl_parameter_new_value("fors.vimos_science.anyframe",
00433 CPL_TYPE_BOOL,
00434 "Look for a standard star in any frame "
00435 "classified as MOS_STANDARD",
00436 "fors.vimos_science",
00437 FALSE);
00438 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "anyframe");
00439 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00440 cpl_parameterlist_append(recipe->parameters, p);
00441
00442
00443
00444
00445
00446
00447 p = cpl_parameter_new_value("fors.vimos_science.response",
00448 CPL_TYPE_INT,
00449 "Order of polynomial modeling the "
00450 "instrument response",
00451 "fors.vimos_science",
00452 5);
00453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "response");
00454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00455 cpl_parameterlist_append(recipe->parameters, p);
00456
00457
00458
00459
00460
00461
00462 p = cpl_parameter_new_enum("fors.vimos_science.alignment",
00463 CPL_TYPE_STRING,
00464 "Type of alignment of dithered frames, "
00465 "either to the nearest neighbour pixel "
00466 "or to fractions of pixel",
00467 "fors.vimos_science",
00468 "integer", 2,
00469 "integer", "float");
00470 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "alignment");
00471 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00472 cpl_parameterlist_append(recipe->parameters, p);
00473
00474
00475
00476
00477
00478
00479 fors_stack_define_parameters(recipe->parameters,
00480 "fors.vimos_science", "average");
00481
00482
00483
00484
00485
00486
00487 p = cpl_parameter_new_value("fors.vimos_science.fringing",
00488 CPL_TYPE_BOOL,
00489 "Apply fringing correction "
00490 "(only for dithered observations)",
00491 "fors.vimos_science",
00492 TRUE);
00493 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fringing");
00494 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00495 cpl_parameterlist_append(recipe->parameters, p);
00496
00497
00498
00499
00500
00501
00502 p = cpl_parameter_new_value("fors.vimos_science.qc",
00503 CPL_TYPE_BOOL,
00504 "Compute QC1 parameters",
00505 "fors.vimos_science",
00506 TRUE);
00507 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "qc");
00508 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00509 cpl_parameterlist_append(recipe->parameters, p);
00510
00511
00512 return 0;
00513 }
00514
00515
00524 static int vimos_science_exec(cpl_plugin *plugin)
00525 {
00526 cpl_recipe *recipe;
00527
00528 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00529 recipe = (cpl_recipe *)plugin;
00530 else
00531 return -1;
00532
00533 return vimos_science(recipe->parameters, recipe->frames);
00534 }
00535
00536
00545 static int vimos_science_destroy(cpl_plugin *plugin)
00546 {
00547 cpl_recipe *recipe;
00548
00549 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00550 recipe = (cpl_recipe *)plugin;
00551 else
00552 return -1;
00553
00554 cpl_parameterlist_delete(recipe->parameters);
00555
00556 return 0;
00557 }
00558
00559
00569 static int vimos_science(cpl_parameterlist *parlist, cpl_frameset *frameset)
00570 {
00571 const char *science_tag = "MOS_SCIENCE";
00572 int mos = cpl_frameset_count_tags(frameset, science_tag);
00573
00574 if (mos > 1) {
00575 char version[80];
00576 const char *curv_coeff_tag = "MOS_CURV_COEFF";
00577 const char *slit_location_tag = "MOS_SLIT_LOCATION";
00578 const char *disp_coeff_tag = "MOS_DISP_COEFF";
00579 const char *unmapped_science_tag = "MOS_UNMAPPED_SCIENCE";
00580 const char *mapped_science_tag = "MOS_SCIENCE_EXTRACTED";
00581 const char *object_table_tag = "OBJECT_TABLE";
00582 const char *unmapped_sky_tag = "MOS_UNMAPPED_SKY";
00583 const char *mapped_sky_tag = "MOS_SCIENCE_SKY";
00584 const char *reduced_science_tag = "MOS_SCIENCE_REDUCED";
00585 const char *reduced_sky_tag = "MOS_SKY_REDUCED";
00586 const char *reduced_error_tag = "MOS_ERROR_REDUCED";
00587 const char *stack_method;
00588 const char *alignment;
00589 double refwave;
00590 double startwavelength;
00591 double endwavelength;
00592 double dispersion;
00593 int flux;
00594 int fringing;
00595 int cosmics;
00596 int slit_margin;
00597 int ext_radius;
00598 int cont_radius;
00599 int ext_mode;
00600 int rotate = 1;
00601 int rotate_back = -1;
00602 cpl_frameset *work = cpl_frameset_duplicate(frameset);
00603 cpl_frame **mos_science = cpl_calloc(mos, sizeof(cpl_frame*));
00604 cpl_parameter *param;
00605 cpl_table *reference = NULL;
00606 cpl_table *objects = NULL;
00607 cpl_image **images = NULL;
00608 cpl_image *image = NULL;
00609 cpl_image *sky_image = NULL;
00610 cpl_imagelist *imagelist = NULL;
00611 cpl_image *fringes = NULL;
00612 cpl_image *stacked = NULL;
00613 cpl_image *mapped = NULL;
00614 cpl_image *smapped = NULL;
00615 cpl_image *sky_stacked = NULL;
00616 cpl_image *sky_mapped = NULL;
00617 cpl_image *sky_smapped = NULL;
00618 cpl_table *polytraces = NULL;
00619 cpl_table *idscoeff = NULL;
00620 cpl_table *slits = NULL;
00621 cpl_table *grism_table = NULL;
00622 cpl_propertylist *header = NULL;
00623 char *name;
00624 double offset;
00625 double gain;
00626 double ron;
00627 int time_normal;
00628 int min_reject;
00629 int max_reject;
00630 double klow;
00631 double khigh;
00632 int kiter;
00633 int int_alignment = 0;
00634 int status;
00635 int nx, ny;
00636 int i;
00637
00638
00639 snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00640
00641 grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00642
00643 flux = dfs_get_parameter_bool(parlist, "fors.vimos_science.flux", NULL);
00644
00645 cosmics = dfs_get_parameter_bool(parlist,
00646 "fors.vimos_science.cosmics", NULL);
00647
00648 dispersion = dfs_get_parameter_double(parlist,
00649 "fors.vimos_science.dispersion", grism_table);
00650
00651 refwave = dfs_get_parameter_double(parlist,
00652 "fors.vimos_science.reference", grism_table);
00653
00654 startwavelength = dfs_get_parameter_double(parlist,
00655 "fors.vimos_science.startwavelength", grism_table);
00656
00657 endwavelength = dfs_get_parameter_double(parlist,
00658 "fors.vimos_science.endwavelength", grism_table);
00659
00660 alignment = dfs_get_parameter_string(parlist,
00661 "fors.vimos_science.alignment", NULL);
00662
00663 if (strcmp(alignment, "integer") == 0) {
00664 int_alignment = 1;
00665 }
00666
00667 stack_method = dfs_get_parameter_string(parlist,
00668 "fors.vimos_science.stack_method", NULL);
00669
00670 if (strcmp(stack_method, "minmax") == 0) {
00671 min_reject = dfs_get_parameter_int(parlist,
00672 "fors.vimos_science.minrejection", NULL);
00673 if (min_reject < 0) {
00674 cpl_msg_error("vimos_science",
00675 "Invalid number of lower rejections");
00676 return -1;
00677 }
00678
00679 max_reject = dfs_get_parameter_int(parlist,
00680 "fors.vimos_science.maxrejection", NULL);
00681
00682 if (max_reject < 0) {
00683 cpl_msg_error("vimos_science",
00684 "Invalid number of upper rejections");
00685 return -1;
00686 }
00687 }
00688
00689 if (strcmp(stack_method, "ksigma") == 0) {
00690 klow = dfs_get_parameter_double(parlist,
00691 "fors.vimos_science.klow", NULL);
00692 if (klow < 0.1) {
00693 cpl_msg_error("vimos_science",
00694 "Invalid lower K-sigma");
00695 return -1;
00696 }
00697
00698 khigh = dfs_get_parameter_double(parlist,
00699 "fors.vimos_science.khigh", NULL);
00700 if (khigh < 0.1) {
00701 cpl_msg_error("vimos_science",
00702 "Invalid lower K-sigma");
00703 return -1;
00704 }
00705
00706 kiter = dfs_get_parameter_int(parlist,
00707 "fors.vimos_science.kiter", NULL);
00708 if (kiter < 1) {
00709 cpl_msg_error("vimos_science",
00710 "Invalid number of iterations");
00711 return -1;
00712 }
00713 }
00714
00715 slit_margin = dfs_get_parameter_int(parlist,
00716 "fors.vimos_science.slit_margin",
00717 NULL);
00718 ext_radius = dfs_get_parameter_int(parlist,
00719 "fors.vimos_science.ext_radius",
00720 NULL);
00721 cont_radius = dfs_get_parameter_int(parlist,
00722 "fors.vimos_science.cont_radius",
00723 NULL);
00724 ext_mode = dfs_get_parameter_int(parlist,
00725 "fors.vimos_science.ext_mode",
00726 NULL);
00727
00728 fringing = dfs_get_parameter_bool(parlist,
00729 "fors.vimos_science.fringing", NULL);
00730
00731 cpl_table_delete(grism_table); grism_table = NULL;
00732
00733
00734
00735
00736
00737
00738 param = cpl_parameterlist_find(parlist,
00739 "fors.vimos_science.time_normalise");
00740 time_normal = cpl_parameter_get_bool(param);
00741 cpl_parameter_set_bool(param, 0);
00742
00743
00744
00745
00746
00747
00748 mos_science[0] = cpl_frameset_find(frameset, science_tag);
00749 for (i = 1; i < mos; i++) {
00750 mos_science[i] = cpl_frameset_find(frameset, NULL);
00751 }
00752
00753
00754
00755
00756
00757
00758 for (i = 0; i < mos; i++) {
00759 cpl_frameset_erase(work, science_tag);
00760 cpl_frameset_insert(work, cpl_frame_duplicate(mos_science[i]));
00761 vimos_science_impl(work, parlist);
00762
00763
00764
00765
00766
00767
00768
00769 cpl_frameset_erase(work, "MOS_SKYLINES_OFFSETS_SLIT");
00770 cpl_frameset_erase(work, "MOS_SCIENCE_SKY_EXTRACTED");
00771 cpl_frameset_erase(work, "MOS_UNMAPPED_SKY");
00772 cpl_frameset_erase(work, "MOS_UNMAPPED_SCIENCE");
00773 cpl_frameset_erase(work, "MOS_WAVELENGTH_MAP_SKY");
00774 cpl_frameset_erase(work, "MOS_SCIENCE_SKY");
00775 cpl_frameset_erase(work, "OBJECT_TABLE");
00776 cpl_frameset_erase(work, "MOS_SCIENCE_REDUCED");
00777 cpl_frameset_erase(work, "MOS_SKY_REDUCED");
00778 cpl_frameset_erase(work, "MOS_ERROR_REDUCED");
00779 cpl_frameset_erase(work, "MOS_DISP_COEFF_SKY");
00780 cpl_frameset_erase(work, "MOS_SCIENCE_EXTRACTED");
00781
00782
00783
00784
00785
00786
00787
00788 name = cpl_sprintf("object_table_%d.fits", i);
00789 status = rename("object_table.fits", name);
00790 cpl_free(name);
00791 name = cpl_sprintf("mos_unmapped_sky_%d.fits", i);
00792 status |= rename("mos_unmapped_sky.fits", name);
00793 cpl_free(name);
00794 name = cpl_sprintf("mos_unmapped_science_%d.fits", i);
00795 status |= rename("mos_unmapped_science.fits", name);
00796 cpl_free(name);
00797
00798 if (status) {
00799 cpl_msg_error("vimos_science", "Cannot rename product.");
00800 cpl_free(mos_science);
00801 cpl_frameset_delete(work);
00802 return -1;
00803 }
00804 }
00805
00806 cpl_free(mos_science);
00807 cpl_frameset_delete(work);
00808
00809 if (fringing) {
00810
00811
00812
00813
00814
00815 imagelist = cpl_imagelist_new();
00816
00817 for (i = 0; i < mos; i++) {
00818 name = cpl_sprintf("mos_unmapped_science_%d.fits", i);
00819 image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00820 cpl_imagelist_set(imagelist, image,
00821 cpl_imagelist_get_size(imagelist));
00822 }
00823
00824 fringes = cpl_imagelist_collapse_median_create(imagelist);
00825 cpl_imagelist_delete(imagelist);
00826 cpl_image_save(fringes, "fringes.fits",
00827 CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT);
00828
00829 }
00830
00831
00832
00833
00834
00835
00836 reference = cpl_table_load("object_table_0.fits", 1, 1);
00837 stacked = cpl_image_load("mos_unmapped_science_0.fits",
00838 CPL_TYPE_FLOAT, 0, 0);
00839 sky_stacked = cpl_image_load("mos_unmapped_sky_0.fits",
00840 CPL_TYPE_FLOAT, 0, 0);
00841 if (fringing) {
00842 cpl_image_subtract(stacked, fringes);
00843 cpl_image_add(sky_stacked, fringes);
00844 }
00845
00846
00847 cpl_image_save(stacked, "mos_unmapped_science_0.fits",
00848 CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT);
00849
00850
00851 for (i = 1; i < mos; i++) {
00852 name = cpl_sprintf("object_table_%d.fits", i);
00853 objects = cpl_table_load(name, 1, 1);
00854 cpl_free(name);
00855 if (mos_compute_offset(reference, objects, &offset)) {
00856 cpl_msg_error("vimos_science", "Cannot compute offset.");
00857 cpl_table_delete(objects);
00858 return -1;
00859 }
00860 cpl_table_delete(objects);
00861 name = cpl_sprintf("mos_unmapped_science_%d.fits", i);
00862 image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00863
00864 if (fringing) {
00865 cpl_image_subtract(image, fringes);
00866 }
00867
00868 cpl_msg_info("vimos_science",
00869 "Frame %d offset relative "
00870 "to frame 1: %.2f pix\n", i + 1, offset);
00871
00872 if (int_alignment) {
00873 offset = floor(offset + 0.5);
00874 cpl_msg_info("vimos_science",
00875 "Nearest neighbour offset applied is "
00876 "%.0f pix\n", offset);
00877 }
00878
00879 mos_image_shift(image, offset, 0.0);
00880 cpl_image_save(image, name, CPL_BPP_IEEE_FLOAT,
00881 NULL, CPL_IO_DEFAULT);
00882 cpl_free(name);
00883
00884
00885
00886
00887
00888 name = cpl_sprintf("mos_unmapped_sky_%d.fits", i);
00889 sky_image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00890
00891 if (fringing) {
00892 cpl_image_add(sky_image, fringes);
00893 }
00894
00895 mos_image_shift(sky_image, offset, 0.0);
00896 cpl_free(name);
00897 cpl_image_add(sky_stacked, sky_image);
00898 cpl_image_delete(sky_image);
00899
00900 if (strcmp(stack_method, "average") == 0) {
00901 cpl_image_add(stacked, image);
00902 cpl_image_delete(image);
00903 }
00904 else {
00905 if (i == 1) {
00906 imagelist = cpl_imagelist_new();
00907 cpl_imagelist_set(imagelist, stacked,
00908 cpl_imagelist_get_size(imagelist));
00909 }
00910 cpl_imagelist_set(imagelist, image,
00911 cpl_imagelist_get_size(imagelist));
00912 }
00913 }
00914 cpl_table_delete(reference);
00915
00916 cpl_image_divide_scalar(sky_stacked, mos);
00917
00918 if (fringing) {
00919 cpl_image_delete(fringes);
00920 }
00921
00922 if (strcmp(stack_method, "average") == 0) {
00923 cpl_image_divide_scalar(stacked, mos);
00924 }
00925
00926 if (strcmp(stack_method, "median") == 0) {
00927 stacked = cpl_imagelist_collapse_median_create(imagelist);
00928 cpl_imagelist_delete(imagelist);
00929 }
00930
00931 if (strcmp(stack_method, "minmax") == 0) {
00932 stacked = cpl_imagelist_collapse_minmax_create(imagelist,
00933 min_reject,
00934 max_reject);
00935 cpl_imagelist_delete(imagelist);
00936 }
00937
00938 if (strcmp(stack_method, "ksigma") == 0) {
00939 stacked = mos_ksigma_stack(imagelist, klow, khigh, kiter, NULL);
00940 cpl_imagelist_delete(imagelist);
00941 }
00942
00943 header = dfs_load_header(frameset, science_tag, 0);
00944
00945 gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00946 ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
00947 ron /= gain;
00948
00949 if (dfs_save_image(frameset, stacked, unmapped_science_tag,
00950 header, parlist, "vimos_science", version)) {
00951 cpl_image_delete(stacked);
00952 cpl_image_delete(sky_stacked);
00953 cpl_propertylist_delete(header);
00954 cpl_table_delete(slits);
00955 return -1;
00956 }
00957
00958 if (dfs_save_image(frameset, sky_stacked, unmapped_sky_tag,
00959 header, parlist, "vimos_science", version)) {
00960 cpl_image_delete(stacked);
00961 cpl_image_delete(sky_stacked);
00962 cpl_propertylist_delete(header);
00963 cpl_table_delete(slits);
00964 return -1;
00965 }
00966
00967 cpl_parameter_set_bool(param, time_normal);
00968
00969 cpl_image_turn(stacked, rotate);
00970 cpl_image_turn(sky_stacked, rotate);
00971
00972 nx = cpl_image_get_size_x(stacked);
00973 ny = cpl_image_get_size_y(stacked);
00974
00975 polytraces = dfs_load_table(frameset, curv_coeff_tag, 1);
00976
00977 slits = dfs_load_table(frameset, slit_location_tag, 1);
00978 mos_rotate_slits(slits, -rotate, nx, ny);
00979
00980
00981 idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1);
00982
00983 cpl_msg_indent_less();
00984 cpl_msg_info("vimos_science",
00985 "Processing stacked scientific spectra...");
00986 cpl_msg_indent_more();
00987
00988 smapped = mos_spatial_calibration(stacked, slits, polytraces, refwave,
00989 startwavelength, endwavelength,
00990 dispersion, flux, NULL);
00991
00992 cpl_image_delete(stacked);
00993
00994 sky_smapped = mos_spatial_calibration(sky_stacked, slits, polytraces,
00995 refwave, startwavelength,
00996 endwavelength, dispersion,
00997 flux, NULL);
00998
00999 cpl_image_delete(sky_stacked);
01000 cpl_table_delete(polytraces);
01001
01002 mapped = mos_wavelength_calibration(smapped, refwave,
01003 startwavelength, endwavelength,
01004 dispersion, idscoeff, flux);
01005
01006 cpl_image_delete(smapped);
01007
01008 sky_mapped = mos_wavelength_calibration(sky_smapped, refwave,
01009 startwavelength, endwavelength,
01010 dispersion, idscoeff, flux);
01011 cpl_table_delete(idscoeff);
01012
01013 cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01014 cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01015 cpl_propertylist_update_double(header, "CRVAL1",
01016 startwavelength + dispersion/2);
01017 cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01018 cpl_propertylist_update_double(header, "CD1_1", dispersion);
01019 cpl_propertylist_update_double(header, "CD1_2", 0.0);
01020 cpl_propertylist_update_double(header, "CD2_1", 0.0);
01021 cpl_propertylist_update_double(header, "CD2_2", 1.0);
01022 cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01023 cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 if (dfs_save_image(frameset, mapped, mapped_science_tag,
01036 header, parlist, "vimos_science", version)) {
01037 cpl_propertylist_delete(header);
01038 cpl_image_delete(mapped);
01039 cpl_image_delete(sky_mapped);
01040 cpl_table_delete(slits);
01041 return -1;
01042 }
01043
01044 if (dfs_save_image(frameset, sky_mapped, mapped_sky_tag,
01045 header, parlist, "vimos_science", version)) {
01046 cpl_propertylist_delete(header);
01047 cpl_image_delete(mapped);
01048 cpl_image_delete(sky_mapped);
01049 cpl_table_delete(slits);
01050 return -1;
01051 }
01052
01053
01054 cpl_msg_indent_less();
01055 cpl_msg_info("vimos_science", "Final object detection...");
01056 cpl_msg_indent_more();
01057
01058 if (cosmics || strcmp(stack_method, "average")) {
01059 image = mos_detect_objects(mapped, slits, slit_margin, ext_radius,
01060 cont_radius);
01061 }
01062 else {
01063 cpl_image *mapped_cleaned = cpl_image_duplicate(mapped);
01064 mos_clean_cosmics(mapped_cleaned, gain, -1., -1.);
01065 image = mos_detect_objects(mapped_cleaned, slits, slit_margin,
01066 ext_radius, cont_radius);
01067
01068 cpl_image_delete(mapped_cleaned);
01069 }
01070
01071 cpl_image_delete(image);
01072
01073 mos_rotate_slits(slits, rotate, ny, nx);
01074 if (dfs_save_table(frameset, slits, object_table_tag, NULL, parlist,
01075 "vimos_science", version)) {
01076 cpl_propertylist_delete(header);
01077 cpl_image_delete(mapped);
01078 cpl_image_delete(sky_mapped);
01079 cpl_table_delete(slits);
01080 return -1;
01081 }
01082
01083 cpl_msg_indent_less();
01084 cpl_msg_info("vimos_science", "Final object extraction...");
01085 cpl_msg_indent_more();
01086
01087 images = mos_extract_objects(mapped, sky_mapped, slits,
01088 ext_mode, ron, gain, mos);
01089
01090 cpl_image_delete(mapped);
01091 cpl_image_delete(sky_mapped);
01092 cpl_table_delete(slits);
01093
01094 if (images) {
01095
01096
01097
01098 if (dfs_save_image(frameset, images[0], reduced_science_tag,
01099 header, parlist, "vimos_science", version)) {
01100 cpl_image_delete(images[0]);
01101 cpl_image_delete(images[1]);
01102 cpl_image_delete(images[2]);
01103 cpl_free(images);
01104 cpl_propertylist_delete(header);
01105 return -1;
01106 }
01107
01108 cpl_image_delete(images[0]);
01109
01110
01111
01112
01113 if (dfs_save_image(frameset, images[1], reduced_sky_tag, header,
01114 parlist, "vimos_science", version)) {
01115 cpl_image_delete(images[1]);
01116 cpl_image_delete(images[2]);
01117 cpl_free(images);
01118 cpl_propertylist_delete(header);
01119 return -1;
01120 }
01121
01122 cpl_image_delete(images[1]);
01123
01124
01125
01126
01127 if (dfs_save_image(frameset, images[2], reduced_error_tag, header,
01128 parlist, "vimos_science", version)) {
01129 cpl_image_delete(images[2]);
01130 cpl_free(images);
01131 cpl_propertylist_delete(header);
01132 return -1;
01133 }
01134
01135 cpl_image_delete(images[2]);
01136
01137 cpl_free(images);
01138 }
01139 else {
01140 cpl_msg_warning("vimos_science", "No objects found: the products "
01141 "%s, %s, and %s are not created",
01142 reduced_science_tag, reduced_sky_tag,
01143 reduced_error_tag);
01144 }
01145
01146 cpl_propertylist_delete(header);
01147
01148 return 0;
01149 }
01150
01151 return vimos_science_impl(frameset, parlist);
01152 }