uves_redchain_impl.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston MA 02110-1301 USA          *
00018  */
00019  
00020 /*
00021  * $Author: jmlarsen $
00022  * $Date: 2007/06/11 13:28:26 $
00023  * $Revision: 1.35 $
00024  * $Name: uves-3_3_1 $
00025  * $Log: uves_redchain_impl.c,v $
00026  * Revision 1.35  2007/06/11 13:28:26  jmlarsen
00027  * Changed recipe contact address to cpl at eso.org
00028  *
00029  * Revision 1.34  2007/06/08 13:06:16  jmlarsen
00030  * Send bug reports to Andrea
00031  *
00032  * Revision 1.33  2007/06/06 08:17:33  amodigli
00033  * replace tab with 4 spaces
00034  *
00035  * Revision 1.32  2007/05/22 09:11:06  jmlarsen
00036  * Reverse logic bugfix
00037  *
00038  * Revision 1.31  2007/05/22 08:13:19  amodigli
00039  * allow to process only blu or red data
00040  *
00041  * Revision 1.30  2007/05/14 08:09:48  amodigli
00042  * updated input frames and tag description in recipe man page
00043  *
00044  * Revision 1.29  2007/05/03 16:03:58  jmlarsen
00045  * uves_obs_redchain: Implemented option to skip final science reduction
00046  *
00047  * Revision 1.28  2007/02/09 13:40:26  jmlarsen
00048  * Use defines for recipe id
00049  *
00050  * Revision 1.27  2007/02/09 08:58:51  jmlarsen
00051  * Use define's rather than hard-coded recipe names
00052  *
00053  * Revision 1.26  2006/11/24 16:21:39  jmlarsen
00054  * Added FIB_LINE_TABLE_x
00055  *
00056  * Revision 1.25  2006/11/15 15:02:15  jmlarsen
00057  * Implemented const safe workarounds for CPL functions
00058  *
00059  * Revision 1.23  2006/11/15 14:04:08  jmlarsen
00060  * Removed non-const version of parameterlist_get_first/last/next which is
00061  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00062  *
00063  * Revision 1.22  2006/11/13 12:47:08  jmlarsen
00064  * Changed syntax of UVES_ARC_LAMP to support FLAMES
00065  *
00066  * Revision 1.21  2006/11/06 15:19:41  jmlarsen
00067  * Removed unused include directives
00068  *
00069  * Revision 1.20  2006/10/24 14:06:27  jmlarsen
00070  * Added flames=false where relevant
00071  *
00072  * Revision 1.19  2006/10/19 13:53:25  jmlarsen
00073  * Changed guess line table tag to LINE_GUESS_TAB
00074  *
00075  * Revision 1.18  2006/10/17 12:33:02  jmlarsen
00076  * Added semicolon at UVES_RECIPE_DEFINE invocation
00077  *
00078  * Revision 1.17  2006/10/09 13:01:13  jmlarsen
00079  * Use macro to define recipe interface functions
00080  *
00081  * Revision 1.16  2006/10/02 08:37:49  jmlarsen
00082  * Added REF_TFLAT
00083  *
00084  * Revision 1.15  2006/09/27 15:08:45  jmlarsen
00085  * Fixed doc. bug
00086  *
00087  * Revision 1.14  2006/09/14 08:46:51  jmlarsen
00088  * Added support for TFLAT, SCREEN_FLAT frames
00089  *
00090  * Revision 1.13  2006/08/17 13:56:53  jmlarsen
00091  * Reduced max line length
00092  *
00093  * Revision 1.12  2006/08/16 11:58:02  jmlarsen
00094  * Fixed trivial but harmful buffer overrun
00095  *
00096  * Revision 1.11  2006/08/11 14:56:05  amodigli
00097  * removed Doxygen warnings
00098  *
00099  * Revision 1.10  2006/07/14 12:30:34  jmlarsen
00100  * Compute PRO CATG depending on DO CATG
00101  *
00102  * Revision 1.9  2006/07/03 13:27:10  jmlarsen
00103  * Minor doc update
00104  *
00105  * Revision 1.8  2006/07/03 13:16:47  amodigli
00106  * updated description
00107  *
00108  * Revision 1.7  2006/06/16 08:25:45  jmlarsen
00109  * Manually propagate ESO.DET. keywords from 1st/2nd input header
00110  *
00111  * Revision 1.6  2006/06/13 12:00:54  jmlarsen
00112  * Support ORDER_GUESS_TAB
00113  *
00114  * Revision 1.5  2006/04/24 09:23:33  jmlarsen
00115  * Recognize PDARK, DFLAT, IFLAT as products
00116  *
00117  * Revision 1.4  2006/04/06 12:56:50  jmlarsen
00118  * Added support for PDARK, IFLAT, DLFAT frames
00119  *
00120  * Revision 1.3  2006/04/06 11:48:17  jmlarsen
00121  * Support for SCI_POINT_-, SCI_EXTND_- and SCI_SLICER-frames
00122  *
00123  * Revision 1.2  2006/04/06 08:47:16  jmlarsen
00124  * Support DFLAT, IFLAT, PDARK
00125  *
00126  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00127  * Moved recipe implementations to ./uves directory
00128  *
00129  * Revision 1.14  2006/01/19 08:47:24  jmlarsen
00130  * Inserted missing doxygen end tag
00131  *
00132  * Revision 1.13  2005/12/20 08:11:44  jmlarsen
00133  * Added CVS  entry
00134  *
00135  */
00136 
00137 #ifdef HAVE_CONFIG_H
00138 #  include <config.h>
00139 #endif
00140 
00141 
00142 /*----------------------------------------------------------------------------*/
00148 /*----------------------------------------------------------------------------*/
00149 
00150 /*-----------------------------------------------------------------------------
00151                                 Includes
00152  -----------------------------------------------------------------------------*/
00153 
00154 #include <uves.h>
00155 
00156 #include <uves_parameters.h>
00157 #include <uves_utils.h>
00158 #include <uves_utils_wrappers.h>
00159 #include <uves_dfs.h>
00160 #include <uves_recipe.h>
00161 #include <uves_error.h>
00162 #include <uves_msg.h>
00163 
00164 /* Library */
00165 #include <irplib_access.h>
00166 #include <cpl.h>
00167 
00168 /*-----------------------------------------------------------------------------
00169                             Local constants
00170  -----------------------------------------------------------------------------*/
00171 static const bool flames = false;  /* This recipe is only for UVES */
00172 
00173 /*-----------------------------------------------------------------------------
00174                             Functions prototypes
00175  -----------------------------------------------------------------------------*/
00176 static bool frame_is_needed(bool blue, const cpl_frame *f);
00177 static cpl_error_code execute_recipe(const char *recipe_id, 
00178                                      cpl_frameset *frames, const cpl_parameterlist *parameters,
00179                                      const char *products[], int n_products, bool reclassify);
00180 static bool is_missing(const cpl_frameset *frames, const char *frame1, const char *frame2);
00181 static void remove_input_frame(cpl_frameset *frames, const char *tag);
00182 
00183 static int uves_redchain_define_parameters(cpl_parameterlist *parameters);
00184 
00185 /*-----------------------------------------------------------------------------
00186                             Recipe standard code
00187  -----------------------------------------------------------------------------*/
00188 #define cpl_plugin_get_info uves_redchain_get_info
00189 UVES_RECIPE_DEFINE(
00190     UVES_REDCHAIN_ID, UVES_REDCHAIN_DOM, uves_redchain_define_parameters,
00191     "Jonas M. Larsen", "cpl@eso.org",
00192     "Runs the full UVES reduction chain",
00193     "This recipe does a complete science reduction. It runs all necessary\n"
00194     "calibration recipes depending on the availability of raw/processed\n"
00195     "calibration frames.\n"
00196     "Input frames are all UVES raw and reference frames:\n"
00197     "formatchecks, ARC_LAMP_FORM_xxxx, xxxx=BLUE or RED,\n"
00198     "order definition frames, ORDER_FLAT_xxx,\n"
00199     "biases, BIAS_xxx,\n"
00200     "darks, DARK_xxx,\n"
00201     "flats, FLAT_xxx,\n"
00202     "arc lamps, ARC_LAMP_xxx,\n"
00203     "standard stars, STANDARD_xxx\n"
00204     "a wavelength catalogue table,LINE_REFER_TABLE, \n"
00205     "and optionally a wavelength table of bright lines,LINE_INTMON_TABLE, \n"
00206     "used only for computing Quality Control parameters.\n"
00207     "a reference standard star flux table, FLUX_STD_TABLE, \n"
00208     "a table describing the atmospheric extintion,EXTCOEFF_TABLE.\n"
00209     "optionally, science frames, SCIENCE_xxx, or UVES_SCI_POINT_xxx, \n"
00210     "or UVES_SCI_EXTND_xxx, or UVES_SCI_SLICER_xxx.\n"
00211     "For further details on the data reduction and the input frame types\n"
00212     "refer to the man page of the individual recipes.\n");
00213 
00216 /*-----------------------------------------------------------------------------
00217                               Functions code
00218  -----------------------------------------------------------------------------*/
00219 /*----------------------------------------------------------------------------*/
00225 /*----------------------------------------------------------------------------*/
00226 static int
00227 uves_redchain_define_parameters(cpl_parameterlist *parameters)
00228 {
00229     const char *recipe_id = make_str(UVES_REDCHAIN_ID);
00230     const char *subcontext = NULL;
00231 
00232     uves_par_new_value("scired",
00233                        CPL_TYPE_BOOL,
00234                        "Whether or not to do science reduction. "
00235                        "If false, only master calibration frames "
00236                        "are created. If false, either zero or all "
00237                        "necessary calibration frames must be provided "
00238                        "for each arm",
00239                        true);
00240 
00241     /*****************
00242      *    General    *
00243      *****************/
00244     if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00245         {
00246             return -1;
00247         }
00248 
00249     /******************
00250      *   Master bias  *
00251      ******************/
00252     if (uves_propagate_parameters(
00253             make_str(UVES_MBIAS_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00254         {
00255             return -1;
00256         }
00257 
00258     /******************
00259      *   Master dark  *
00260      ******************/
00261     if (uves_propagate_parameters(
00262             make_str(UVES_MDARK_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00263         {
00264             return -1;
00265         }
00266 
00267     /******************
00268      * Physical model *
00269      ******************/
00270     if (uves_propagate_parameters(
00271             make_str(UVES_PHYSMOD_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00272         {
00273             return -1;
00274         }
00275 
00276     /******************
00277      * Order position *
00278      ******************/
00279     if (uves_propagate_parameters(
00280             make_str(UVES_ORDERPOS_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00281         {
00282             return -1;
00283         }
00284 
00285     /******************
00286      *   Master flat  *
00287      ******************/
00288     if (uves_propagate_parameters(
00289             make_str(UVES_MFLAT_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00290         {
00291             return -1;
00292         }
00293 
00294     /******************
00295      *   Wave.cal.    *
00296      ******************/
00297     if (uves_propagate_parameters(
00298             make_str(UVES_WAVECAL_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00299         {
00300             return -1;
00301         }
00302 
00303     /******************
00304      *    Response    *
00305      ******************/
00306     if (uves_propagate_parameters(
00307             make_str(UVES_RESPONSE_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00308         {
00309             return -1;
00310         }
00311 
00312     /******************
00313      *    Scired      *
00314      ******************/
00315     if (uves_propagate_parameters(
00316             make_str(UVES_SCIRED_ID), parameters, make_str(UVES_REDCHAIN_ID), NULL) != 0)
00317         {
00318             return -1;
00319         }
00320 
00321     return (cpl_error_get_code() != CPL_ERROR_NONE);
00322 }
00323 
00324 /*----------------------------------------------------------------------------*/
00333 /*----------------------------------------------------------------------------*/
00334 static void
00335 IRPLIB_CONCAT2X(UVES_REDCHAIN_ID,exe)(cpl_frameset *frames,
00336                       const cpl_parameterlist *parameters, 
00337                       const char *starttime)
00338 {
00339     cpl_frameset *blue_frames = NULL;
00340     cpl_frameset *red_frames = NULL;
00341     cpl_frameset *common_frames = NULL;
00342  
00343 
00344     bool blue;
00345     bool do_science;
00346 
00347     bool run_mbias[2];     /* index 0 (==false): red  arm */
00348     bool run_mdark[2];     /* index 1 (==true ): blue arm  */
00349     bool run_mflat[2];
00350     bool run_physmod[2];
00351     bool run_orderpos[2];
00352     bool run_wavecal[2];
00353     bool run_response[2];
00354     bool run_scired[2];
00355     bool nraw_arm[2];      /* Do we have frames used exclusively
00356                               for this arm? */
00357 
00358     /* Exceptionally, this parameter is not used because this
00359        recipe does not create any products on its own. Suppress
00360        warning about unused variable */
00361     starttime = starttime;
00362 
00363     check( uves_get_parameter(parameters, NULL, make_str(UVES_REDCHAIN_ID), "scired", 
00364                               CPL_TYPE_BOOL, &do_science), "Could not read parameter");
00365 
00366     /* Check for at least one science frame */
00367     assure(!do_science ||
00368            irplib_frameset_find(frames, UVES_SCIENCE(true ))    != NULL ||
00369            irplib_frameset_find(frames, UVES_SCIENCE(false))    != NULL ||
00370            irplib_frameset_find(frames, UVES_SCI_EXTND(true ))  != NULL ||
00371            irplib_frameset_find(frames, UVES_SCI_EXTND(false))  != NULL ||
00372            irplib_frameset_find(frames, UVES_SCI_POINT(true ))  != NULL ||
00373            irplib_frameset_find(frames, UVES_SCI_POINT(false))  != NULL ||
00374            irplib_frameset_find(frames, UVES_SCI_SLICER(true )) != NULL ||
00375            irplib_frameset_find(frames, UVES_SCI_SLICER(false)) != NULL,
00376            CPL_ERROR_DATA_NOT_FOUND, "No %s, %s, %s, %s, %s, %s, %s or %s in frame set", 
00377            UVES_SCIENCE(true),
00378            UVES_SCIENCE(false),
00379            UVES_SCI_EXTND(true),
00380            UVES_SCI_EXTND(false),
00381            UVES_SCI_POINT(true),
00382            UVES_SCI_POINT(false),
00383            UVES_SCI_SLICER(true),
00384            UVES_SCI_SLICER(false));
00385         
00386     blue_frames = cpl_frameset_new();
00387     red_frames = cpl_frameset_new();
00388     common_frames = cpl_frameset_new();
00389 
00390     /* Split in blue/red frames */
00391     {
00392         cpl_frame *f = NULL;
00393 
00394         for (f = irplib_frameset_get_first(frames);
00395              f != NULL;
00396              f = irplib_frameset_get_next(frames))
00397             {
00398                 if (frame_is_needed(true, f))    /* Used in blue arm? */
00399                     {
00400                         uves_msg_debug("Found blue frame: '%s'", cpl_frame_get_tag(f));
00401                         check( cpl_frameset_insert(blue_frames, cpl_frame_duplicate(f)),
00402                                "Error extracting frame '%s' from frame set",
00403                                cpl_frame_get_tag(f));
00404                     }
00405                 if (frame_is_needed(false, f))  /* Used in red arm? */
00406                     {
00407                         uves_msg_debug("Found red frame: '%s'", cpl_frame_get_tag(f));
00408                         check( cpl_frameset_insert(red_frames, cpl_frame_duplicate(f)),
00409                                "Error extracting frame '%s' from frame set",
00410                                cpl_frame_get_tag(f));
00411                     }
00412 
00413                 if (frame_is_needed(true, f) && 
00414                     frame_is_needed(false, f))  /* Used in both arms? */
00415                     {
00416                         uves_msg_debug("Found common frame: '%s'", cpl_frame_get_tag(f));
00417                         check( cpl_frameset_insert(common_frames, cpl_frame_duplicate(f)),
00418                                "Error extracting frame '%s' from frame set",
00419                                cpl_frame_get_tag(f));
00420                     }
00421             }
00422 
00423         /* Remove all frames from input frame set */
00424         while ((f = irplib_frameset_get_first(frames)) != NULL)
00425             {
00426                 cpl_frameset_erase_frame(frames, f);
00427             }
00428     }
00429 
00430     /* Algorithm:
00431        (with purpose of failing early if we have to fail.)
00432 
00433        1) Find out which recipes to run
00434        2) Check for necessary input frames
00435        3) Execute
00436     */
00437 
00438     blue = true;
00439     do {
00440         enum uves_chip chip1 = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDL;
00441         enum uves_chip chip2 = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDU;
00442         
00443         cpl_frameset *fms = (blue) ? blue_frames : red_frames;
00444 
00445         nraw_arm[blue] = 
00446             cpl_frameset_get_size(fms) > 
00447             cpl_frameset_get_size(common_frames);
00448         
00449         uves_msg_debug("nraw_arm=%d (%s arm)", nraw_arm[blue], blue ? "blue" : "red");
00450         
00451         run_scired[blue] = do_science &&
00452             !(is_missing(fms, UVES_SCIENCE(blue), NULL) &&
00453               is_missing(fms, UVES_SCI_EXTND(blue), NULL) &&
00454               is_missing(fms, UVES_SCI_POINT(blue), NULL) &&
00455               is_missing(fms, UVES_SCI_SLICER(blue), NULL));
00456         
00457         /* If calibrations must be produced for this arm */
00458         if (run_scired[blue]
00459             ||
00460             (!do_science && nraw_arm[blue])) {
00461             
00462             /* Require master bias */
00463             run_mbias[blue] = is_missing(fms, 
00464                                          UVES_MASTER_BIAS(chip1),
00465                                          UVES_MASTER_BIAS(chip2)
00466                 );
00467             
00468             /* Run master dark, only if raw frames are available */ 
00469             run_mdark[blue] = 
00470                 !is_missing(fms, UVES_DARK(blue), NULL) ||
00471                 !is_missing(fms, UVES_PDARK(blue), NULL);
00472             
00473             /* Run orderpos if either order table is missing, 
00474                or raw frame available */
00475             run_orderpos[blue] = is_missing(fms,
00476                                             UVES_ORDER_TABLE(flames, chip1),
00477                                             UVES_ORDER_TABLE(flames, chip2)
00478                 ) ||
00479                 !is_missing(fms, UVES_ORDER_FLAT(flames, blue), NULL);
00480             
00481             /* Run master flat recipe if master flat frame is missing */
00482             run_mflat[blue] = 
00483                 is_missing(fms,
00484                            UVES_MASTER_FLAT(chip1),
00485                            UVES_MASTER_FLAT(chip2))
00486                 &&
00487                 is_missing(fms,
00488                            UVES_MASTER_DFLAT(chip1),
00489                            UVES_MASTER_DFLAT(chip2))
00490                 &&
00491                 is_missing(fms,
00492                            UVES_MASTER_IFLAT(chip1),
00493                            UVES_MASTER_IFLAT(chip2))
00494                 &&
00495                 is_missing(fms,
00496                            UVES_MASTER_SCREEN_FLAT(chip1),
00497                            UVES_MASTER_SCREEN_FLAT(chip2))
00498                 &&
00499                 is_missing(fms,
00500                            UVES_REF_TFLAT(chip1),
00501                            UVES_REF_TFLAT(chip2));
00502             
00503             
00504             /* Line tables are used as both input and output
00505                for wavecal recipe. A provided line table is 
00506                interpreted as an input table if an arc lamp 
00507                frame is also available, otherwise as output.
00508                Line tables produce by the physmod recipe are
00509                input tables. The logic is
00510                
00511                if !linetable
00512                  physmod=yes
00513                  wavecal=yes
00514                if linetable
00515                  physmod=no
00516                  if !arclamp
00517                    wavecal=no   // line table is final
00518                  if arclamp
00519                    wavecal=yes  // line table is guess
00520             */
00521             
00522             /* Run physical model if there's no
00523                line table */
00524             run_physmod[blue] = is_missing(fms,
00525                                            UVES_LINE_TABLE(flames, chip1),
00526                                            UVES_LINE_TABLE(flames, chip2))
00527                 &&
00528         is_missing(fms,
00529                UVES_GUESS_LINE_TABLE(flames, chip1),
00530                UVES_GUESS_LINE_TABLE(flames, chip2))
00531                 &&
00532                 (
00533                     is_missing(fms,
00534                                UVES_LINE_TABLE_MIDAS(chip1, 1), 
00535                                UVES_LINE_TABLE_MIDAS(chip2, 1)) ||
00536                     is_missing(fms,
00537                                UVES_LINE_TABLE_MIDAS(chip1, 2),
00538                                UVES_LINE_TABLE_MIDAS(chip2, 2)) ||
00539                     is_missing(fms,
00540                                UVES_LINE_TABLE_MIDAS(chip1, 3),
00541                                UVES_LINE_TABLE_MIDAS(chip2, 3))
00542                     );
00543                     
00544             /* Run wavecal if no line table,
00545                or if there's an arc lamp frame
00546             */
00547             run_wavecal[blue] = 
00548                 run_physmod[blue]
00549                 ||
00550         (
00551             is_missing(fms,
00552                    UVES_LINE_TABLE(flames, chip1),
00553                    UVES_LINE_TABLE(flames, chip2))
00554             &&
00555             (
00556             is_missing(fms,
00557                    UVES_LINE_TABLE_MIDAS(chip1, 1), 
00558                    UVES_LINE_TABLE_MIDAS(chip2, 1)) ||
00559             is_missing(fms,
00560                    UVES_LINE_TABLE_MIDAS(chip1, 2),
00561                    UVES_LINE_TABLE_MIDAS(chip2, 2)) ||
00562             is_missing(fms,
00563                    UVES_LINE_TABLE_MIDAS(chip1, 3),
00564                    UVES_LINE_TABLE_MIDAS(chip2, 3))
00565             )
00566             )
00567         ||
00568         (
00569             !is_missing(fms,
00570                                 UVES_ARC_LAMP(flames, blue), NULL) ||
00571                     !is_missing(fms,
00572                                 UVES_ECH_ARC_LAMP(blue), NULL)
00573                     );
00574         
00575             /* Run response only if there's a standard star.
00576                Otherwise no response correction is done */
00577             run_response[blue] = !is_missing(fms,
00578                                              UVES_STD_STAR(blue), NULL);
00579                     
00580                     
00581             uves_msg("Reduction strategy for %s arm:", (blue) ? "BLUE" : "RED");
00582             uves_msg("Run %-13s: %s", make_str(UVES_MBIAS_ID)   , (run_mbias[blue]   ) ? "Yes" : "No");
00583             uves_msg("Run %-13s: %s", make_str(UVES_MDARK_ID)   , (run_mdark[blue]   ) ? "Yes" : "No");
00584             uves_msg("Run %-13s: %s", make_str(UVES_PHYSMOD_ID) , (run_physmod[blue] ) ? "Yes" : "No");
00585             uves_msg("Run %-13s: %s", make_str(UVES_ORDERPOS_ID), (run_orderpos[blue]) ? "Yes" : "No");
00586             uves_msg("Run %-13s: %s", make_str(UVES_MFLAT_ID)   , (run_mflat[blue]   ) ? "Yes" : "No");
00587             uves_msg("Run %-13s: %s", make_str(UVES_WAVECAL_ID) , (run_wavecal[blue] ) ? "Yes" : "No");
00588             uves_msg("Run %-13s: %s", make_str(UVES_RESPONSE_ID), (run_response[blue]) ? "Yes" : "No");
00589             uves_msg("Run %-13s: %s", make_str(UVES_SCIRED_ID)  , (run_scired[blue]  ) ? "Yes" : "No");
00590     
00591         }  /* if reduce this arm */
00592         else {
00593             uves_msg("Skipping %s arm", 
00594                      (blue) ? "BLUE" : "RED");
00595 
00596             run_mbias[blue] = false;
00597             run_mdark[blue] = false;
00598             run_mflat[blue] = false;
00599             run_physmod[blue] = false;
00600             run_orderpos[blue] = false;
00601             run_wavecal[blue] = false;
00602             run_response[blue] = false;
00603         }
00604             
00605         blue = !blue;
00606     }
00607     while (!blue);
00608 
00609     /* As a service to the user, assure that required
00610        raw frames and catalogue calibration frames
00611        exist *before* doing the reduction */
00612     
00613     blue = true;
00614     do
00615         {
00616             cpl_frameset *fms = (blue) ? blue_frames : red_frames;
00617 
00618             assure( !run_mbias[blue] || !is_missing(fms, UVES_BIAS(blue), NULL), 
00619                     CPL_ERROR_DATA_NOT_FOUND,
00620                     "One or more '%s' frames needed for recipe '%s'",
00621                     UVES_BIAS(blue), make_str(UVES_MBIAS_ID));
00622             
00623             assure( !run_mdark[blue] || 
00624                     !is_missing(fms, UVES_DARK(blue), NULL) ||
00625                     !is_missing(fms, UVES_PDARK(blue), NULL),
00626                     CPL_ERROR_DATA_NOT_FOUND, 
00627                     "One or more '%s' or '%s' frames needed for recipe '%s'",
00628                     UVES_DARK(blue), UVES_PDARK(blue), make_str(UVES_MDARK_ID));
00629             
00630             assure( !run_physmod[blue] || !is_missing(fms, UVES_FORMATCHECK(flames, blue), NULL),
00631                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00632                     UVES_FORMATCHECK(flames, blue), make_str(UVES_PHYSMOD_ID));
00633             
00634             assure( !run_orderpos[blue] || !is_missing(fms, UVES_ORDER_FLAT(flames, blue), NULL),
00635                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00636                     UVES_ORDER_FLAT(flames, blue), make_str(UVES_ORDERPOS_ID));
00637             
00638             assure( !run_mflat[blue] || 
00639                     !is_missing(fms, UVES_FLAT(blue), NULL) ||
00640                     !is_missing(fms, UVES_IFLAT(blue), NULL) ||
00641                     !is_missing(fms, UVES_SCREEN_FLAT(blue), NULL) ||
00642                     !is_missing(fms, UVES_DFLAT(blue), NULL) ||
00643                     !is_missing(fms, UVES_TFLAT(blue), NULL),
00644                     CPL_ERROR_DATA_NOT_FOUND, 
00645                     "One or more '%s', '%s', '%s', '%s' or '%s' frames needed for recipe '%s'",
00646                     UVES_FLAT(blue), 
00647                     UVES_IFLAT(blue), 
00648                     UVES_SCREEN_FLAT(blue), 
00649                     UVES_DFLAT(blue), 
00650                     UVES_TFLAT(blue), 
00651                     make_str(UVES_MFLAT_ID));
00652             
00653             assure( !run_wavecal[blue] || (
00654                         !is_missing(fms, UVES_ARC_LAMP(flames, blue), NULL) ||
00655                         !is_missing(fms, UVES_ECH_ARC_LAMP(blue), NULL)),
00656                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' or '%s' needed for recipe '%s'",
00657                     UVES_ARC_LAMP(flames, blue), UVES_ECH_ARC_LAMP(blue), make_str(UVES_WAVECAL_ID));
00658             assure( !run_wavecal[blue] || !is_missing(fms, UVES_LINE_REFER_TABLE, NULL),
00659                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00660                     UVES_LINE_REFER_TABLE, make_str(UVES_WAVECAL_ID));
00661             
00662             assure( !run_response[blue] || !is_missing(fms, UVES_STD_STAR(blue), NULL), 
00663                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00664                     UVES_STD_STAR(blue), make_str(UVES_RESPONSE_ID));
00665             assure( !run_response[blue] || !is_missing(fms, UVES_FLUX_STD_TABLE, NULL), 
00666                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00667                     UVES_FLUX_STD_TABLE, make_str(UVES_RESPONSE_ID));
00668             assure( !run_response[blue] || !is_missing(fms, UVES_EXTCOEFF_TABLE, NULL), 
00669                     CPL_ERROR_DATA_NOT_FOUND, "Frame '%s' needed for recipe '%s'",
00670                     UVES_EXTCOEFF_TABLE, make_str(UVES_RESPONSE_ID));
00671             
00672             blue = !blue;
00673         }
00674     while (!blue);
00675    
00676     /* We now know which recipes to run and
00677      * that required input frames exist. Execute
00678      * chain; re-classify PRODUCT->CALIB under way
00679      */
00680     
00681     blue = true;
00682     do
00683         {
00684             enum uves_chip chip1 = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDL;
00685             enum uves_chip chip2 = (blue) ? UVES_CHIP_BLUE : UVES_CHIP_REDU;
00686 
00687             cpl_frameset *fms = (blue) ? blue_frames : red_frames;
00688 
00689             if (run_mbias[blue])
00690                 {
00691                     const char *products[2];
00692                     
00693                     int nprod = sizeof(products) / sizeof (char *);
00694                     
00695                     products[0] = UVES_MASTER_BIAS(chip1);
00696                     products[1] = UVES_MASTER_BIAS(chip2);
00697                     
00698                     if (blue) nprod /= 2;
00699                     
00700                     check( execute_recipe(make_str(UVES_MBIAS_ID), fms, parameters, products, nprod, true),
00701                            "Recipe execution failed");
00702                 }
00703             
00704             check( remove_input_frame(fms, UVES_BIAS(blue)), "Error removing input frames");
00705             
00706             if (run_mdark[blue])
00707                 {
00708                     const char *products[4];
00709                     
00710                     int nprod = sizeof(products) / sizeof (char *);
00711                     
00712                     products[0] = UVES_MASTER_DARK(chip1);
00713                     products[1] = UVES_MASTER_PDARK(chip1);
00714                     products[2] = UVES_MASTER_DARK(chip2);
00715                     products[3] = UVES_MASTER_PDARK(chip2);
00716                     
00717                     if (blue) nprod /= 2;
00718 
00719                     check( execute_recipe(
00720                                make_str(UVES_MDARK_ID), fms, parameters, products, nprod, true), 
00721                            "Recipe execution failed");
00722                 }
00723             
00724             check( remove_input_frame(fms, UVES_DARK(blue)), "Error removing input frames");
00725             check( remove_input_frame(fms, UVES_PDARK(blue)), "Error removing input frames");
00726             
00727             if (run_physmod[blue])
00728                 {
00729                     const char *products[4];
00730                     int nprod = sizeof(products) / sizeof (char *);
00731                     
00732                     products[0] = UVES_GUESS_LINE_TABLE (flames, chip1);
00733                     products[1] = UVES_GUESS_ORDER_TABLE(flames, chip1);
00734                     products[2] = UVES_GUESS_LINE_TABLE (flames, chip2);
00735                     products[3] = UVES_GUESS_ORDER_TABLE(flames, chip2);
00736                     
00737                     if (blue) nprod /= 2;
00738                     
00739                     check( execute_recipe(
00740                                make_str(UVES_PHYSMOD_ID), 
00741                                fms, parameters, products, nprod, true), 
00742                            "Recipe execution failed");
00743                 }
00744             
00745             check( remove_input_frame(fms, UVES_FORMATCHECK(flames, blue)), 
00746                    "Error removing input frames");
00747             
00748             if (run_orderpos[blue])
00749                 {
00750                     const char *products[2];
00751                     int nprod = sizeof(products) / sizeof (char *);
00752                     
00753                     products[0] = UVES_ORDER_TABLE(flames, chip1);
00754                     products[1] = UVES_ORDER_TABLE(flames, chip2);
00755                     
00756                     if (blue) nprod /= 2;
00757                             
00758                     check( execute_recipe(
00759                                make_str(UVES_ORDERPOS_ID), 
00760                                fms, parameters, products, nprod, true), 
00761                            "Recipe execution failed");
00762                 }
00763 
00764             check( remove_input_frame(fms, UVES_ORDER_FLAT(flames, blue)),
00765                    "Error removing input frames");
00766                     
00767             if (run_mflat[blue])
00768                 {
00769                     const char *products[10];
00770                             
00771                     int nprod = sizeof(products) / sizeof (char *);
00772 
00773                     products[0] = UVES_MASTER_FLAT(chip1);
00774                     products[1] = UVES_MASTER_DFLAT(chip1);
00775                     products[2] = UVES_MASTER_IFLAT(chip1);
00776                     products[3] = UVES_MASTER_TFLAT(chip1);
00777                     products[4] = UVES_MASTER_SCREEN_FLAT(chip1);
00778                     products[5] = UVES_MASTER_FLAT(chip2);
00779                     products[6] = UVES_MASTER_DFLAT(chip2);
00780                     products[7] = UVES_MASTER_IFLAT(chip2);
00781                     products[8] = UVES_MASTER_TFLAT(chip2);
00782                     products[9] = UVES_MASTER_SCREEN_FLAT(chip2);
00783                             
00784                     if (blue) nprod /= 2;
00785                             
00786                     check( execute_recipe(make_str(UVES_MFLAT_ID), 
00787                                           fms, parameters, products, nprod, true), 
00788                            "Recipe execution failed");
00789                 }
00790                     
00791             check( remove_input_frame(fms, UVES_FLAT(blue)), "Error removing input frames");
00792             check( remove_input_frame(fms, UVES_IFLAT(blue)), "Error removing input frames");
00793             check( remove_input_frame(fms, UVES_DFLAT(blue)), "Error removing input frames");
00794             check( remove_input_frame(fms, UVES_TFLAT(blue)), "Error removing input frames");
00795             check( remove_input_frame(fms, UVES_SCREEN_FLAT(blue)), "Error removing input frames");
00796                     
00797             if (run_wavecal[blue])
00798                 {
00799                     const char *products[2];
00800                             
00801                     int nprod = sizeof(products) / sizeof (char *);
00802 
00803                     products[0] = UVES_LINE_TABLE(flames, chip1);
00804                     products[1] = UVES_LINE_TABLE(flames, chip2);
00805                             
00806                     if (blue) nprod /= 2;
00807                     
00808                     check( execute_recipe(make_str(UVES_WAVECAL_ID), 
00809                                           fms, parameters, products, nprod, true), 
00810                            "Recipe execution failed");
00811                 }
00812 
00813             check( remove_input_frame(fms, UVES_ARC_LAMP(flames, blue)), 
00814            "Error removing input frames");
00815             check( remove_input_frame(fms, UVES_ECH_ARC_LAMP(blue)), 
00816            "Error removing input frames");
00817             check( remove_input_frame(fms, UVES_LINE_REFER_TABLE), 
00818            "Error removing input frames");
00819                     
00820             if (run_response[blue])
00821                 {
00822                     const char *products[2];
00823                             
00824                     int nprod = sizeof(products) / sizeof (char *);
00825 
00826                     products[0] = UVES_INSTR_RESPONSE(chip1);
00827                     products[1] = UVES_INSTR_RESPONSE(chip2);
00828                             
00829                     if (blue) nprod /= 2;
00830                             
00831                     check( execute_recipe(make_str(UVES_RESPONSE_ID), 
00832                                           fms, parameters, products, nprod, true),
00833                            "Recipe execution failed");
00834                 }
00835 
00836             check( remove_input_frame(fms, UVES_STD_STAR(blue)), "Error removing input frames");
00837             check( remove_input_frame(fms, UVES_FLUX_STD_TABLE), "Error removing input frames");
00838 
00839             if (run_scired[blue])
00840                 {
00841                     const char *products[2];
00842                             
00843                     int nprod = sizeof(products) / sizeof (char *);
00844 
00845                     products[0] = blue ? "RED_SCIENCE_BLUE" : "RED_SCIENCE_REDL";
00846                     products[1] = blue ? "RED_SCIENCE_BLUE" : "RED_SCIENCE_REDU";
00847                             
00848                     if (blue) nprod /= 2;
00849 
00850                     check( execute_recipe(make_str(UVES_SCIRED_ID), 
00851                                           fms, parameters, products, nprod, false),
00852                            "Recipe execution failed");
00853                 }
00854                     
00855             check( remove_input_frame(fms, UVES_SCIENCE(blue))   , "Error removing input frames");
00856             check( remove_input_frame(fms, UVES_SCI_EXTND(blue)) , "Error removing input frames");
00857             check( remove_input_frame(fms, UVES_SCI_POINT(blue)) , "Error removing input frames");
00858             check( remove_input_frame(fms, UVES_SCI_SLICER(blue)), "Error removing input frames");
00859                     
00860             /* Insert all product frames into recipe frame set */
00861             {
00862                 cpl_frame *f = NULL;
00863                 
00864                 for (f = irplib_frameset_get_first(fms);
00865                      f != NULL;
00866                      f = irplib_frameset_get_next(fms))
00867                     {
00868                         if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_PRODUCT)
00869                             {
00870                                 check( cpl_frameset_insert(frames, cpl_frame_duplicate(f)),
00871                                        "Error inserting product '%s' into frame set",
00872                                        cpl_frame_get_tag(f));
00873                             }
00874                     }
00875             }
00876             
00877             blue = !blue;
00878         }
00879     while(!blue);     /* For each arm */
00880     
00881   cleanup:
00882     uves_free_frameset(&blue_frames);
00883     uves_free_frameset(&red_frames);
00884     uves_free_frameset(&common_frames);
00885 
00886     return;
00887 }
00888 
00889 /* Returns true, iff frame is used for blue/red arm
00890    (note that some frames like UVES_FLUX_STD_TABLE are
00891    used for both arms) */
00892 static bool
00893 frame_is_needed(bool blue, const cpl_frame *f)
00894 {
00895     const char *tag = cpl_frame_get_tag(f);
00896     
00897     bool result = (strcmp(tag, UVES_ORDER_FLAT (flames, blue)) == 0 ||
00898                    strcmp(tag, UVES_BIAS       (blue)) == 0 ||
00899                    strcmp(tag, UVES_DARK       (blue)) == 0 ||
00900                    strcmp(tag, UVES_PDARK      (blue)) == 0 ||
00901                    strcmp(tag, UVES_FLAT       (blue)) == 0 ||
00902                    strcmp(tag, UVES_IFLAT      (blue)) == 0 ||
00903                    strcmp(tag, UVES_DFLAT      (blue)) == 0 ||
00904                    strcmp(tag, UVES_TFLAT      (blue)) == 0 ||
00905                    strcmp(tag, UVES_SCREEN_FLAT(blue)) == 0 ||
00906                    strcmp(tag, UVES_STD_STAR   (blue)) == 0 ||
00907                    strcmp(tag, UVES_FORMATCHECK(flames, blue)) == 0 ||
00908                    strcmp(tag, UVES_STD_STAR   (blue)) == 0 ||
00909                    strcmp(tag, UVES_SCIENCE    (blue)) == 0 ||
00910                    strcmp(tag, UVES_SCI_EXTND  (blue)) == 0 ||
00911                    strcmp(tag, UVES_SCI_POINT  (blue)) == 0 ||
00912                    strcmp(tag, UVES_SCI_SLICER (blue)) == 0 ||
00913                    strcmp(tag, UVES_ARC_LAMP   (flames, blue)) == 0 ||
00914                    strcmp(tag, UVES_ECH_ARC_LAMP(blue)) == 0);
00915     
00916     enum uves_chip chip;
00917     
00918     /* Loop through all blue or red chips  (1 or 2) */
00919     for (chip = uves_chip_get_first(blue); 
00920          chip != UVES_CHIP_INVALID; 
00921          chip = uves_chip_get_next(chip))
00922         {
00923             result = result || (strcmp(tag, UVES_DRS_SETUP(flames, chip)) == 0 ||
00924                                 strcmp(tag, UVES_ORDER_TABLE(flames, chip)) == 0 ||
00925                                 strcmp(tag, UVES_GUESS_ORDER_TABLE(flames, chip)) == 0 ||
00926                                 strcmp(tag, UVES_MASTER_BIAS(chip)) == 0 ||
00927                                 strcmp(tag, UVES_MASTER_DARK(chip)) == 0 ||
00928                                 strcmp(tag, UVES_MASTER_PDARK(chip)) == 0 ||
00929                                 strcmp(tag, UVES_MASTER_FLAT(chip)) == 0 ||
00930                                 strcmp(tag, UVES_MASTER_DFLAT(chip)) == 0 ||
00931                                 strcmp(tag, UVES_MASTER_IFLAT(chip)) == 0 ||
00932                                 strcmp(tag, UVES_MASTER_TFLAT(chip)) == 0 ||
00933                                 strcmp(tag, UVES_REF_TFLAT(chip)) == 0 ||
00934                                 strcmp(tag, UVES_MASTER_SCREEN_FLAT(chip)) == 0 ||
00935                                 strcmp(tag, UVES_LINE_TABLE (flames, chip)) == 0 ||
00936                                 strcmp(tag, UVES_GUESS_LINE_TABLE(flames, chip)) == 0 ||
00937                                 strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, 1)) == 0 ||
00938                                 strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, 2)) == 0 ||
00939                                 strcmp(tag, UVES_LINE_TABLE_MIDAS(chip, 3)) == 0 ||
00940                                 strcmp(tag, UVES_LINE_REFER_TABLE ) == 0 ||
00941                                 strcmp(tag, UVES_FLUX_STD_TABLE   ) == 0 ||
00942                                 strcmp(tag, UVES_EXTCOEFF_TABLE   ) == 0);
00943         }
00944     return result;
00945 }
00946 
00947 /* Execute a recipe and re-classify its products as calibration frames */
00948 static cpl_error_code
00949 execute_recipe(const char *recipe_id, 
00950                cpl_frameset *frames, const cpl_parameterlist *parameters,
00951                const char *products[],
00952                int n_products,
00953                bool reclassify)              /* Re-classify products? */
00954 {
00955   int i;
00956   cpl_frame *f = NULL;
00957 
00958   /* Remove (from frame set) any product
00959      frames already present */
00960   for (i = 0; i < n_products; i++)
00961       {
00962           if ((f = irplib_frameset_find(frames, products[i])) != NULL)
00963               {
00964                   if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_PRODUCT)
00965                       {
00966                           cpl_msg_warning(__func__, "Ignoring %s frame in '%s'. "
00967                                           "A new %s frame will now be calculated",
00968                                           products[i], cpl_frame_get_filename(f),
00969                                           products[i]);
00970                           
00971                           cpl_frameset_erase_frame(frames, f);
00972                       }
00973               }
00974       }
00975   
00976   /* Execute */
00977   check( uves_invoke_recipe(recipe_id, parameters, frames, make_str(UVES_REDCHAIN_ID), NULL),
00978          "Recipe '%s' failed", recipe_id);
00979             
00980 
00981   if (reclassify)
00982       {
00983           /* Now re-classify PRODUCT->CALIB to be used in the remaining
00984              reduction chain. Before doing that, we have to remove any
00985              calibration frame with same tag as a product (such as line tables),
00986              in order not to confuse the re-classified products with the
00987              previous calibration frames */
00988           
00989           for (i = 0; i < n_products; i++)
00990               {
00991                   if ((f = irplib_frameset_find(frames, products[i])) != NULL &&
00992                       cpl_frame_get_group(f) != CPL_FRAME_GROUP_PRODUCT)
00993                       {
00994                           uves_msg("Removing %s frame in '%s' from frameset. "
00995                                    "It is not tagged as a product",
00996                                    products[i], cpl_frame_get_filename(f));
00997                           
00998                           cpl_frameset_erase_frame(frames, f);
00999                       }
01000               }
01001           
01002           /*
01003            * Re-classify products
01004            */
01005           for (i = 0; i < n_products; i++)
01006               {
01007                   cpl_frame *found = NULL;
01008                   for (f = irplib_frameset_get_first(frames);
01009                        f != NULL;
01010                        f = irplib_frameset_get_next(frames))
01011                       {
01012                           if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_PRODUCT)
01013                               {
01014                                   if (strcmp(cpl_frame_get_tag(f), products[i]) == 0)
01015                                       {
01016                                           found = f;
01017                                       }
01018                               }
01019                       }
01020                   
01021                   if (found != NULL)
01022                       {
01023                           /* Re-classify the product as calibration frames */
01024                           uves_msg("Re-classifying %s product in '%s' PRODUCT->CALIB",
01025                                    products[i], cpl_frame_get_filename(found));
01026                           
01027                           cpl_frame_set_group(found, CPL_FRAME_GROUP_CALIB);
01028                       }
01029               }
01030           
01031           /*
01032            * Remove other products that 
01033            * are not used later  (e.g. BKG_FLAT_xxxx)
01034            */
01035           for (f = irplib_frameset_get_first(frames);
01036                f != NULL;
01037                f = irplib_frameset_get_next(frames))
01038               {
01039                   if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_PRODUCT)
01040                       {
01041                           /* Remove this product */
01042                           uves_msg("Removing product %s in '%s' from frameset. "
01043                                    "Not needed later",
01044                                    cpl_frame_get_tag(f), cpl_frame_get_filename(f));
01045                           
01046                           cpl_frameset_erase_frame(frames, f);
01047                           
01048                       }
01049               }  
01050       } /* if re-classify... */  
01051 
01052   cleanup:
01053   return cpl_error_get_code();
01054 }
01055   
01056 
01057 /* Retruns true if either frame 1 or frame 2 is not in the
01058    provided frame set 
01059 
01060    fixme: reverse the logic of this function, i.e. rename to 'contains'
01061 */
01062 static bool
01063 is_missing(const cpl_frameset *frames, const char *frame1, const char *frame2)
01064 {
01065     bool result = false;
01066     if (irplib_frameset_find_const(frames, frame1) == NULL)
01067         {
01068             uves_msg("checking for %s... no", frame1);
01069             result = true;
01070         }
01071     else
01072         {
01073             uves_msg("checking for %s... yes", frame1);
01074         }
01075     
01076     if (frame2 != NULL && strcmp(frame1, frame2) != 0)
01077         {
01078             if (irplib_frameset_find_const(frames, frame2) == NULL)
01079                 {
01080                     uves_msg("checking for %s... no", frame2);
01081                     result = true;
01082                 }
01083             else
01084                 {
01085                     uves_msg("checking for %s... yes", frame2);
01086                 }
01087         }
01088     
01089   return result;
01090 }
01091 
01092 
01093 /* Remove input frames (e.g. bias frames) along the way */
01094 static void
01095 remove_input_frame(cpl_frameset *frames, const char *tag)
01096 {
01097     int removed = cpl_frameset_erase(frames, tag);
01098 
01099     if (removed > 0)
01100         {
01101             uves_msg("Removing %d %s frame(s) from frame set", removed, tag);
01102         }
01103 
01104     return;
01105 }

Generated on Tue Jun 19 14:39:17 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6