vimos_science_impl.c

00001 /* $Id: vimos_science_impl.c,v 1.3 2010/09/14 07:49:30 cizzo Exp $
00002  *
00003  * This file is part of the FORS Data Reduction Pipeline
00004  * Copyright (C) 2002-2010 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author: cizzo $
00023  * $Date: 2010/09/14 07:49:30 $
00024  * $Revision: 1.3 $
00025  * $Name: fors-4_8_6 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <vimos_science_impl.h>
00033 
00034 #include <math.h>
00035 #include <cpl.h>
00036 #include <moses.h>
00037 #include <fors_tools.h>
00038 #include <fors_dfs.h>
00039 #include <fors_qc.h>
00040 
00041 #define vimos_science_exit(message)           \
00042 {                                             \
00043 if (message) cpl_msg_error(recipe, message);  \
00044 cpl_free(exptime);                            \
00045 cpl_image_delete(dummy);                      \
00046 cpl_image_delete(mapped);                     \
00047 cpl_image_delete(mapped_sky);                 \
00048 cpl_image_delete(mapped_cleaned);             \
00049 cpl_image_delete(skylocalmap);                \
00050 cpl_image_delete(skymap);                     \
00051 cpl_image_delete(smapped);                    \
00052 cpl_table_delete(offsets);                    \
00053 cpl_table_delete(sky);                        \
00054 cpl_image_delete(bias);                       \
00055 cpl_image_delete(spectra);                    \
00056 cpl_image_delete(coordinate);                 \
00057 cpl_image_delete(norm_flat);                  \
00058 cpl_image_delete(rainbow);                    \
00059 cpl_image_delete(rectified);                  \
00060 cpl_image_delete(wavemap);                    \
00061 cpl_propertylist_delete(header);              \
00062 cpl_propertylist_delete(save_header);         \
00063 cpl_table_delete(grism_table);                \
00064 cpl_table_delete(idscoeff);                   \
00065 cpl_table_delete(maskslits);                  \
00066 cpl_table_delete(overscans);                  \
00067 cpl_table_delete(polytraces);                 \
00068 cpl_table_delete(slits);                      \
00069 cpl_table_delete(wavelengths);                \
00070 cpl_vector_delete(lines);                     \
00071 cpl_msg_indent_less();                        \
00072 return -1;                                    \
00073 }
00074 
00081 int vimos_science_impl(cpl_frameset *frameset, cpl_parameterlist *parlist)
00082 {
00083     const char *recipe = "vimos_science";
00084 
00085 
00086     /*
00087      * Input parameters
00088      */
00089 
00090     double      dispersion;
00091     int         skyalign;
00092     const char *wcolumn;
00093     double      startwavelength;
00094     double      endwavelength;
00095     double      reference;
00096     int         flux;
00097     int         flatfield;
00098     int         skyglobal;
00099     int         skylocal;
00100     int         skymedian;
00101     int         cosmics;
00102     int         slit_margin;
00103     int         ext_radius;
00104     int         cont_radius;
00105     int         ext_mode;
00106     int         time_normalise;
00107     int         anyframe;
00108     int         res_order;
00109     int         qc;
00110 
00111     /*
00112      * CPL objects
00113      */
00114 
00115     cpl_imagelist    *all_science;
00116     cpl_image       **images;
00117 
00118     cpl_image        *bias           = NULL;
00119     cpl_image        *norm_flat      = NULL;
00120     cpl_image        *spectra        = NULL;
00121     cpl_image        *rectified      = NULL;
00122     cpl_image        *coordinate     = NULL;
00123     cpl_image        *rainbow        = NULL;
00124     cpl_image        *mapped         = NULL;
00125     cpl_image        *mapped_sky     = NULL;
00126     cpl_image        *mapped_cleaned = NULL;
00127     cpl_image        *smapped        = NULL;
00128     cpl_image        *wavemap        = NULL;
00129     cpl_image        *skymap         = NULL;
00130     cpl_image        *skylocalmap    = NULL;
00131     cpl_image        *dummy          = NULL;
00132 
00133     cpl_table        *grism_table    = NULL;
00134     cpl_table        *overscans      = NULL;
00135     cpl_table        *wavelengths    = NULL;
00136     cpl_table        *idscoeff       = NULL;
00137     cpl_table        *slits          = NULL;
00138     cpl_table        *maskslits      = NULL;
00139     cpl_table        *polytraces     = NULL;
00140     cpl_table        *offsets        = NULL;
00141     cpl_table        *sky            = NULL;
00142 
00143     cpl_vector       *lines          = NULL;
00144 
00145     cpl_propertylist *header         = NULL;
00146     cpl_propertylist *save_header    = NULL;
00147     cpl_propertylist *qclist         = NULL;
00148 
00149     /*
00150      * Auxiliary variables
00151      */
00152 
00153     char        version[80];
00154     char       *instrume = NULL;
00155     const char *science_tag;
00156     const char *master_norm_flat_tag;
00157     const char *disp_coeff_tag;
00158     const char *disp_coeff_sky_tag;
00159     const char *wavelength_map_tag;
00160     const char *wavelength_map_sky_tag;
00161     const char *curv_coeff_tag;
00162     const char *slit_location_tag;
00163     const char *reduced_science_tag;
00164     const char *reduced_sky_tag;
00165     const char *reduced_error_tag;
00166     const char *mapped_science_tag;
00167     const char *unmapped_science_tag;
00168     const char *mapped_science_sky_tag;
00169     const char *mapped_sky_tag;
00170     const char *unmapped_sky_tag;
00171     const char *global_sky_spectrum_tag;
00172     const char *object_table_tag;
00173     const char *skylines_offsets_tag;
00174     const char *specphot_tag;
00175     const char *key_gris_name;
00176     const char *key_gris_id;
00177     const char *key_filt_name;
00178     const char *key_filt_id;
00179     int         mos;
00180     int         nexp, expno;
00181     int         treat_as_lss = 0;
00182     int         nslits;
00183     int         nscience;
00184     int         quadrant;
00185     double     *xpos;
00186     double     *exptime = NULL;
00187     double      airmass;
00188     double      alltime;
00189     double      mxpos;
00190     double      mean_rms;
00191     int         nlines;
00192     double     *line;
00193     int         nx, ny;
00194     double      gain;
00195     double      ron;
00196     int         standard;
00197     int         highres;
00198     int         rotate = 1;
00199     int         rotate_back = -1;
00200     int         i;
00201     double      wstart;
00202     double      wstep;
00203     int         wcount;
00204 
00205 
00206     snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
00207 
00208     cpl_msg_set_indentation(2);
00209 
00210     if (dfs_files_dont_exist(frameset))
00211         vimos_science_exit(NULL);
00212 
00213 
00214     /* 
00215      * Get configuration parameters
00216      */
00217 
00218     cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
00219     cpl_msg_indent_more();
00220 
00221     if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
00222         vimos_science_exit("Too many in input: GRISM_TABLE");
00223 
00224     grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
00225 
00226     dispersion = dfs_get_parameter_double(parlist, 
00227                     "fors.vimos_science.dispersion", grism_table);
00228 
00229     if (dispersion <= 0.0)
00230         vimos_science_exit("Invalid resampling step");
00231 
00232     skyalign = dfs_get_parameter_int(parlist, 
00233                     "fors.vimos_science.skyalign", NULL);
00234 
00235     if (skyalign > 2)
00236         vimos_science_exit("Max polynomial degree for sky alignment is 2");
00237 
00238     wcolumn = dfs_get_parameter_string(parlist, 
00239                     "fors.vimos_science.wcolumn", NULL);
00240 
00241     startwavelength = dfs_get_parameter_double(parlist, 
00242                     "fors.vimos_science.startwavelength", grism_table);
00243     if (startwavelength < 3000.0 || startwavelength > 13000.0)
00244         vimos_science_exit("Invalid wavelength");
00245 
00246     endwavelength = dfs_get_parameter_double(parlist, 
00247                     "fors.vimos_science.endwavelength", grism_table);
00248     if (endwavelength < 3000.0 || endwavelength > 13000.0)
00249         vimos_science_exit("Invalid wavelength");
00250 
00251     if (endwavelength - startwavelength <= 0.0)
00252         vimos_science_exit("Invalid wavelength interval");
00253 
00254     reference = dfs_get_parameter_double(parlist,
00255                 "fors.vimos_science.reference", grism_table);
00256 
00257     if (reference < startwavelength || reference > endwavelength)
00258         vimos_science_exit("Invalid reference wavelength");
00259 
00260     flux = dfs_get_parameter_bool(parlist, "fors.vimos_science.flux", NULL);
00261 
00262     flatfield = dfs_get_parameter_bool(parlist, "fors.vimos_science.flatfield", 
00263                                        NULL);
00264 
00265     skyglobal = dfs_get_parameter_bool(parlist, "fors.vimos_science.skyglobal", 
00266                                        NULL);
00267     skylocal  = dfs_get_parameter_bool(parlist, "fors.vimos_science.skylocal", 
00268                                        NULL);
00269     skymedian = dfs_get_parameter_bool(parlist, "fors.vimos_science.skymedian", 
00270                                        NULL);
00271 
00272     if (skylocal && skyglobal)
00273         vimos_science_exit("Cannot do both local and global sky subtraction");
00274 
00275     if (skylocal && skymedian)
00276         vimos_science_exit("Cannot do sky subtraction both on extracted "
00277                            "and non-extracted spectra");
00278 
00279     cosmics = dfs_get_parameter_bool(parlist, 
00280                                      "fors.vimos_science.cosmics", NULL);
00281 
00282     if (cosmics)
00283         if (!(skyglobal || skylocal))
00284             vimos_science_exit("Cosmic rays correction requires "
00285                               "either skylocal=true or skyglobal=true");
00286 
00287     slit_margin = dfs_get_parameter_int(parlist, 
00288                                         "fors.vimos_science.slit_margin",
00289                                         NULL);
00290     if (slit_margin < 0)
00291         vimos_science_exit("Value must be zero or positive");
00292 
00293     ext_radius = dfs_get_parameter_int(parlist, 
00294                                        "fors.vimos_science.ext_radius",
00295                                        NULL);
00296     if (ext_radius < 0)
00297         vimos_science_exit("Value must be zero or positive");
00298 
00299     cont_radius = dfs_get_parameter_int(parlist, 
00300                                         "fors.vimos_science.cont_radius",
00301                                         NULL);
00302     if (cont_radius < 0)
00303         vimos_science_exit("Value must be zero or positive");
00304 
00305     ext_mode = dfs_get_parameter_int(parlist, "fors.vimos_science.ext_mode",
00306                                        NULL);
00307     if (ext_mode < 0 || ext_mode > 1)
00308         vimos_science_exit("Invalid object extraction mode");
00309 
00310     time_normalise = dfs_get_parameter_bool(parlist, 
00311                              "fors.vimos_science.time_normalise", NULL);
00312 
00313     res_order = dfs_get_parameter_int(parlist, "fors.vimos_science.response",
00314                                       NULL);
00315     if (res_order < 2 || res_order > 10)
00316         vimos_science_exit("Invalid instrument response modeling polynomial");
00317 
00318     anyframe = dfs_get_parameter_bool(parlist, "fors.vimos_science.anyframe", 
00319                                       NULL);
00320 
00321     qc = dfs_get_parameter_bool(parlist, "fors.vimos_science.qc", NULL);
00322 
00323     cpl_table_delete(grism_table); grism_table = NULL;
00324 
00325     if (cpl_error_get_code())
00326         vimos_science_exit("Failure getting the configuration parameters");
00327 
00328     
00329     /* 
00330      * Check input set-of-frames
00331      */
00332 
00333     cpl_msg_indent_less();
00334     cpl_msg_info(recipe, "Check input set-of-frames:");
00335     cpl_msg_indent_more();
00336 
00337     if (!dfs_equal_keyword(frameset, "ESO OCS CON QUAD"))
00338         vimos_science_exit("Input frames are not from the same quadrant");
00339 
00340     mos = cpl_frameset_count_tags(frameset, "MOS_SCIENCE");
00341     standard = 0;
00342 
00343     if (mos == 0) {
00344         mos = cpl_frameset_count_tags(frameset, "MOS_STANDARD");
00345         standard = 1;
00346     }
00347 
00348     if (mos == 0)
00349         vimos_science_exit("Missing input scientific frame");
00350 
00351     nscience = mos;
00352 
00353     if (standard) {
00354         science_tag            = "MOS_STANDARD";
00355         reduced_science_tag    = "MOS_STANDARD_REDUCED";
00356         unmapped_science_tag   = "MOS_UNMAPPED_STANDARD";
00357         mapped_science_tag     = "MOS_STANDARD_EXTRACTED";
00358         mapped_science_sky_tag = "MOS_STANDARD_SKY_EXTRACTED";
00359         mapped_sky_tag         = "MOS_STANDARD_SKY";
00360         specphot_tag           = "MOS_SPECPHOT_TABLE";
00361 
00362     }
00363     else {
00364         science_tag            = "MOS_SCIENCE";
00365         reduced_science_tag    = "MOS_SCIENCE_REDUCED";
00366         unmapped_science_tag   = "MOS_UNMAPPED_SCIENCE";
00367         mapped_science_tag     = "MOS_SCIENCE_EXTRACTED";
00368         mapped_science_sky_tag = "MOS_SCIENCE_SKY_EXTRACTED";
00369         mapped_sky_tag         = "MOS_SCIENCE_SKY";
00370     }
00371 
00372     reduced_sky_tag         = "MOS_SKY_REDUCED";
00373     reduced_error_tag       = "MOS_ERROR_REDUCED";
00374     master_norm_flat_tag    = "MOS_MASTER_SCREEN_FLAT";
00375     disp_coeff_sky_tag      = "MOS_DISP_COEFF_SKY";
00376     wavelength_map_sky_tag  = "MOS_WAVELENGTH_MAP_SKY";
00377     disp_coeff_tag          = "MOS_DISP_COEFF";
00378     wavelength_map_tag      = "WAVELENGTH_MAP_MXU";
00379     curv_coeff_tag          = "MOS_CURV_COEFF";
00380     slit_location_tag       = "MOS_SLIT_LOCATION";
00381     skylines_offsets_tag    = "MOS_SKYLINES_OFFSETS_SLIT";
00382     unmapped_sky_tag        = "MOS_UNMAPPED_SKY";
00383     global_sky_spectrum_tag = "MOS_GLOBAL_SKY_SPECTRUM";
00384     object_table_tag        = "OBJECT_TABLE";
00385 
00386     if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0)
00387         vimos_science_exit("Missing required input: MASTER_BIAS");
00388 
00389     if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
00390         vimos_science_exit("Too many in input: MASTER_BIAS");
00391 
00392     if (skyalign >= 0)
00393         if (cpl_frameset_count_tags(frameset, "SKY_LINE_CATALOG") > 1)
00394             vimos_science_exit("Too many in input: SKY_LINE_CATALOG");
00395 
00396     if (cpl_frameset_count_tags(frameset, disp_coeff_tag) == 0) {
00397         cpl_msg_error(recipe, "Missing required input: %s", disp_coeff_tag);
00398         vimos_science_exit(NULL);
00399     }
00400 
00401     if (cpl_frameset_count_tags(frameset, disp_coeff_tag) > 1) {
00402         cpl_msg_error(recipe, "Too many in input: %s", disp_coeff_tag);
00403         vimos_science_exit(NULL);
00404     }
00405 
00406     if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
00407         if (flatfield) {
00408             cpl_msg_error(recipe, "Too many in input: %s", 
00409                           master_norm_flat_tag);
00410             vimos_science_exit(NULL);
00411         }
00412         else {
00413             cpl_msg_warning(recipe, "%s in input are ignored, "
00414                             "since flat field correction was not requested", 
00415                             master_norm_flat_tag);
00416         }
00417     }
00418 
00419     if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
00420         if (!flatfield) {
00421             cpl_msg_warning(recipe, "%s in input is ignored, "
00422                             "since flat field correction was not requested", 
00423                             master_norm_flat_tag);
00424         }
00425     }
00426 
00427     if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
00428         if (flatfield) {
00429             cpl_msg_error(recipe, "Flat field correction was requested, "
00430                           "but no %s are found in input",
00431                           master_norm_flat_tag);
00432             vimos_science_exit(NULL);
00433         }
00434     }
00435 
00436     if (standard) {
00437 
00438         if (cpl_frameset_count_tags(frameset, "EXTINCT_TABLE") == 0) {
00439             cpl_msg_warning(recipe, "An EXTINCT_TABLE was not found in input: "
00440                             "instrument response curve will not be produced.");
00441             standard = 0;
00442         }
00443 
00444         if (cpl_frameset_count_tags(frameset, "EXTINCT_TABLE") > 1)
00445             vimos_science_exit("Too many in input: EXTINCT_TABLE");
00446 
00447         if (cpl_frameset_count_tags(frameset, "STD_FLUX_TABLE") == 0) {
00448             cpl_msg_warning(recipe, "A STD_FLUX_TABLE was not found in input: "
00449                             "instrument response curve will not be produced.");
00450             standard = 0;
00451         }
00452 
00453         if (cpl_frameset_count_tags(frameset, "STD_FLUX_TABLE") > 1)
00454             vimos_science_exit("Too many in input: STD_FLUX_TABLE");
00455 
00456         if (!dfs_equal_keyword(frameset, "ESO OBS TARG NAME")) {
00457             cpl_msg_warning(recipe, "The target name of observation does not "
00458                             "match the standard star catalog: "
00459                             "instrument response curve will not be produced.");
00460             standard = 0;
00461         }
00462     }
00463 
00464     cpl_msg_indent_less();
00465 
00466 
00467     /*
00468      * Loading input data
00469      */
00470 
00471     exptime = cpl_calloc(nscience, sizeof(double));
00472 
00473     if (nscience > 1) {
00474 
00475         cpl_msg_info(recipe, "Load %d scientific frames and median them...",
00476                      nscience);
00477         cpl_msg_indent_more();
00478 
00479         all_science = cpl_imagelist_new();
00480 
00481         header = dfs_load_header(frameset, science_tag, 0);
00482 
00483         if (header == NULL)
00484             vimos_science_exit("Cannot load scientific frame header");
00485 
00486         alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
00487 
00488         if (cpl_error_get_code() != CPL_ERROR_NONE)
00489             vimos_science_exit("Missing keyword EXPTIME in scientific "
00490                               "frame header");
00491 
00492         if (standard) {
00493             airmass = fors_get_airmass(header);
00494             if (airmass < 0.0)
00495                 vimos_science_exit("Missing airmass information in "
00496                                    "scientific frame header");
00497         }
00498 
00499         instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00500         if (instrume == NULL)
00501             vimos_science_exit("Missing keyword INSTRUME "
00502                                "in scientific frame header");
00503 
00504         cpl_propertylist_delete(header); header = NULL;
00505 
00506         cpl_msg_info(recipe, "Scientific frame 1 exposure time: %.2f s", 
00507                      exptime[0]);
00508 
00509         for (i = 1; i < nscience; i++) {
00510 
00511             header = dfs_load_header(frameset, NULL, 0);
00512 
00513             if (header == NULL)
00514                 vimos_science_exit("Cannot load scientific frame header");
00515     
00516             exptime[i] = cpl_propertylist_get_double(header, "EXPTIME");
00517 
00518             alltime += exptime[i];
00519     
00520             if (cpl_error_get_code() != CPL_ERROR_NONE)
00521                 vimos_science_exit("Missing keyword EXPTIME in scientific "
00522                                   "frame header");
00523     
00524             cpl_propertylist_delete(header); header = NULL;
00525 
00526             cpl_msg_info(recipe, "Scientific frame %d exposure time: %.2f s", 
00527                          i+1, exptime[i]);
00528         }
00529 
00530         spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
00531 
00532         if (spectra == NULL)
00533             vimos_science_exit("Cannot load scientific frame");
00534 
00535         cpl_image_divide_scalar(spectra, exptime[0]);
00536         cpl_imagelist_set(all_science, spectra, 0);
00537 
00538         for (i = 1; i < nscience; i++) {
00539 
00540             spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
00541 
00542             if (spectra) {
00543                 cpl_image_divide_scalar(spectra, exptime[i]);
00544                 cpl_imagelist_set(all_science, spectra, i);
00545             }
00546             else
00547                 vimos_science_exit("Cannot load scientific frame");
00548 
00549         }
00550 
00551         spectra = cpl_imagelist_collapse_median_create(all_science);
00552         cpl_image_multiply_scalar(spectra, alltime);
00553 
00554         cpl_imagelist_delete(all_science);
00555     }
00556     else {
00557         cpl_msg_info(recipe, "Load scientific exposure...");
00558         cpl_msg_indent_more();
00559 
00560         header = dfs_load_header(frameset, science_tag, 0);
00561 
00562         if (header == NULL)
00563             vimos_science_exit("Cannot load scientific frame header");
00564 
00565         alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
00566 
00567         if (cpl_error_get_code() != CPL_ERROR_NONE)
00568             vimos_science_exit("Missing keyword EXPTIME in scientific "
00569                               "frame header");
00570 
00571         if (standard) {
00572             airmass = fors_get_airmass(header);
00573             if (airmass < 0.0)
00574                 vimos_science_exit("Missing airmass information in "
00575                                    "scientific frame header");
00576         }
00577 
00578         instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
00579         if (instrume == NULL)
00580             vimos_science_exit("Missing keyword INSTRUME "
00581                                "in scientific frame header");
00582 
00583         cpl_propertylist_delete(header); header = NULL;
00584 
00585         cpl_msg_info(recipe, "Scientific frame exposure time: %.2f s", 
00586                      exptime[0]);
00587 
00588         spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
00589     }
00590 
00591     if (spectra == NULL)
00592         vimos_science_exit("Cannot load scientific frame");
00593 
00594     cpl_free(exptime); exptime = NULL;
00595 
00596     cpl_msg_indent_less();
00597 
00598 
00599     /*
00600      * Get some info from header
00601      */
00602 
00603     header = dfs_load_header(frameset, science_tag, 0);
00604 
00605     if (header == NULL)
00606         vimos_science_exit("Cannot load scientific frame header");
00607 
00608     quadrant = cpl_propertylist_get_int(header, "ESO OCS CON QUAD");
00609 
00610     switch (quadrant) {
00611     case 1:
00612         key_gris_name = "ESO INS GRIS1 NAME";
00613         key_gris_id = "ESO INS GRIS1 ID";
00614         key_filt_name = "ESO INS FILT1 NAME";
00615         key_filt_id = "ESO INS FILT1 ID";
00616         break;
00617     case 2: 
00618         key_gris_name = "ESO INS GRIS2 NAME";
00619         key_gris_id = "ESO INS GRIS2 ID";
00620         key_filt_name = "ESO INS FILT2 NAME";
00621         key_filt_id = "ESO INS FILT2 ID";
00622         break;
00623     case 3: 
00624         key_gris_name = "ESO INS GRIS3 NAME";
00625         key_gris_id = "ESO INS GRIS3 ID";
00626         key_filt_name = "ESO INS FILT3 NAME";
00627         key_filt_id = "ESO INS FILT3 ID";
00628         break;
00629     case 4:
00630         key_gris_name = "ESO INS GRIS4 NAME";
00631         key_gris_id = "ESO INS GRIS4 ID";
00632         key_filt_name = "ESO INS FILT4 NAME";
00633         key_filt_id = "ESO INS FILT4 ID";
00634         break;
00635     }
00636 
00637     if (standard) {
00638         if (!anyframe) {
00639 
00640            /*
00641             *  As a default this recipe wouldn't reduce a frame belonging 
00642             *  to a quadrant that is not expected to contain a standard 
00643             *  star. The current template for getting data for photometric 
00644             *  calibration consists of a sequence of 4 exposures, where 
00645             *  the same standard star is moved through all quadrants. 
00646             *  The first exposure has the standard star in quadrant 1, 
00647             *  the second exposure in quadrant 2, and so on. So a standard 
00648             *  star will be reduced only if it is part of a template of 
00649             *  4 exposures (i.e., TPL NEXP == 4), and if its sequence 
00650             *  number in the template is equal to its quadrant number 
00651             *  (i.e., TPL EXPNO == OCS CON QUAD).
00652             */
00653 
00654             nexp = cpl_propertylist_get_int(header, "ESO TPL NEXP");
00655 
00656             if (cpl_error_get_code() != CPL_ERROR_NONE)
00657                 vimos_science_exit("Missing keyword ESO TPL NEXP in "
00658                                     "scientific frame header");
00659 
00660             if (nexp == 4) {
00661                 expno = cpl_propertylist_get_int(header, "ESO TPL EXPNO");
00662 
00663             if (cpl_error_get_code() != CPL_ERROR_NONE)
00664                 vimos_science_exit("Missing keyword ESO TPL EXPNO in "
00665                                    "scientific frame header");
00666             }
00667 
00668             if (quadrant != expno) {
00669                 cpl_msg_warning(recipe, "The MOS_STANDARD frame is not "
00670                                 "expected to contain a standard star: "
00671                                 "instrument response curve will not be "
00672                                 "produced. Set --anyframe=true to skip "
00673                                 "this check.");
00674                 standard = 0;
00675             }
00676         }
00677     }
00678 
00679 /*
00680     if (!dfs_equal_keyword(frameset, key_gris_id))
00681         vimos_science_exit("Input frames are not from the same grism");
00682 
00683     if (!dfs_equal_keyword(frameset, key_filt_id))
00684         vimos_science_exit("Input frames are not from the same filter");
00685 */
00686 
00687     gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
00688 
00689     if (cpl_error_get_code() != CPL_ERROR_NONE)
00690         vimos_science_exit("Missing keyword ESO DET OUT1 CONAD in scientific "
00691                           "frame header");
00692 
00693     cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
00694 
00695     ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
00696 
00697     if (cpl_error_get_code() != CPL_ERROR_NONE)
00698         vimos_science_exit("Missing keyword ESO DET OUT1 RON in scientific "
00699                           "frame header");
00700 
00701     ron /= gain;     /* Convert from electrons to ADU */
00702 
00703     cpl_msg_info(recipe, "The read-out-noise is: %.2f ADU", ron);
00704 
00705     /* 
00706      * In VIMOS data are "never" LSS. This is why this part is
00707      * commented out.
00708      */
00709 
00710 //    maskslits = mos_load_slits_vimos(header);
00711 //
00712 //    /*
00713 //     * Check if all slits have the same X offset: in such case,
00714 //     * treat the observation as a long-slit one!
00715 //     */
00716 //
00717 //    mxpos = cpl_table_get_column_median(maskslits, "ytop");
00718 //    xpos = cpl_table_get_data_double(maskslits, "ytop");
00719 //    nslits = cpl_table_get_nrow(maskslits);
00720 //     
00721 //    treat_as_lss = 1;
00722 //    for (i = 0; i < nslits; i++) { 
00723 //        if (fabs(mxpos-xpos[i]) > 0.01) {
00724 //            treat_as_lss = 0;
00725 //            break;
00726 //        }
00727 //    }
00728 //
00729 //    treat_as_lss = 0;  // FIXME Prevent LSS treatment for the moment!!!
00730 //
00731 //    cpl_table_delete(maskslits); maskslits = NULL;
00732 //
00733 //    if (treat_as_lss) {
00734 //        cpl_msg_warning(recipe, "All MOS slits have the same offset: %.2f\n"
00735 //                        "The LSS data reduction strategy is applied!",
00736 //                        mxpos);
00737 //        skylines_offsets_tag   = "MOS_SKYLINES_OFFSETS_LONG";
00738 //    }
00739 
00740     if (treat_as_lss) {
00741         if (skylocal) {
00742             if (cosmics)
00743                 vimos_science_exit("Cosmic rays correction for long-slit-like "
00744                                   "data requires --skyglobal=true");
00745             skymedian = skylocal;
00746             skylocal = 0;
00747         }
00748     }
00749     else {
00750         if (cpl_frameset_count_tags(frameset, curv_coeff_tag) == 0) {
00751             cpl_msg_error(recipe, "Missing required input: %s", curv_coeff_tag);
00752             vimos_science_exit(NULL);
00753         }
00754 
00755         if (cpl_frameset_count_tags(frameset, curv_coeff_tag) > 1) {
00756             cpl_msg_error(recipe, "Too many in input: %s", curv_coeff_tag);
00757             vimos_science_exit(NULL);
00758         }
00759 
00760         if (cpl_frameset_count_tags(frameset, slit_location_tag) == 0) {
00761             cpl_msg_error(recipe, "Missing required input: %s", 
00762                           slit_location_tag);
00763             vimos_science_exit(NULL);
00764         }
00765         
00766         if (cpl_frameset_count_tags(frameset, slit_location_tag) > 1) {
00767             cpl_msg_error(recipe, "Too many in input: %s", slit_location_tag);
00768             vimos_science_exit(NULL);
00769         }
00770     }
00771 
00772     /* Leave the header on for the next step... */
00773 
00774 
00775     /*
00776      * Remove the master bias
00777      */
00778 
00779     cpl_msg_info(recipe, "Remove the master bias...");
00780 
00781     bias = dfs_load_image(frameset, "MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
00782 
00783     if (bias == NULL)
00784         vimos_science_exit("Cannot load master bias");
00785 
00786     overscans = mos_load_overscans_vimos(header, 1);
00787     cpl_propertylist_delete(header); header = NULL;
00788     dummy = mos_remove_bias(spectra, bias, overscans);
00789     cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
00790     cpl_image_delete(bias); bias = NULL;
00791     cpl_table_delete(overscans); overscans = NULL;
00792 
00793     if (spectra == NULL)
00794         vimos_science_exit("Cannot remove bias from scientific frame");
00795 
00796     /*
00797      * Rotate frames horizontally with red to the right
00798      */
00799 
00800     cpl_image_turn(spectra, rotate);
00801 
00802     nx = cpl_image_get_size_x(spectra);
00803     ny = cpl_image_get_size_y(spectra);
00804 
00805     cpl_msg_indent_less();
00806     cpl_msg_info(recipe, "Load normalised flat field (if present)...");
00807     cpl_msg_indent_more();
00808 
00809     if (flatfield) {
00810 
00811         norm_flat = dfs_load_image(frameset, master_norm_flat_tag, 
00812                                    CPL_TYPE_FLOAT, 0, 1);
00813 
00814         if (norm_flat) {
00815             cpl_image_turn(norm_flat, rotate);
00816             cpl_msg_info(recipe, "Apply flat field correction...");
00817             if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
00818                 cpl_msg_error(recipe, "Failure of flat field correction: %s",
00819                               cpl_error_get_message());
00820                 vimos_science_exit(NULL);
00821             }
00822             cpl_image_delete(norm_flat); norm_flat = NULL;
00823         }
00824         else {
00825             cpl_msg_error(recipe, "Cannot load input %s for flat field "
00826                           "correction", master_norm_flat_tag);
00827             vimos_science_exit(NULL);
00828         }
00829 
00830     }
00831 
00832 
00833     if (skyalign >= 0) {
00834         cpl_msg_indent_less();
00835         cpl_msg_info(recipe, "Load input sky line catalog...");
00836         cpl_msg_indent_more();
00837 
00838         wavelengths = dfs_load_table(frameset, "SKY_LINE_CATALOG", 1);
00839 
00840         if (wavelengths) {
00841 
00842             /*
00843              * Cast the wavelengths into a (double precision) CPL vector
00844              */
00845 
00846             nlines = cpl_table_get_nrow(wavelengths);
00847 
00848             if (nlines == 0)
00849                 vimos_science_exit("Empty input sky line catalog");
00850 
00851             if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
00852                 cpl_msg_error(recipe, "Missing column %s in input line "
00853                               "catalog table", wcolumn);
00854                 vimos_science_exit(NULL);
00855             }
00856 
00857             line = cpl_malloc(nlines * sizeof(double));
00858     
00859             for (i = 0; i < nlines; i++)
00860                 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
00861 
00862             cpl_table_delete(wavelengths); wavelengths = NULL;
00863 
00864             lines = cpl_vector_wrap(nlines, line);
00865         }
00866         else {
00867             cpl_msg_info(recipe, "No sky line catalog found in input - fine!");
00868         }
00869     }
00870 
00871 
00872     /*
00873      * Load the spectral curvature table, or provide a dummy one
00874      * in case of LSS-like data (single slit with flat curvature)
00875      */
00876 
00877     if (!treat_as_lss) {
00878         polytraces = dfs_load_table(frameset, curv_coeff_tag, 1);
00879         if (polytraces == NULL)
00880             vimos_science_exit("Cannot load spectral curvature table");
00881     }
00882 
00883 
00884     /*
00885      * Load the slit location table, or provide a dummy one in case
00886      * of LSS-like data (single slit spanning whole image)
00887      */
00888 
00889     if (treat_as_lss) {
00890         slits = cpl_table_new(1);
00891         cpl_table_new_column(slits, "slit_id", CPL_TYPE_INT);
00892         cpl_table_set_int(slits, "slit_id", 0, 1);
00893         cpl_table_new_column(slits, "position", CPL_TYPE_INT);
00894         cpl_table_set_int(slits, "position", 0, 0);
00895         cpl_table_new_column(slits, "length", CPL_TYPE_INT);
00896         cpl_table_set_int(slits, "length", 0, ny);
00897     }
00898     else {
00899         slits = dfs_load_table(frameset, slit_location_tag, 1);
00900         if (slits == NULL)
00901             vimos_science_exit("Cannot load slits location table");
00902         mos_rotate_slits(slits, -rotate, nx, ny);
00903     }
00904 
00905 
00906     /*
00907      * Load the wavelength calibration table
00908      */
00909 
00910     idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1);
00911     if (idscoeff == NULL)
00912         vimos_science_exit("Cannot load wavelength calibration table");
00913 
00914     cpl_msg_indent_less();
00915     cpl_msg_info(recipe, "Processing scientific spectra...");
00916     cpl_msg_indent_more();
00917 
00918     /*
00919      * This one will also generate the spatial map from the spectral 
00920      * curvature table (in the case of multislit data)
00921      */
00922 
00923     if (treat_as_lss) {
00924         smapped = cpl_image_duplicate(spectra);
00925     }
00926     else {
00927         coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00928 
00929         smapped = mos_spatial_calibration(spectra, slits, polytraces, reference,
00930                                           startwavelength, endwavelength,
00931                                           dispersion, flux, coordinate);
00932     }
00933 
00934 
00935     /*
00936      * Generate a rectified wavelength map from the wavelength calibration 
00937      * table
00938      */
00939 
00940     rainbow = mos_map_idscoeff(idscoeff, nx, reference, startwavelength, 
00941                                endwavelength);
00942 
00943     if (dispersion > 1.0)
00944         highres = 0;
00945     else
00946         highres = 1;
00947 
00948     if (skyalign >= 0) {
00949         if (skyalign) {
00950             cpl_msg_info(recipe, "Align wavelength solution to reference "
00951             "skylines applying %d order residual fit...", skyalign);
00952         }
00953         else {
00954             cpl_msg_info(recipe, "Align wavelength solution to reference "
00955             "skylines applying median offset...");
00956         }
00957 
00958         if (treat_as_lss) {
00959             offsets = mos_wavelength_align_lss(smapped, reference, 
00960                                                startwavelength, endwavelength, 
00961                                                idscoeff, lines, highres, 
00962                                                skyalign, rainbow, 4);
00963         }
00964         else {
00965             offsets = mos_wavelength_align(smapped, slits, reference, 
00966                                            startwavelength, endwavelength, 
00967                                            idscoeff, lines, highres, skyalign, 
00968                                            rainbow, 4);
00969         }
00970 
00971         cpl_vector_delete(lines); lines = NULL;
00972 
00973         if (offsets) {
00974             if (standard)
00975                 cpl_msg_warning(recipe, "Alignment of the wavelength solution "
00976                                 "to reference sky lines may be unreliable in "
00977                                 "this case!");
00978 
00979             if (dfs_save_table(frameset, offsets, skylines_offsets_tag, NULL, 
00980                                parlist, recipe, version))
00981                 vimos_science_exit(NULL);
00982 
00983             cpl_table_delete(offsets); offsets = NULL;
00984         }
00985         else {
00986             cpl_msg_warning(recipe, "Alignment of the wavelength solution "
00987                             "to reference sky lines could not be done!");
00988             skyalign = -1;
00989         }
00990 
00991     }
00992 
00993     if (treat_as_lss) {
00994         wavemap = rainbow;
00995         rainbow = NULL;
00996     }
00997     else {
00998         wavemap = mos_map_wavelengths(coordinate, rainbow, slits, 
00999                                       polytraces, reference, 
01000                                       startwavelength, endwavelength,
01001                                       dispersion);
01002     }
01003 
01004     cpl_image_delete(rainbow); rainbow = NULL;
01005     cpl_image_delete(coordinate); coordinate = NULL;
01006 
01007     /*
01008      * Here the wavelength calibrated slit spectra are created. This frame
01009      * contains sky_science.
01010      */
01011 
01012     mapped_sky = mos_wavelength_calibration(smapped, reference,
01013                                             startwavelength, endwavelength,
01014                                             dispersion, idscoeff, flux);
01015 
01016     cpl_msg_indent_less();
01017     cpl_msg_info(recipe, "Check applied wavelength against skylines...");
01018     cpl_msg_indent_more();
01019 
01020     mean_rms = mos_distortions_rms(mapped_sky, NULL, startwavelength,
01021                                    dispersion, 6, highres);
01022 
01023     cpl_msg_info(recipe, "Mean residual: %f", mean_rms);
01024 
01025     mean_rms = cpl_table_get_column_mean(idscoeff, "error");
01026 
01027     cpl_msg_info(recipe, "Mean model accuracy: %f pixel (%f A)",
01028                  mean_rms, mean_rms * dispersion);
01029 
01030     header = cpl_propertylist_new();
01031     cpl_propertylist_update_double(header, "CRPIX1", 1.0);
01032     cpl_propertylist_update_double(header, "CRPIX2", 1.0);
01033     cpl_propertylist_update_double(header, "CRVAL1", 
01034                                    startwavelength + dispersion/2);
01035     cpl_propertylist_update_double(header, "CRVAL2", 1.0);
01036     /* cpl_propertylist_update_double(header, "CDELT1", dispersion);
01037     cpl_propertylist_update_double(header, "CDELT2", 1.0); */
01038     cpl_propertylist_update_double(header, "CD1_1", dispersion);
01039     cpl_propertylist_update_double(header, "CD1_2", 0.0);
01040     cpl_propertylist_update_double(header, "CD2_1", 0.0);
01041     cpl_propertylist_update_double(header, "CD2_2", 1.0);
01042     cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
01043     cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
01044 
01045     if (time_normalise) {
01046         dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
01047         if (dfs_save_image(frameset, dummy, mapped_science_sky_tag, header, 
01048                            parlist, recipe, version))
01049             vimos_science_exit(NULL);
01050         cpl_image_delete(dummy); dummy = NULL;
01051     }
01052     else {
01053         if (dfs_save_image(frameset, mapped_sky, mapped_science_sky_tag, 
01054                            header, parlist, recipe, version))
01055             vimos_science_exit(NULL);
01056     }
01057 
01058     if (skyglobal == 0 && skymedian == 0 && skylocal == 0) {
01059         cpl_image_delete(mapped_sky); mapped_sky = NULL;
01060     }
01061 
01062     if (skyglobal || skylocal) {
01063 
01064         cpl_msg_indent_less();
01065 
01066         if (skyglobal) {
01067             cpl_msg_info(recipe, "Global sky determination...");
01068             cpl_msg_indent_more();
01069             skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01070             sky = mos_sky_map_super(spectra, wavemap, dispersion, 
01071                                     2.0, 50, skymap);
01072             if (sky)
01073                 cpl_image_subtract(spectra, skymap);
01074             else
01075                 cpl_image_delete(skymap); skymap = NULL;
01076         }
01077         else {
01078             cpl_msg_info(recipe, "Local sky determination...");
01079             cpl_msg_indent_more();
01080             skymap = mos_subtract_sky(spectra, slits, polytraces, reference,
01081                            startwavelength, endwavelength, dispersion);
01082         }
01083 
01084         if (skymap) {
01085             if (skyglobal) {
01086                 if (time_normalise)
01087                     cpl_table_divide_scalar(sky, "sky", alltime);
01088                 if (dfs_save_table(frameset, sky, global_sky_spectrum_tag, 
01089                                    NULL, parlist, recipe, version))
01090                     vimos_science_exit(NULL);
01091     
01092                 cpl_table_delete(sky); sky = NULL;
01093             }
01094 
01095             save_header = dfs_load_header(frameset, science_tag, 0);
01096 
01097             if (time_normalise)
01098                 cpl_image_divide_scalar(skymap, alltime);
01099             cpl_image_turn(skymap, rotate_back);
01100             if (dfs_save_image(frameset, skymap, unmapped_sky_tag,
01101                                save_header, parlist, recipe, version))
01102                 vimos_science_exit(NULL);
01103 
01104             cpl_image_delete(skymap); skymap = NULL;
01105 
01106             cpl_image_turn(spectra, rotate_back);
01107 
01108             if (cosmics) {
01109                 cpl_msg_info(recipe, "Removing cosmic rays...");
01110                 mos_clean_cosmics(spectra, gain, -1., -1.);
01111             }
01112 
01113             if (dfs_save_image(frameset, spectra, unmapped_science_tag,
01114                                save_header, parlist, recipe, version))
01115                 vimos_science_exit(NULL);
01116             cpl_image_turn(spectra, rotate);
01117 
01118             cpl_propertylist_delete(save_header); save_header = NULL;
01119 /* Cosmics was here */
01120             /*
01121              * The spatially rectified image, that contained the sky,
01122              * is replaced by a sky-subtracted spatially rectified image:
01123              */
01124 
01125             cpl_image_delete(smapped); smapped = NULL;
01126 
01127             if (treat_as_lss) {
01128                 smapped = cpl_image_duplicate(spectra);
01129             }
01130             else {
01131                 smapped = mos_spatial_calibration(spectra, slits, polytraces, 
01132                                                   reference, startwavelength, 
01133                                                   endwavelength, dispersion, 
01134                                                   flux, NULL);
01135             }
01136         }
01137         else {
01138             cpl_msg_warning(recipe, "Sky subtraction failure");
01139             if (cosmics)
01140                 cpl_msg_warning(recipe, "Cosmic rays removal not performed!");
01141             cosmics = skylocal = skyglobal = 0;
01142         }
01143     }
01144 
01145     cpl_image_delete(spectra); spectra = NULL;
01146     cpl_table_delete(polytraces); polytraces = NULL;
01147 
01148     if (skyalign >= 0) {
01149         save_header = dfs_load_header(frameset, science_tag, 0);
01150         cpl_image_turn(wavemap, rotate_back);
01151         if (dfs_save_image(frameset, wavemap, wavelength_map_sky_tag,
01152                            save_header, parlist, recipe, version))
01153             vimos_science_exit(NULL);
01154         cpl_propertylist_delete(save_header); save_header = NULL;
01155     }
01156 
01157     cpl_image_delete(wavemap); wavemap = NULL;
01158 
01159     mapped = mos_wavelength_calibration(smapped, reference,
01160                                         startwavelength, endwavelength,
01161                                         dispersion, idscoeff, flux);
01162 
01163     cpl_image_delete(smapped); smapped = NULL;
01164 
01165     if (skymedian) {
01166         cpl_msg_indent_less();
01167         cpl_msg_info(recipe, "Local sky determination...");
01168         cpl_msg_indent_more();
01169     
01170         skylocalmap = mos_sky_local_old(mapped, slits);       
01171         cpl_image_subtract(mapped, skylocalmap);
01172         cpl_image_delete(skylocalmap); skylocalmap = NULL;
01173     }
01174 
01175     if (skyglobal || skymedian || skylocal) {
01176 
01177         skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
01178 
01179         cpl_image_delete(mapped_sky); mapped_sky = NULL;
01180 
01181         if (time_normalise) {
01182             dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
01183             if (dfs_save_image(frameset, dummy, mapped_sky_tag, header,
01184                                parlist, recipe, version))
01185                 vimos_science_exit(NULL);
01186             cpl_image_delete(dummy); dummy = NULL;
01187         }
01188         else {
01189             if (dfs_save_image(frameset, skylocalmap, mapped_sky_tag, header,
01190                                parlist, recipe, version))
01191                 vimos_science_exit(NULL);
01192         }
01193 
01194         cpl_msg_indent_less();
01195         cpl_msg_info(recipe, "Object detection...");
01196         cpl_msg_indent_more();
01197 
01198         if (cosmics || nscience > 1) {
01199             dummy = mos_detect_objects(mapped, slits, slit_margin, ext_radius, 
01200                                        cont_radius);
01201         }
01202         else {
01203             mapped_cleaned = cpl_image_duplicate(mapped);
01204             mos_clean_cosmics(mapped_cleaned, gain, -1., -1.);
01205             dummy = mos_detect_objects(mapped_cleaned, slits, slit_margin, 
01206                                        ext_radius, cont_radius);
01207 
01208             cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
01209         }
01210 
01211         cpl_image_delete(dummy); dummy = NULL;
01212 
01213         mos_rotate_slits(slits, rotate, ny, nx);
01214         if (dfs_save_table(frameset, slits, object_table_tag, NULL, parlist, 
01215                            recipe, version))
01216             vimos_science_exit(NULL);
01217 
01218         cpl_msg_indent_less();
01219         cpl_msg_info(recipe, "Object extraction...");
01220         cpl_msg_indent_more();
01221 
01222         images = mos_extract_objects(mapped, skylocalmap, slits, 
01223                                      ext_mode, ron, gain, 1);
01224 
01225         cpl_image_delete(skylocalmap); skylocalmap = NULL;
01226 
01227         if (images) {
01228             if (standard) {
01229                 cpl_table *photcal    = NULL;
01230                 cpl_table *ext_table  = NULL;
01231                 cpl_table *flux_table = NULL;
01232 
01233                 ext_table = dfs_load_table(frameset, "EXTINCT_TABLE", 1);
01234                 flux_table = dfs_load_table(frameset, "STD_FLUX_TABLE", 1);
01235 
01236                 photcal = mos_photometric_calibration(images[0],
01237                                                       startwavelength,
01238                                                       dispersion, gain,
01239                                                       alltime, ext_table,
01240                                                       airmass, flux_table,
01241                                                       res_order);
01242 
01243                 cpl_table_delete(ext_table);
01244                 cpl_table_delete(flux_table);
01245 
01246                 if (photcal) {
01247 
01248                     if (qc) {
01249 
01250                         float *data;
01251                         char  *pipefile = NULL;
01252                         char   keyname[30];
01253 
01254                         qclist = dfs_load_header(frameset, science_tag, 0);
01255 
01256                         if (qclist == NULL)
01257                             vimos_science_exit("Cannot reload scientific "
01258                                                "frame header");
01259 
01260                         fors_qc_start_group(qclist, "2.0", instrume);
01261 
01262 
01263                         /*
01264                          * QC1 group header
01265                          */
01266 
01267                         if (fors_qc_write_string("PRO.CATG", specphot_tag,
01268                                                  "Product category", instrume))
01269                             vimos_science_exit("Cannot write product category "
01270                                                "to QC log file");
01271 
01272                         if (fors_qc_keyword_to_paf(qclist, "ESO DPR TYPE", NULL,
01273                                                    "DPR type", instrume))
01274                             vimos_science_exit("Missing keyword DPR TYPE in "
01275                                                "scientific frame header");
01276 
01277                         if (fors_qc_keyword_to_paf(qclist, "ESO TPL ID", NULL,
01278                                                    "Template", instrume))
01279                             vimos_science_exit("Missing keyword TPL ID in "
01280                                                "scientific frame header");
01281 
01282                         if (fors_qc_keyword_to_paf(qclist,
01283                                                    key_gris_name, NULL,
01284                                                    "Grism name", instrume)) {
01285                             cpl_msg_error(recipe, "Missing keyword %s in "
01286                                           "scientific frame header", 
01287                                           key_gris_name);
01288                             vimos_science_exit(NULL);
01289                         }
01290 
01291                         if (fors_qc_keyword_to_paf(qclist,
01292                                                    "ESO INS GRIS1 ID", NULL,
01293                                                    "Grism identifier",
01294                                                    instrume)) {
01295                             cpl_msg_error(recipe, "Missing keyword %s in "
01296                                           "scientific frame header", 
01297                                           key_gris_id);
01298                             vimos_science_exit(NULL);
01299                         }
01300 
01301                         if (cpl_propertylist_has(qclist, key_filt_name))
01302                             fors_qc_keyword_to_paf(qclist, key_filt_name, NULL,
01303                                                    "Filter name", instrume);
01304 
01305                         if (fors_qc_keyword_to_paf(qclist,
01306                                                    "ESO DET CHIP1 ID", NULL,
01307                                                    "Chip identifier",
01308                                                    instrume))
01309                             vimos_science_exit("Missing keyword DET CHIP1 ID "
01310                                                "in scientific frame header");
01311 
01312                         if (fors_qc_keyword_to_paf(qclist, "ARCFILE", NULL,
01313                                                    "Archive name of input data",
01314                                                    instrume))
01315                             vimos_science_exit("Missing keyword ARCFILE in "
01316                                                "scientific frame header");
01317 
01318                         pipefile = dfs_generate_filename_tfits(specphot_tag);
01319 
01320                         if (fors_qc_write_string("PIPEFILE", pipefile,
01321                                                  "Pipeline product name",
01322                                                  instrume))
01323                             vimos_science_exit("Cannot write PIPEFILE to "
01324                                                "QC log file");
01325                         cpl_free(pipefile);
01326 
01327 
01328                         /*
01329                          * QC1 parameters
01330                          */
01331 
01332                         wstart = 3700.;
01333                         wstep  = 400.;
01334                         wcount = 15;
01335 
01336                         dummy = cpl_image_new(wcount, 1, CPL_TYPE_FLOAT);
01337                         data = cpl_image_get_data_float(dummy);
01338                         map_table(dummy, wstart, wstep, photcal,
01339                                   "WAVE", "EFFICIENCY");
01340 
01341                         for (i = 0; i < wcount; i++) {
01342                             sprintf(keyname, "QC.MOS.EFFICIENCY%d.LAMBDA",
01343                                     i + 1);
01344                             if (fors_qc_write_qc_double(qclist,
01345                                                         wstart + wstep * i,
01346                                                         keyname, "Angstrom",
01347                                                         "Wavelength of "
01348                                                         "efficiency evaluation",
01349                                                         instrume)) {
01350                                 vimos_science_exit("Cannot write wavelength of "
01351                                                    "efficiency evaluation");
01352                             }
01353 
01354                             sprintf(keyname, "QC.MOS.EFFICIENCY%d", i + 1);
01355                             if (fors_qc_write_qc_double(qclist,
01356                                                         data[i],
01357                                                         keyname, "e-/photon",
01358                                                         "Efficiency",
01359                                                         instrume)) {
01360                                 vimos_science_exit("Cannot write wavelength of "
01361                                                    "efficiency evaluation");
01362                             }
01363                         }
01364 
01365                         cpl_image_delete(dummy); dummy = NULL;
01366 
01367                         fors_qc_end_group();
01368 
01369                     }  /* End of QC1 computation */
01370 
01371                     if (dfs_save_table(frameset, photcal, specphot_tag, qclist,
01372                                        parlist, recipe, version)) {
01373                         cpl_table_delete(photcal);
01374                         vimos_science_exit(NULL);
01375                     }
01376                     cpl_propertylist_delete(qclist); qclist = NULL;
01377                     cpl_table_delete(photcal);
01378                 }
01379             }
01380 
01381             if (time_normalise)
01382                 cpl_image_divide_scalar(images[0], alltime);
01383 
01384             if (dfs_save_image(frameset, images[0], reduced_science_tag, header,
01385                                parlist, recipe, version))
01386                 vimos_science_exit(NULL);
01387 
01388             cpl_image_delete(images[0]);
01389     
01390             if (time_normalise)
01391                 cpl_image_divide_scalar(images[1], alltime);
01392 
01393             if (dfs_save_image(frameset, images[1], reduced_sky_tag, header,
01394                                parlist, recipe, version))
01395                 vimos_science_exit(NULL);
01396 
01397             cpl_image_delete(images[1]);
01398     
01399             if (time_normalise)
01400                 cpl_image_divide_scalar(images[2], alltime);
01401 
01402             if (dfs_save_image(frameset, images[2], reduced_error_tag, header,
01403                                parlist, recipe, version))
01404                 vimos_science_exit(NULL);
01405 
01406             cpl_image_delete(images[2]);
01407 
01408             cpl_free(images);
01409         }
01410         else {
01411             cpl_msg_warning(recipe, "No objects found: the products "
01412                             "%s, %s, and %s are not created", 
01413                             reduced_science_tag, reduced_sky_tag, 
01414                             reduced_error_tag);
01415         }
01416 
01417     }
01418 
01419     cpl_table_delete(slits); slits = NULL;
01420 
01421     if (skyalign >= 0) {
01422         if (dfs_save_table(frameset, idscoeff, disp_coeff_sky_tag, NULL, 
01423                            parlist, recipe, version))
01424             vimos_science_exit(NULL);
01425     }
01426 
01427     cpl_table_delete(idscoeff); idscoeff = NULL;
01428 
01429     if (skyglobal || skymedian || skylocal) {
01430         if (time_normalise)
01431             cpl_image_divide_scalar(mapped, alltime);
01432         if (dfs_save_image(frameset, mapped, mapped_science_tag, header, 
01433                            parlist, recipe, version))
01434             vimos_science_exit(NULL);
01435     }
01436 
01437     cpl_image_delete(mapped); mapped = NULL;
01438     cpl_propertylist_delete(header); header = NULL;
01439 
01440     if (cpl_error_get_code()) {
01441         cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
01442         vimos_science_exit(NULL);
01443     }
01444     else 
01445         return 0;
01446 }

Generated on Fri Mar 4 09:46:01 2011 for FORS Pipeline Reference Manual by  doxygen 1.4.7