KMOS Pipeline Reference Manual  1.2.8
kmo_reconstruct.c
00001 /* $Id: kmo_reconstruct.c,v 1.61 2013/10/08 14:55:01 erw Exp $
00002  *
00003  * This file is part of the KMOS Pipeline
00004  * Copyright (C) 2002,2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: erw $
00023  * $Date: 2013/10/08 14:55:01 $
00024  * $Revision: 1.61 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033  *                              Includes
00034  *----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 
00039 #include <cpl.h>
00040 
00041 #include "kmo_utils.h"
00042 #include "kmo_functions.h"
00043 #include "kmo_priv_reconstruct.h"
00044 #include "kmo_priv_functions.h"
00045 #include "kmo_priv_lcorr.h"
00046 #include "kmo_cpl_extensions.h"
00047 #include "kmo_dfs.h"
00048 #include "kmo_error.h"
00049 #include "kmo_utils.h"
00050 #include "kmo_constants.h"
00051 #include "kmo_debug.h"
00052 
00053 /*-----------------------------------------------------------------------------
00054  *                          Functions prototypes
00055  *----------------------------------------------------------------------------*/
00056 
00057 static int kmo_reconstruct_create(cpl_plugin *);
00058 static int kmo_reconstruct_exec(cpl_plugin *);
00059 static int kmo_reconstruct_destroy(cpl_plugin *);
00060 static int kmo_reconstruct(cpl_parameterlist *, cpl_frameset *);
00061 
00062 /*-----------------------------------------------------------------------------
00063  *                          Static variables
00064  *----------------------------------------------------------------------------*/
00065 
00066 static char kmo_reconstruct_description[] =
00067 "Data with or without noise is reconstructed into a cube using the calibration\n"
00068 "frames XCAL, YCAL and LCAL. XCAL and YCAL are generated using recipe kmo_flat,\n"
00069 "LCAL is generated using recipe kmo_wave_cal.\n"
00070 "The input data can contain noise extensions and will be reconstructed into\n"
00071 "additional extensions.\n"
00072 "If an OH spectrum is given in the SOF file the lambda axis will be corrected\n"
00073 "using the OH lines as reference.\n"
00074 "\n"
00075 "BASIC PARAMETERS:\n"
00076 "-----------------\n"
00077 "--imethod\n"
00078 "The interpolation method used for reconstruction.\n"
00079 "\n"
00080 "--detectorimage\n"
00081 "Specify if the resampled image of the input frame should be generated. There-\n"
00082 "fore all slitlets of all IFUs are aligned one next to the other. This frame\n"
00083 "serves for quality control. One can immediately see if the reconstruction was\n"
00084 "successful.\n"
00085 "\n"
00086 "--file_extension"
00087 "Set to TRUE if OBS_ID (from input frame header) should be appended to the\n"
00088 "output frame.\n"
00089 "\n"
00090 "ADVANCED PARAMETERS\n"
00091 "-------------------\n"
00092 "--flux\n"
00093 "Specify if flux conservation should be applied.\n"
00094 "\n"
00095 "--neighborhoodRange\n"
00096 "Defines the range to search for neighbors during reconstruction\n"
00097 "\n"
00098 "--b_samples\n"
00099 "The number of samples in spectral direction for the reconstructed cube. Ideal-\n"
00100 "ly this number should be greater than 2048, the detector size.\n"
00101 "\n"
00102 "--b_start\n"
00103 "--b_end\n"
00104 "Used to define manually the start and end wavelength for the reconstructed\n"
00105 "cube. By default the internally defined values are used.\n"
00106 "\n"
00107 "--pix_scale\n"
00108 "Change the pixel scale [arcsec]. Default of 0.2\" results into cubes of\n"
00109 "14x14pix, a scale of 0.1\" results into cubes of 28x28pix, etc.\n"
00110 "\n"
00111 "--xcal_interpolation\n"
00112 "If TRUE interpolate the pixel position in the slitlet (xcal) using the two\n"
00113 "closest rotator angles in the calibration file. Otherwise take the values\n"
00114 "of the closest rotator angle\n"
00115 "\n"
00116 "-------------------------------------------------------------------------------\n"
00117 "  Input files:\n"
00118 "\n"
00119 "   DO                  KMOS                                                    \n"
00120 "   category            Type     Explanation                    Required #Frames\n"
00121 "   --------            -----    -----------                    -------- -------\n"
00122 "   DARK    or          RAW/F2D  data with                          Y       1   \n"
00123 "   FLAT_ON or          RAW/F2D  or without noise                               \n"
00124 "   ARC_ON  or          RAW/F2D                                                 \n"
00125 "   OBJECT  or          RAW                                                     \n"
00126 "   STD     or          RAW                                                     \n"
00127 "   SCIENCE             RAW                                                     \n"
00128 "   XCAL                F2D      x-direction calib. frame           Y       1   \n"
00129 "   YCAL                F2D      y-direction calib. frame           Y       1   \n"
00130 "   LCAL                F2D      Wavelength calib. frame            Y       1   \n"
00131 "   WAVE_BAND           F2L      Table with start-/end-wavelengths  Y       1   \n"
00132 "   OH_SPEC             F1S      Vector holding OH lines            N       1   \n"
00133 "\n"
00134 "  Output files:\n"
00135 "\n"
00136 "   DO                    KMOS\n"
00137 "   category              Type     Explanation\n"
00138 "   --------              -----    -----------\n"
00139 "   CUBE_DARK   or        F3I      Reconstructed cube   \n"
00140 "   CUBE_FLAT   or        RAW/F2D  with or without noise\n"
00141 "   CUBE_ARC    or                                      \n"
00142 "   CUBE_OBJECT or                                      \n"
00143 "   CUBE_STD    or                                      \n"
00144 "   CUBE_SCIENCE                                        \n"
00145 "-------------------------------------------------------------------------------\n"
00146 "\n";
00147 
00148 /*-----------------------------------------------------------------------------
00149  *                              Functions code
00150  *----------------------------------------------------------------------------*/
00151 
00168 int cpl_plugin_get_info(cpl_pluginlist *list)
00169 {
00170     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00171     cpl_plugin *plugin = &recipe->interface;
00172 
00173     cpl_plugin_init(plugin,
00174                         CPL_PLUGIN_API,
00175                         KMOS_BINARY_VERSION,
00176                         CPL_PLUGIN_TYPE_RECIPE,
00177                         "kmo_reconstruct",
00178                         "Performs the cube reconstruction "
00179                         "using different interpolation methods.",
00180                         kmo_reconstruct_description,
00181                         "Alex Agudo Berbel",
00182                         "kmos-spark@mpe.mpg.de",
00183                         kmos_get_license(),
00184                         kmo_reconstruct_create,
00185                         kmo_reconstruct_exec,
00186                         kmo_reconstruct_destroy);
00187 
00188     cpl_pluginlist_append(list, plugin);
00189 
00190     return 0;
00191 }
00192 
00200 static int kmo_reconstruct_create(cpl_plugin *plugin)
00201 {
00202     cpl_recipe *recipe;
00203     cpl_parameter *p;
00204 
00205     /* Check that the plugin is part of a valid recipe */
00206     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00207         recipe = (cpl_recipe *)plugin;
00208     else
00209         return -1;
00210 
00211     /* Create the parameters list in the cpl_recipe object */
00212     recipe->parameters = cpl_parameterlist_new();
00213 
00214     /* Fill the parameters list */
00215     /* --imethod */
00216     p = cpl_parameter_new_value("kmos.kmo_reconstruct.imethod",
00217                                 CPL_TYPE_STRING,
00218                                 "Method to use for interpolation. "
00219                                 "[\"NN\" (nearest neighbour), "
00220                                 "\"lwNN\" (linear weighted nearest neighbor), "
00221                                 "\"swNN\" (square weighted nearest neighbor), "
00222                                 "\"MS\" (Modified Shepard's method)"
00223                                 "\"CS\" (Cubic spline)]",
00224                                 "kmos.kmo_reconstruct",
00225                                 "CS");
00226     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00227     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00228     cpl_parameterlist_append(recipe->parameters, p);
00229 
00230     /* --neighborhoodRange */
00231     p = cpl_parameter_new_value("kmos.kmo_reconstruct.neighborhoodRange",
00232                                 CPL_TYPE_DOUBLE,
00233                                 "Defines the range to search for neighbors. "
00234                                 "in pixels",
00235                                 "kmos.kmo_reconstruct",
00236                                 1.001);
00237     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00238     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00239     cpl_parameterlist_append(recipe->parameters, p);
00240 
00241     /* --flux */
00242     p = cpl_parameter_new_value("kmos.kmo_reconstruct.flux",
00243                                 CPL_TYPE_BOOL,
00244                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00245                                 "kmos.kmo_reconstruct",
00246                                 FALSE);
00247     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00248     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00249     cpl_parameterlist_append(recipe->parameters, p);
00250 
00251     /* --detectorimage */
00252     p = cpl_parameter_new_value("kmos.kmo_reconstruct.detectorimage",
00253                                 CPL_TYPE_BOOL,
00254                                 "TRUE: if resampled detector frame should be "
00255                                 "created, FALSE: otherwise",
00256                                 "kmos.kmo_reconstruct",
00257                                 FALSE);
00258     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detimg");
00259     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00260     cpl_parameterlist_append(recipe->parameters, p);
00261 
00262     /* --file_extension */
00263     p = cpl_parameter_new_value("kmos.kmo_reconstruct.file_extension",
00264                                 CPL_TYPE_BOOL,
00265                                 "TRUE: if OBS_ID keyword should be appended to "
00266                                 "output frames, FALSE: otherwise",
00267                                 "kmos.kmo_reconstruct",
00268                                 FALSE);
00269     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension");
00270     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00271     cpl_parameterlist_append(recipe->parameters, p);
00272 
00273     /* --pix_scale */
00274     p = cpl_parameter_new_value("kmos.kmo_reconstruct.pix_scale",
00275                                 CPL_TYPE_DOUBLE,
00276                                 "Change the pixel scale [arcsec]. "
00277                                 "Default of 0.2\" results into cubes of 14x14pix, "
00278                                 "a scale of 0.1\" results into cubes of 28x28pix, "
00279                                 "etc.",
00280                                 "kmos.kmo_reconstruct",
00281                                 KMOS_PIX_RESOLUTION);
00282     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pix_scale");
00283     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00284     cpl_parameterlist_append(recipe->parameters, p);
00285 
00286     /* --dev_flip */
00287     p = cpl_parameter_new_value("kmos.kmo_reconstruct.dev_flip",
00288                                 CPL_TYPE_BOOL,
00289                                 "INTENDED FOR PIPELINE DEVELOPERS ONLY: "
00290                                 "Set this parameter to TRUE if the wavelengths "
00291                                 "are ascending on the detector from bottom to "
00292                                 "top (only for old simulation data).",
00293                                 "kmos.kmo_reconstruct",
00294                                 FALSE);
00295     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_flip");
00296     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00297     cpl_parameterlist_append(recipe->parameters, p);
00298 
00299     /* --xcal_interpolation */
00300     p = cpl_parameter_new_value("kmos.kmo_reconstruct.xcal_interpolation",
00301                                 CPL_TYPE_BOOL,
00302                                 "TRUE: Interpolate xcal between rotator angles. FALSE: otherwise",
00303                                 "kmos.kmo_reconstruct",
00304                                 TRUE);
00305     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xcal_interpolation");
00306     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00307     cpl_parameterlist_append(recipe->parameters, p);
00308 
00309     // add parameters for band-definition
00310     kmo_band_pars_create(recipe->parameters,
00311                          "kmos.kmo_reconstruct");
00312 
00313     return 0;
00314 }
00315 
00321 static int kmo_reconstruct_exec(cpl_plugin *plugin)
00322 {
00323     cpl_recipe  *recipe;
00324 
00325     /* Get the recipe out of the plugin */
00326     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00327         recipe = (cpl_recipe *)plugin;
00328     else return -1;
00329 
00330     return kmo_reconstruct(recipe->parameters, recipe->frames);
00331 }
00332 
00338 static int kmo_reconstruct_destroy(cpl_plugin *plugin)
00339 {
00340     cpl_recipe *recipe;
00341 
00342     /* Get the recipe out of the plugin */
00343     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00344         recipe = (cpl_recipe *)plugin;
00345     else return -1 ;
00346 
00347     cpl_parameterlist_delete(recipe->parameters);
00348     return 0 ;
00349 }
00350 
00365 static int kmo_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset)
00366 {
00367     int                 ret_val                 = 0,
00368                         nr_devices              = 0,
00369                         i                       = 0,
00370                         j                       = 0,
00371                         flux                    = FALSE,
00372                         background              = FALSE,
00373                         index                   = 0,
00374                         detectorimage           = 0,
00375                         *bounds                 = NULL,
00376                         ifu_nr                  = 0,
00377                         obs_id                  = 0,
00378                         file_extension          = FALSE,
00379                         dev_flip                = FALSE,
00380                         xcal_interpolation      = FALSE,
00381                         detImgCube              = FALSE,
00382                         l = 0, x = 0, y = 0;
00383     float               *pdet_img_data          = NULL,
00384                         *pdet_img_noise         = NULL,
00385                         *slice                  = NULL;
00386     double              neighborhoodRange       = 1.001,
00387                         pix_scale               = 0.0;
00388 
00389     const char          *imethod                = NULL,
00390                         *input_frame_name       = NULL,
00391                         *output_frame_name      = NULL,
00392                         *filter_id              = NULL,
00393                         *filter_id_tmp          = NULL,
00394                         *tmp_str                = NULL;
00395     char                *keyword                = NULL,
00396                         *filename_cube          = NULL,
00397                         *filename_img           = NULL,
00398 //                        *fn_lut                 = NULL,
00399                         *suffix                 = NULL,
00400                         *obs_suffix             = NULL,
00401                         *my_filter_id           = NULL,
00402                         *extname                = NULL;
00403     cpl_image           *lcal                   = NULL,
00404                         *det_img_data[KMOS_NR_DETECTORS],
00405                         *det_img_noise[KMOS_NR_DETECTORS],
00406                         *tmp_img                = NULL;
00407     cpl_imagelist       *cube_data              = NULL,
00408                         *cube_noise             = NULL;
00409     cpl_frame           *rec_frame              = NULL,
00410                         *xcal_frame             = NULL,
00411                         *ycal_frame             = NULL,
00412                         *lcal_frame             = NULL,
00413                         *ref_spectrum_frame     = NULL;
00414     cpl_propertylist    *main_header           = NULL,
00415                         *sub_header            = NULL,
00416                         *sub_header_orig       = NULL,
00417                         *actual_sub_header     = NULL,
00418                         *tmp_header            = NULL;
00419     cpl_table           *band_table            = NULL;
00420     gridDefinition      gd;
00421     main_fits_desc      desc1,
00422                         desc2;
00423     cpl_polynomial      *lcorr_coeffs = NULL;
00424 
00425     for (i = 0; i < KMOS_NR_DETECTORS; i++) {
00426         det_img_data[i] = NULL;
00427         det_img_noise[i] = NULL;
00428     }
00429 
00430     KMO_TRY
00431     {
00432         kmo_init_fits_desc(&desc1);
00433         kmo_init_fits_desc(&desc2);
00434 
00435         // --- check input ---
00436         KMO_TRY_ASSURE((parlist != NULL) &&
00437                        (frameset != NULL),
00438                        CPL_ERROR_NULL_INPUT,
00439                        "Not all input data is provided!");
00440 
00441         KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, DARK) == 1) ||
00442                        (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) ||
00443                        (cpl_frameset_count_tags(frameset, ARC_ON) == 1) ||
00444                        (cpl_frameset_count_tags(frameset, OBJECT) == 1) ||
00445                        (cpl_frameset_count_tags(frameset, STD) == 1) ||
00446                        (cpl_frameset_count_tags(frameset, SCIENCE) == 1),
00447                        CPL_ERROR_NULL_INPUT,
00448                        "A data frame (DARK, FLAT_ON, ARC_ON, OBJECT, STD or SCIENCE) must "
00449                        "be provided!");
00450 
00451         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00452                        CPL_ERROR_FILE_NOT_FOUND,
00453                        "XCAL frame missing in frameset!!");
00454 
00455         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00456                        CPL_ERROR_FILE_NOT_FOUND,
00457                        "YCAL frame missing in frameset!!");
00458 
00459         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00460                        CPL_ERROR_FILE_NOT_FOUND,
00461                        "LCAL frame missing in frameset!!");
00462 
00463         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00464                        CPL_ERROR_FILE_NOT_FOUND,
00465                        "WAVE_BAND frame missing in frameset!!");
00466 
00467         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_reconstruct") == 1,
00468                        CPL_ERROR_ILLEGAL_INPUT,
00469                        "Cannot identify RAW and CALIB frames!");
00470 
00471         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 ||
00472                        cpl_frameset_count_tags(frameset, OH_SPEC) == 1,
00473                        CPL_ERROR_ILLEGAL_INPUT,
00474                        "Only a single reference spectrum can be provided!");
00475 
00476         // --- get parameters ---
00477         cpl_msg_info("", "--- Parameter setup for kmo_reconstruct ---");
00478 
00479         KMO_TRY_EXIT_IF_NULL(
00480             imethod = kmo_dfs_get_parameter_string(parlist,
00481                                               "kmos.kmo_reconstruct.imethod"));
00482 
00483         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00484                        (strcmp(imethod, "lwNN") == 0) ||
00485                        (strcmp(imethod, "swNN") == 0) ||
00486                        (strcmp(imethod, "MS") == 0) ||
00487                        (strcmp(imethod, "CS") == 0),
00488                        CPL_ERROR_ILLEGAL_INPUT,
00489                        "imethod must be either \"NN\", \"lwNN\", "
00490                        "\"swNN\", \"MS\" or \"CS\"!");
00491 
00492         KMO_TRY_EXIT_IF_ERROR(
00493             kmo_dfs_print_parameter_help(parlist,
00494                                         "kmos.kmo_reconstruct.imethod"));
00495 
00496         flux = kmo_dfs_get_parameter_bool(parlist,
00497                                           "kmos.kmo_reconstruct.flux");
00498 
00499         KMO_TRY_ASSURE((flux == 0) ||
00500                        (flux == 1),
00501                        CPL_ERROR_ILLEGAL_INPUT,
00502                        "flux must be either FALSE or TRUE!");
00503 
00504         KMO_TRY_EXIT_IF_ERROR(
00505             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.flux"));
00506 
00507         detectorimage = kmo_dfs_get_parameter_bool(parlist,
00508                                           "kmos.kmo_reconstruct.detectorimage");
00509 
00510         KMO_TRY_ASSURE((detectorimage == 0) ||
00511                        (detectorimage == 1),
00512                        CPL_ERROR_ILLEGAL_INPUT,
00513                        "detectorimage must be either 0 or 1 !");
00514 
00515         KMO_TRY_EXIT_IF_ERROR(
00516             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.detectorimage"));
00517 
00518         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00519                 "kmos.kmo_reconstruct.neighborhoodRange");
00520         KMO_TRY_CHECK_ERROR_STATE();
00521         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00522                 CPL_ERROR_ILLEGAL_INPUT,
00523                 "neighborhoodRange must be greater than 0.0");
00524         KMO_TRY_EXIT_IF_ERROR(
00525             kmo_dfs_print_parameter_help(parlist,
00526                                      "kmos.kmo_reconstruct.neighborhoodRange"));
00527 
00528         kmo_band_pars_load(parlist, "kmos.kmo_reconstruct");
00529 
00530         file_extension = kmo_dfs_get_parameter_bool(parlist,
00531                                         "kmos.kmo_reconstruct.file_extension");
00532         KMO_TRY_CHECK_ERROR_STATE();
00533         KMO_TRY_EXIT_IF_ERROR(
00534            kmo_dfs_print_parameter_help(parlist,
00535                                        "kmos.kmo_reconstruct.file_extension"));
00536 
00537         pix_scale = kmo_dfs_get_parameter_double(parlist,
00538                                         "kmos.kmo_reconstruct.pix_scale");
00539         KMO_TRY_CHECK_ERROR_STATE();
00540         KMO_TRY_EXIT_IF_ERROR(
00541            kmo_dfs_print_parameter_help(parlist,
00542                                        "kmos.kmo_reconstruct.pix_scale"));
00543         KMO_TRY_ASSURE((pix_scale >= 0.01) &&
00544                        (pix_scale <= 0.4),
00545                        CPL_ERROR_ILLEGAL_INPUT,
00546                        "pix_scale must be between 0.01 and 0.4 (results in cubes "
00547                        "with 7x7 to 280x280 pixels)!");
00548 
00549         dev_flip = kmo_dfs_get_parameter_bool(parlist,
00550                                            "kmos.kmo_reconstruct.dev_flip");
00551         KMO_TRY_CHECK_ERROR_STATE();
00552         KMO_TRY_EXIT_IF_ERROR(
00553             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.dev_flip"));
00554         KMO_TRY_ASSURE((dev_flip == TRUE) ||
00555                        (dev_flip == FALSE),
00556                        CPL_ERROR_ILLEGAL_INPUT,
00557                        "dev_flip must be TRUE or FALSE!");
00558 
00559         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist,
00560                                            "kmos.kmo_reconstruct.xcal_interpolation");
00561         KMO_TRY_CHECK_ERROR_STATE();
00562         KMO_TRY_EXIT_IF_ERROR(
00563             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.xcal_interpolation"));
00564         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00565                        (xcal_interpolation == FALSE),
00566                        CPL_ERROR_ILLEGAL_INPUT,
00567                        "xcal_interpolation must be TRUE or FALSE!");
00568 
00569 
00570         cpl_msg_info("", "-------------------------------------------");
00571 
00572         // load descriptor and header of data frame to reconstruct
00573         if (cpl_frameset_count_tags(frameset, DARK) == 1) {
00574             input_frame_name = DARK;
00575             output_frame_name = CUBE_DARK;
00576         } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) {
00577             input_frame_name = FLAT_ON;
00578             output_frame_name = CUBE_FLAT;
00579         } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) {
00580             input_frame_name = ARC_ON;
00581             output_frame_name = CUBE_ARC;
00582         } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) {
00583             input_frame_name = OBJECT;
00584             output_frame_name = CUBE_OBJECT;
00585         } else if (cpl_frameset_count_tags(frameset, STD) == 1) {
00586             input_frame_name = STD;
00587             output_frame_name = CUBE_STD;
00588         } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) {
00589             input_frame_name = SCIENCE;
00590             output_frame_name = CUBE_SCIENCE;
00591         }
00592 
00593         // assure that filters, grating and rotation offsets match for
00594         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00595         // frames)
00596         // check if filter_id and grating_id match for all detectors
00597         KMO_TRY_EXIT_IF_ERROR(
00598             kmo_check_frame_setup(frameset, XCAL, YCAL,
00599                                        TRUE, FALSE, TRUE));
00600         KMO_TRY_EXIT_IF_ERROR(
00601             kmo_check_frame_setup(frameset, XCAL, LCAL,
00602                                        TRUE, FALSE, TRUE));
00603 
00604         if (cpl_frameset_count_tags(frameset, DARK) != 1) {
00605 
00606             // check if filters, gratings and rotator offset match
00607             // (except for DARK frames)
00608             KMO_TRY_EXIT_IF_ERROR(
00609                 kmo_check_frame_setup(frameset, XCAL, input_frame_name,
00610                                            TRUE, FALSE, FALSE));
00611 /*
00612             // check if rotator offset don't differ to much
00613             cpl_frame        *f1 = NULL, *f2 = NULL;
00614             cpl_propertylist *h1 = NULL, *h2 = NULL;
00615             char             *kw = NULL;
00616             double           tmp_dbl1 = 0.0, tmp_dbl2 = 0.0;
00617 
00618             KMO_TRY_EXIT_IF_NULL(
00619                 f1 = kmo_dfs_get_frame(frameset, XCAL));
00620 
00621             KMO_TRY_EXIT_IF_NULL(
00622                 f2 = kmo_dfs_get_frame(frameset, input_frame_name));
00623             h1 = kmclipm_propertylist_load(cpl_frame_get_filename(f1), 0);
00624             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00625                 cpl_msg_error("","File not found: %s!",
00626                               cpl_frame_get_filename(f1));
00627                 KMO_TRY_CHECK_ERROR_STATE();
00628             }
00629 
00630             h2 = kmclipm_propertylist_load(cpl_frame_get_filename(f2), 0);
00631             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00632                 cpl_msg_error("","File not found: %s!",
00633                               cpl_frame_get_filename(f2));
00634                 KMO_TRY_CHECK_ERROR_STATE();
00635             }
00636             KMO_TRY_EXIT_IF_NULL(
00637                 kw = cpl_sprintf("%s", ROTANGLE));
00638             tmp_dbl1 = cpl_propertylist_get_double(h1, kw);
00639             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00640                 KMO_TRY_ASSURE(1 == 0,
00641                                CPL_ERROR_ILLEGAL_INPUT,
00642                                "keyword \n%s\n of frame %s is missing!",
00643                                keyword, XCAL);
00644             }
00645 
00646             tmp_dbl2 = cpl_propertylist_get_double(h2, kw);
00647             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00648                 KMO_TRY_ASSURE(1 == 0,
00649                                CPL_ERROR_ILLEGAL_INPUT,
00650                                "keyword \n%s\n of frame %s is missing!",
00651                                keyword, input_frame_name);
00652             }
00653 
00654             // strip angles below 0 deg and above 360 deg
00655             kmclipm_strip_angle(&tmp_dbl1);
00656             kmclipm_strip_angle(&tmp_dbl2);
00657 
00658             if (fabs(tmp_dbl1 - tmp_dbl2) > 30.) {
00659                 if ((fabs(tmp_dbl1) < 0.001) && (tmp_dbl2>330) && (tmp_dbl2<360)) {
00660                     // singularity!
00661                     // we have rot=0 for XCAL and rot>330 | rot<360 for input frame
00662                 } else {
00663                 cpl_msg_warning("","The angle of the calibration files (%g deg) "
00664                                 "and the angle of the frame to reconstruct"
00665                                 " (%g deg) differ by %g deg! Think about using "
00666                                 "calibration files matching better the actual "
00667                                 "rotator offset (ESO OCS ROT NAANGLE)",
00668                                 tmp_dbl1, tmp_dbl2,
00669                                 fabs(tmp_dbl1 - tmp_dbl2));
00670                 }
00671             }
00672 
00673             cpl_propertylist_delete(h1); h1 = NULL;
00674             cpl_propertylist_delete(h2); h2 = NULL;
00675             cpl_free(kw); kw = NULL;
00676 */
00677         }
00678 
00679         KMO_TRY_EXIT_IF_NULL(
00680             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00681         KMO_TRY_EXIT_IF_NULL(
00682             rec_frame = kmo_dfs_get_frame(frameset, input_frame_name));
00683         KMO_TRY_EXIT_IF_NULL(
00684             suffix = kmo_dfs_get_suffix(rec_frame, TRUE, TRUE));
00685 
00686         KMO_TRY_EXIT_IF_ERROR(
00687             kmo_check_frame_setup_md5_xycal(frameset));
00688         KMO_TRY_EXIT_IF_ERROR(
00689             kmo_check_frame_setup_md5(frameset));
00690 
00691         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
00692         cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)");
00693         cpl_msg_info("", "-------------------------------------------");
00694 
00695         KMO_TRY_EXIT_IF_NULL(
00696             main_header = kmo_dfs_load_primary_header(frameset,
00697                                                       input_frame_name));
00698 
00699         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
00700             if (cpl_propertylist_has(main_header, ORIGFILE)) {
00701                 KMO_TRY_EXIT_IF_NULL(
00702                     tmp_str = cpl_propertylist_get_string(main_header, ORIGFILE));
00703                 if (strstr(tmp_str, "OBS") != NULL) {
00704                     // we are reconstructing an OBS-frame, allow OH_SPEC correction
00705                     KMO_TRY_EXIT_IF_NULL(
00706                         ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
00707                 } else {
00708                     cpl_msg_warning("", "Supplied OH_SPEC is ignored since a calibration frame is being reconstructed.");
00709                 }
00710             } else {
00711                 cpl_msg_warning("", "The supplied frame %s is assumed to be a science frame. If it is a calibration frame, omit OH_SPEC from sof-file", input_frame_name);
00712                 KMO_TRY_EXIT_IF_NULL(
00713                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
00714             }
00715         }
00716 
00717         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(rec_frame));
00718         KMO_TRY_CHECK_ERROR_STATE();
00719 
00720         KMO_TRY_ASSURE(((desc1.nr_ext == KMOS_NR_DETECTORS) ||
00721                         ((desc1.nr_ext == 2*KMOS_NR_DETECTORS))) &&
00722                        (desc1.ex_badpix == FALSE) &&
00723                        ((desc1.fits_type == raw_fits) ||
00724                         (desc1.fits_type == f2d_fits)) &&
00725                        (desc1.frame_type == detector_frame),
00726                        CPL_ERROR_ILLEGAL_INPUT,
00727                        "The frame to reconstruct isn't in the correct format!!!"
00728                        "Exactly 3 frames, or 6 with noise are expected!");
00729 
00730         if (!desc1.ex_noise) {
00731             nr_devices = desc1.nr_ext;
00732         } else {
00733             nr_devices = desc1.nr_ext / 2;
00734         }
00735 
00736         // compare descriptor of XCAL and data frame to reconstruct
00737         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00738         KMO_TRY_CHECK_ERROR_STATE();
00739 
00740         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00741                        (desc1.ex_badpix == desc2.ex_badpix) &&
00742                        (desc1.frame_type == desc2.frame_type),
00743                        CPL_ERROR_ILLEGAL_INPUT,
00744                        "XCAL isn't in the correct format!!!");
00745 
00746         kmo_free_fits_desc(&desc2);
00747 
00748         // compare descriptor of YCAL and data frame to reconstruct
00749         kmo_init_fits_desc(&desc2);
00750 
00751         KMO_TRY_EXIT_IF_NULL(
00752             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00753 
00754         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00755         KMO_TRY_CHECK_ERROR_STATE();
00756 
00757         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00758                        (desc1.ex_badpix == desc2.ex_badpix) &&
00759                        (desc1.frame_type == desc2.frame_type),
00760                        CPL_ERROR_ILLEGAL_INPUT,
00761                        "YCAL isn't in the correct format!!!");
00762 
00763         kmo_free_fits_desc(&desc2);
00764 
00765         // compare descriptor of LCAL and data frame to reconstruct
00766         kmo_init_fits_desc(&desc2);
00767 
00768         KMO_TRY_EXIT_IF_NULL(
00769             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00770 
00771         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00772         KMO_TRY_CHECK_ERROR_STATE();
00773 
00774         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00775                        (desc1.ex_badpix == desc2.ex_badpix) &&
00776                        (desc1.frame_type == desc2.frame_type),
00777                        CPL_ERROR_ILLEGAL_INPUT,
00778                        "LCAL isn't in the correct format!!!");
00779 
00780         kmo_free_fits_desc(&desc2);
00781 
00782         //
00783         // --- update & save primary header ---
00784         //
00785         KMO_TRY_EXIT_IF_NULL(
00786             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
00787 
00788         // assert that filters have correct IDs and that all detectors of all
00789         // input frames have the same filter set
00790         for (i = 1; i <= nr_devices; i++) {
00791             // ESO INS FILTi ID
00792             KMO_TRY_EXIT_IF_NULL(
00793                 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i,
00794                                       IFU_FILTID_POSTFIX));
00795 
00796             KMO_TRY_EXIT_IF_NULL(
00797                 filter_id = cpl_propertylist_get_string(tmp_header, keyword));
00798 
00799             KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) ||
00800                            (strcmp(filter_id, "YJ") == 0) ||
00801                            (strcmp(filter_id, "H") == 0) ||
00802                            (strcmp(filter_id, "K") == 0) ||
00803                            (strcmp(filter_id, "HK") == 0),
00804                            CPL_ERROR_ILLEGAL_INPUT,
00805                            "Filter ID in primary header of LCAL frame must "
00806                            "be either \"IZ\", \"YJ\", \"H\", \"K\" or "
00807                            "\"HK\" !");
00808 
00809             if (strcmp(input_frame_name, DARK) != 0) {
00810                 // dark needn't to be taken with filter!
00811 
00812                 KMO_TRY_EXIT_IF_NULL(
00813                     filter_id_tmp = cpl_propertylist_get_string(main_header,
00814                                                                 keyword));
00815                 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_tmp) == 0,
00816                                CPL_ERROR_ILLEGAL_INPUT,
00817                                "Filter IDs must be the same for LCAL frame and "
00818                                "the frame to reconstruct!"
00819                                "Detector No.: %d\nLCAL: %s\n%s: %s\n",
00820                                i, filter_id, input_frame_name, filter_id_tmp);
00821             }
00822             cpl_free(keyword); keyword = NULL;
00823         }
00824         KMO_TRY_EXIT_IF_NULL(
00825             my_filter_id = cpl_strdup(filter_id));
00826         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00827 
00828         obs_id = cpl_propertylist_get_int(main_header, OBS_ID);
00829         KMO_TRY_CHECK_ERROR_STATE();
00830 
00831         KMO_TRY_EXIT_IF_NULL(
00832             filename_cube = cpl_sprintf("%s", output_frame_name));
00833         KMO_TRY_EXIT_IF_NULL(
00834             filename_img = cpl_sprintf("%s", DET_IMG_REC));
00835         if (file_extension) {
00836             KMO_TRY_EXIT_IF_NULL(
00837                 obs_suffix = cpl_sprintf("%s%d", "_", obs_id));
00838         } else {
00839             KMO_TRY_EXIT_IF_NULL(
00840                 obs_suffix = cpl_sprintf("%s", ""));
00841         }
00842 
00843         KMO_TRY_EXIT_IF_ERROR(
00844             kmo_dfs_save_main_header(frameset, filename_cube, obs_suffix,
00845                                      rec_frame, NULL, parlist, cpl_func));
00846 
00847         // setup grid definition, wavelength start and end points will be set
00848         // in the detector loop
00849         KMO_TRY_EXIT_IF_ERROR(
00850             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale, 0.));
00851 
00852         KMO_TRY_EXIT_IF_NULL(
00853             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
00854 
00855         KMO_TRY_EXIT_IF_NULL(
00856             bounds = kmclipm_extract_bounds(tmp_header));
00857         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00858 
00859         if (detectorimage == TRUE) {
00860             KMO_TRY_EXIT_IF_ERROR(
00861                 kmo_dfs_save_main_header(frameset, filename_img, obs_suffix,
00862                                          rec_frame, NULL, parlist, cpl_func));
00863         }
00864 
00865         /* loop through all detectors */
00866         for (i = 1; i <= nr_devices; i++) {
00867             cpl_msg_info("","Processing detector No. %d", i);
00868 
00869             // load lcal
00870             // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
00871             // doesn't differ too much with different ROTANGLEs.
00872             double rotangle_found;
00873             print_cal_angle_msg_once = FALSE;
00874             print_xcal_angle_msg_once = FALSE;
00875             KMO_TRY_EXIT_IF_NULL(
00876                 lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0.,
00877                                               FALSE, NULL, &rotangle_found, -1, 0, 0));
00878             if (i==1) {
00879                 print_cal_angle_msg_once = TRUE;
00880                 print_xcal_angle_msg_once = TRUE;
00881             }
00882             char *tmp_band_method = getenv("KMO_BAND_METHOD");
00883             int band_method = 0;
00884             if (tmp_band_method != NULL) {
00885                 band_method = atoi(tmp_band_method);
00886             }
00887 
00888             KMO_TRY_EXIT_IF_NULL(
00889                 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE));
00890 
00891             KMO_TRY_EXIT_IF_ERROR(
00892                 kmclipm_setup_grid_band_lcal(&gd, lcal, my_filter_id,
00893                                              band_method, band_table));
00894             cpl_table_delete(band_table); band_table = NULL;
00895 
00896             cpl_image_delete(lcal); lcal = NULL;
00897 
00898             if (detectorimage == TRUE) {
00899                 KMO_TRY_EXIT_IF_NULL(
00900                     det_img_data[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR,
00901                                                       gd.l.dim, CPL_TYPE_FLOAT));
00902                 KMO_TRY_EXIT_IF_NULL(
00903                     pdet_img_data = cpl_image_get_data_float(det_img_data[i-1]));
00904 
00905                 KMO_TRY_EXIT_IF_NULL(
00906                     det_img_noise[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR,
00907                                                       gd.l.dim, CPL_TYPE_FLOAT));
00908                 KMO_TRY_EXIT_IF_NULL(
00909                     pdet_img_noise = cpl_image_get_data_float(det_img_noise[i-1]));
00910             }
00911 
00912 
00913             for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
00914                 /* update sub-header */
00915                 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
00916 
00917                 /* load raw image and sub-header*/
00918                 KMO_TRY_EXIT_IF_NULL(
00919                     sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name,
00920                                                          i, FALSE));
00921                 KMO_TRY_EXIT_IF_NULL(
00922                     sub_header_orig = cpl_propertylist_duplicate(sub_header));
00923 
00924                 // check if IFU is valid according to main header keywords &
00925                 // calibration files
00926 
00927                 if (getenv("KMOS_RECONSTRUCT_ALL") == NULL) {
00928                     KMO_TRY_EXIT_IF_NULL(
00929                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr,
00930                                               IFU_VALID_POSTFIX));
00931                     KMO_TRY_CHECK_ERROR_STATE();
00932                     cpl_propertylist_get_string(main_header, keyword);
00933                     cpl_free(keyword); keyword = NULL;
00934                 } else {
00935                     // if KMOS_RECONSTRUCT_ALL is set all IFUs should be
00936                     // reconstructed
00937                     cpl_propertylist_get_string(main_header, "ggg");
00938                 }
00939 
00940                 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
00941                     (bounds[2*(ifu_nr-1)] != -1) &&
00942                     (bounds[2*(ifu_nr-1)+1] != -1))
00943                 {
00944                     cpl_error_reset();
00945                     // IFU is valid
00946                     actual_sub_header = sub_header;
00947 
00948                     //
00949                     // calc WCS & update subheader
00950                     //
00951                     KMO_TRY_EXIT_IF_ERROR(
00952                         kmo_calc_wcs_gd(main_header, actual_sub_header, ifu_nr, gd));
00953 
00954                     KMO_TRY_EXIT_IF_ERROR(
00955                         kmclipm_update_property_int(actual_sub_header,
00956                                                     NAXIS, 3,
00957                                                     "number of data axes"));
00958                     KMO_TRY_EXIT_IF_ERROR(
00959                         kmclipm_update_property_int(actual_sub_header,
00960                                                     NAXIS1, gd.x.dim,
00961                                                     "length of data axis 1"));
00962                     KMO_TRY_EXIT_IF_ERROR(
00963                         kmclipm_update_property_int(actual_sub_header,
00964                                                     NAXIS2, gd.y.dim,
00965                                                     "length of data axis 2"));
00966                     KMO_TRY_EXIT_IF_ERROR(
00967                         kmclipm_update_property_int(actual_sub_header,
00968                                                     NAXIS3, gd.l.dim,
00969                                                     "length of data axis 3"));
00970 
00971                     // reconstruct data and noise (if available)
00972 //                    if (j == 0) {
00973 //                        sat_mode_msg = FALSE;
00974 //                    } else {
00975 //                        sat_mode_msg = TRUE;
00976 //                    }
00977                     KMO_TRY_EXIT_IF_ERROR(
00978                         kmo_reconstruct_sci(ifu_nr,
00979                                             bounds[2*(ifu_nr-1)],
00980                                             bounds[2*(ifu_nr-1)+1],
00981                                             rec_frame,
00982                                             input_frame_name,
00983                                             NULL,
00984                                             NULL,
00985                                             NULL,
00986                                             xcal_frame,
00987                                             ycal_frame,
00988                                             lcal_frame,
00989                                             NULL,
00990                                             NULL,
00991                                             &gd,
00992                                             &cube_data,
00993                                             &cube_noise,
00994                                             flux,
00995                                             background,
00996                                             xcal_interpolation));
00997 
00998                     if (ref_spectrum_frame != NULL && cube_data != NULL) {
00999                         KMO_TRY_EXIT_IF_NULL(
01000                             lcorr_coeffs = kmo_lcorr_get(cube_data,
01001                                                          actual_sub_header,
01002                                                          ref_spectrum_frame,
01003                                                          gd,
01004                                                          my_filter_id,
01005                                                          ifu_nr));
01006 
01007                         cpl_imagelist_delete(cube_data); cube_data = NULL;
01008                         if (cube_noise != NULL) {
01009                             cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01010                         }
01011                         KMO_TRY_EXIT_IF_ERROR(
01012                             kmo_reconstruct_sci(ifu_nr,
01013                                                 bounds[2*(ifu_nr-1)],
01014                                                 bounds[2*(ifu_nr-1)+1],
01015                                                 rec_frame,
01016                                                 input_frame_name,
01017                                                 NULL,
01018                                                 NULL,
01019                                                 NULL,
01020                                                 xcal_frame,
01021                                                 ycal_frame,
01022                                                 lcal_frame,
01023                                                 lcorr_coeffs,
01024                                                 NULL,
01025                                                 &gd,
01026                                                 &cube_data,
01027                                                 &cube_noise,
01028                                                 flux,
01029                                                 background,
01030                                                 xcal_interpolation));
01031 /*
01032  // show that lambda correction improved the data cube, a second one would improve even more
01033 
01034                         cpl_bivector *obj_spectrum2, *obj_spectrum3;
01035                         cpl_polynomial *lcorr_coeffs2, *lcorr_coeffs3;
01036                         KMO_TRY_EXIT_IF_NULL(
01037                                 obj_spectrum2 = kmo_lcorr_extract_spectrum(
01038                                         cube_data, actual_sub_header, 0.8, NULL));
01039 
01040                         KMO_TRY_EXIT_IF_NULL(
01041                                 lcorr_coeffs2 = kmo_lcorr_crosscorrelate_spectra(
01042                                         obj_spectrum2, ref_spectrum, peaks, 0.002));
01043 
01044                         cpl_bivector_delete(obj_spectrum2);
01045 
01046                         coeff_dump[0] = 0;
01047                         for (ic=0; ic<=cpl_polynomial_get_degree(lcorr_coeffs2) && ic < max_coeffs; ic++) {
01048                             pows[0] = ic;
01049                             coeff_string = cpl_sprintf(" %*g,",
01050                                     format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs2,pows));
01051                             strncat(coeff_dump, coeff_string, format_width);
01052                             cpl_free(coeff_string);
01053                             double c1 =  cpl_polynomial_get_coeff(lcorr_coeffs,pows);
01054                             double c2 =  cpl_polynomial_get_coeff(lcorr_coeffs2,pows);
01055                             cpl_polynomial_set_coeff(lcorr_coeffs, pows, c1+c2);
01056                         }
01057                         cpl_msg_debug("","Lambda correction coeffs for ifu %d %s",ifu_nr, coeff_dump);
01058                         cpl_polynomial_delete(lcorr_coeffs2); lcorr_coeffs2=NULL;
01059 
01060                         cpl_imagelist_delete(cube_data); cube_data = NULL;
01061                         cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01062                         KMO_TRY_EXIT_IF_ERROR(
01063                             kmo_reconstruct_sci(ifu_nr,
01064                                                 bounds[2*(ifu_nr-1)],
01065                                                 bounds[2*(ifu_nr-1)+1],
01066                                                 rec_frame,
01067                                                 input_frame_name,
01068                                                 NULL,
01069                                                 NULL,
01070                                                 NULL,
01071                                                 xcal_frame,
01072                                                 ycal_frame,
01073                                                 lcal_frame,
01074                                                 lcorr_coeffs,
01075                                                 &gd,
01076                                                 &cube_data,
01077                                                 &cube_noise,
01078                                                 flux,
01079                                                 background,
01080                                                 xcal_interpolation));
01081 
01082                         KMO_TRY_EXIT_IF_NULL(
01083                                 obj_spectrum3 = kmo_lcorr_extract_spectrum(
01084                                         cube_data, actual_sub_header, 0.8, NULL));
01085 
01086                         KMO_TRY_EXIT_IF_NULL(
01087                                 lcorr_coeffs3 = kmo_lcorr_crosscorrelate_spectra(
01088                                         obj_spectrum3, ref_spectrum, peaks, 0.002));
01089 
01090                         cpl_bivector_delete(obj_spectrum3);
01091 
01092                         coeff_dump[0] = 0;
01093                         for (ic=0; ic<=cpl_polynomial_get_degree(lcorr_coeffs3) && ic < max_coeffs; ic++) {
01094                             pows[0] = ic;
01095                             coeff_string = cpl_sprintf(" %*g,",
01096                                     format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs3,pows));
01097                             strncat(coeff_dump, coeff_string, format_width);
01098                             cpl_free(coeff_string);
01099                         }
01100                         cpl_msg_debug("","Lambda correction coeffs for iFu %d %s",ifu_nr, coeff_dump);
01101                         cpl_polynomial_delete(lcorr_coeffs3); lcorr_coeffs3=NULL;
01102 */
01103                         cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
01104 
01105                     }
01106 
01107                     // scale flux according to pixel_scale
01108                     KMO_TRY_EXIT_IF_NULL(
01109                         tmp_img = cpl_imagelist_get(cube_data, 0));
01110                     double scaling = (cpl_image_get_size_x(tmp_img)*cpl_image_get_size_y(tmp_img)) /
01111                                      (KMOS_SLITLET_X*KMOS_SLITLET_Y);
01112                     KMO_TRY_EXIT_IF_ERROR(
01113                         cpl_imagelist_divide_scalar(cube_data, scaling));
01114                     if (cube_noise != NULL) {
01115                         KMO_TRY_EXIT_IF_ERROR(
01116                             cpl_imagelist_divide_scalar(cube_noise, scaling));
01117                     }
01118                 } else {
01119                     // IFU is invalid
01120                     actual_sub_header = sub_header_orig;
01121                     cpl_error_reset();
01122                 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) ..
01123 
01124                 if (detectorimage) {
01125                     if (cube_data != NULL) {
01126                         for (l = 0; l < gd.l.dim; l++) {
01127                             KMO_TRY_EXIT_IF_NULL(
01128                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_data, l)));
01129                             for (y = 0; y < gd.y.dim; y++) {
01130                                 for (x = 0; x < gd.x.dim; x++) {
01131                                     int ix = x +
01132                                              y * gd.x.dim +
01133                                              j * gd.x.dim*gd.y.dim +     //IFU offset
01134                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
01135                                     pdet_img_data[ix] = slice[x + y*gd.x.dim];
01136                                 }
01137                             }
01138                         }
01139                     }
01140                     if (cube_noise != NULL) {
01141                         if (detectorimage) {
01142                             detImgCube = TRUE;
01143                         }
01144                         for (l = 0; l < gd.l.dim; l++) {
01145                             KMO_TRY_EXIT_IF_NULL(
01146                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_noise, l)));
01147                             for (y = 0; y < gd.y.dim; y++) {
01148                                 for (x = 0; x < gd.x.dim; x++) {
01149                                     int ix = x +
01150                                              y * gd.x.dim +
01151                                              j * gd.x.dim*gd.y.dim +     //IFU offset
01152                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
01153                                     pdet_img_noise[ix] = slice[x + y*gd.x.dim];
01154                                 }
01155                             }
01156                         }
01157                     }
01158                 }
01159 
01160                 // save output
01161                 KMO_TRY_EXIT_IF_NULL(
01162                     extname = kmo_extname_creator(ifu_frame, ifu_nr,
01163                                                   EXT_DATA));
01164 
01165                 KMO_TRY_EXIT_IF_ERROR(
01166                     kmclipm_update_property_string(actual_sub_header,
01167                                             EXTNAME,
01168                                             extname,
01169                                             "FITS extension name"));
01170 
01171                 cpl_free(extname); extname = NULL;
01172 
01173                 KMO_TRY_EXIT_IF_ERROR(
01174                     kmo_dfs_save_cube(cube_data, filename_cube, obs_suffix,
01175                                       actual_sub_header, 0./0.));
01176 
01177                 if (cube_noise != NULL) {
01178                     KMO_TRY_EXIT_IF_NULL(
01179                         extname = kmo_extname_creator(ifu_frame, ifu_nr,
01180                                                       EXT_NOISE));
01181 
01182                     KMO_TRY_EXIT_IF_ERROR(
01183                         kmclipm_update_property_string(actual_sub_header,
01184                                                 EXTNAME,
01185                                                 extname,
01186                                                 "FITS extension name"));
01187 
01188                     cpl_free(extname); extname = NULL;
01189 
01190                     KMO_TRY_EXIT_IF_ERROR(
01191                         kmo_dfs_save_cube(cube_noise, filename_cube, obs_suffix,
01192                                           actual_sub_header, 0./0.));
01193                 }
01194 
01195                 cpl_imagelist_delete(cube_data); cube_data = NULL;
01196                 cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01197                 cpl_propertylist_delete(sub_header); sub_header = NULL;
01198                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01199             } // for j IFUs
01200 
01201             if (detectorimage) {
01202                 index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
01203                                            i, FALSE);
01204                 KMO_TRY_CHECK_ERROR_STATE();
01205 
01206                 KMO_TRY_EXIT_IF_NULL(
01207                     tmp_header = kmclipm_propertylist_load(
01208                                          cpl_frame_get_filename(rec_frame), index));
01209                 KMO_TRY_EXIT_IF_ERROR(
01210                     kmo_save_det_img_ext(det_img_data[i-1], gd, i, filename_img,
01211                                          obs_suffix, tmp_header, dev_flip, FALSE));
01212                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01213 
01214                 if (detImgCube) {
01215                     if (desc1.ex_noise) {
01216                         index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
01217                                                    i, TRUE);
01218                         KMO_TRY_CHECK_ERROR_STATE();
01219                     } else {
01220                         // use same index as for data frame, since input frame
01221                         // has just 3 extensions
01222                     }
01223                     KMO_TRY_EXIT_IF_NULL(
01224                         tmp_header = kmclipm_propertylist_load(
01225                                              cpl_frame_get_filename(rec_frame), index));
01226                     KMO_TRY_EXIT_IF_ERROR(
01227                         kmo_save_det_img_ext(det_img_noise[i-1], gd, i, filename_img,
01228                                              obs_suffix, tmp_header, dev_flip, TRUE));
01229                     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01230                 }
01231             }
01232 
01233             // free memory
01234             cpl_imagelist_delete(cube_data); cube_data = NULL;
01235             cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01236             cpl_propertylist_delete(sub_header); sub_header = NULL;
01237             cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01238         } // for i devices
01239     }
01240     KMO_CATCH
01241     {
01242         KMO_CATCH_MSG();
01243         ret_val = -1;
01244     }
01245 
01246     kmo_free_fits_desc(&desc1);
01247     kmo_free_fits_desc(&desc2);
01248     for (i = 0; i < KMOS_NR_DETECTORS; i++) {
01249         cpl_image_delete(det_img_data[i]); det_img_data[i] = NULL;
01250         cpl_image_delete(det_img_noise[i]); det_img_noise[i] = NULL;
01251     }
01252     cpl_free(my_filter_id); my_filter_id = NULL;
01253     cpl_free(bounds); bounds = NULL;
01254     cpl_propertylist_delete(main_header); main_header = NULL;
01255     cpl_propertylist_delete(sub_header); sub_header = NULL;
01256     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01257     cpl_imagelist_delete(cube_data); cube_data = NULL;
01258     cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01259     cpl_free(obs_suffix); obs_suffix = NULL;
01260     cpl_free(suffix); suffix = NULL;
01261     cpl_free(filename_img); filename_img = NULL;
01262     cpl_free(filename_cube); filename_cube = NULL;
01263 //    sat_mode_msg = FALSE;
01264 
01265     return ret_val;
01266 }
01267