KMOS Pipeline Reference Manual  1.2.0
kmo_reconstruct.c
00001 /* $Id: kmo_reconstruct.c,v 1.55 2013/06/17 07:52:26 aagudo 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: aagudo $
00023  * $Date: 2013/06/17 07:52:26 $
00024  * $Revision: 1.55 $
00025  * $Name: HEAD $
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                         ic = 0, 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     char                *keyword                = NULL,
00395                         *filename_cube          = NULL,
00396                         *filename_img           = NULL,
00397 //                        *fn_lut                 = NULL,
00398                         *suffix                 = NULL,
00399                         *obs_suffix             = NULL,
00400                         *my_filter_id           = NULL,
00401                         *extname                = NULL;
00402     cpl_image           *lcal                   = NULL,
00403                         *det_img_data[KMOS_NR_DETECTORS],
00404                         *det_img_noise[KMOS_NR_DETECTORS],
00405                         *tmp_img                = NULL;
00406     cpl_imagelist       *cube_data              = NULL,
00407                         *cube_noise             = NULL;
00408     cpl_frame           *rec_frame              = NULL,
00409                         *xcal_frame             = NULL,
00410                         *ycal_frame             = NULL,
00411                         *lcal_frame             = NULL,
00412                         *ref_spectrum_frame     = NULL;
00413     cpl_propertylist    *main_header           = NULL,
00414                         *sub_header            = NULL,
00415                         *sub_header_orig       = NULL,
00416                         *actual_sub_header     = NULL,
00417                         *tmp_header            = NULL;
00418     cpl_table           *band_table            = NULL;
00419     gridDefinition      gd;
00420     main_fits_desc      desc1,
00421                         desc2;
00422     cpl_bivector        *obj_spectrum = NULL,
00423                         *ref_spectrum = NULL;
00424     cpl_vector          *peaks = NULL,
00425                         *range = NULL;
00426     cpl_polynomial      *lcorr_coeffs = NULL;
00427 
00428     for (i = 0; i < KMOS_NR_DETECTORS; i++) {
00429         det_img_data[i] = NULL;
00430         det_img_noise[i] = NULL;
00431     }
00432 
00433     KMO_TRY
00434     {
00435         kmo_init_fits_desc(&desc1);
00436         kmo_init_fits_desc(&desc2);
00437 
00438         // --- check input ---
00439         KMO_TRY_ASSURE((parlist != NULL) &&
00440                        (frameset != NULL),
00441                        CPL_ERROR_NULL_INPUT,
00442                        "Not all input data is provided!");
00443 
00444         KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, DARK) == 1) ||
00445                        (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) ||
00446                        (cpl_frameset_count_tags(frameset, ARC_ON) == 1) ||
00447                        (cpl_frameset_count_tags(frameset, OBJECT) == 1) ||
00448                        (cpl_frameset_count_tags(frameset, STD) == 1) ||
00449                        (cpl_frameset_count_tags(frameset, SCIENCE) == 1),
00450                        CPL_ERROR_NULL_INPUT,
00451                        "A data frame (DARK, FLAT_ON, ARC_ON, OBJECT, STD or SCIENCE) must "
00452                        "be provided!");
00453 
00454         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00455                        CPL_ERROR_FILE_NOT_FOUND,
00456                        "XCAL frame missing in frameset!!");
00457 
00458         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00459                        CPL_ERROR_FILE_NOT_FOUND,
00460                        "YCAL frame missing in frameset!!");
00461 
00462         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00463                        CPL_ERROR_FILE_NOT_FOUND,
00464                        "LCAL frame missing in frameset!!");
00465 
00466         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00467                        CPL_ERROR_FILE_NOT_FOUND,
00468                        "WAVE_BAND frame missing in frameset!!");
00469 
00470         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_reconstruct") == 1,
00471                        CPL_ERROR_ILLEGAL_INPUT,
00472                        "Cannot identify RAW and CALIB frames!");
00473 
00474         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, OH_SPEC) == 0 ||
00475                        cpl_frameset_count_tags(frameset, OH_SPEC) == 1,
00476                        CPL_ERROR_ILLEGAL_INPUT,
00477                        "Only a single reference spectrum can be provided!");
00478 
00479         // --- get parameters ---
00480         cpl_msg_info("", "--- Parameter setup for kmo_reconstruct ---");
00481 
00482         KMO_TRY_EXIT_IF_NULL(
00483             imethod = kmo_dfs_get_parameter_string(parlist,
00484                                               "kmos.kmo_reconstruct.imethod"));
00485 
00486         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00487                        (strcmp(imethod, "lwNN") == 0) ||
00488                        (strcmp(imethod, "swNN") == 0) ||
00489                        (strcmp(imethod, "MS") == 0) ||
00490                        (strcmp(imethod, "CS") == 0),
00491                        CPL_ERROR_ILLEGAL_INPUT,
00492                        "imethod must be either \"NN\", \"lwNN\", "
00493                        "\"swNN\", \"MS\" or \"CS\"!");
00494 
00495         KMO_TRY_EXIT_IF_ERROR(
00496             kmo_dfs_print_parameter_help(parlist,
00497                                         "kmos.kmo_reconstruct.imethod"));
00498 
00499         flux = kmo_dfs_get_parameter_bool(parlist,
00500                                           "kmos.kmo_reconstruct.flux");
00501 
00502         KMO_TRY_ASSURE((flux == 0) ||
00503                        (flux == 1),
00504                        CPL_ERROR_ILLEGAL_INPUT,
00505                        "flux must be either FALSE or TRUE!");
00506 
00507         KMO_TRY_EXIT_IF_ERROR(
00508             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.flux"));
00509 
00510         detectorimage = kmo_dfs_get_parameter_bool(parlist,
00511                                           "kmos.kmo_reconstruct.detectorimage");
00512 
00513         KMO_TRY_ASSURE((detectorimage == 0) ||
00514                        (detectorimage == 1),
00515                        CPL_ERROR_ILLEGAL_INPUT,
00516                        "detectorimage must be either 0 or 1 !");
00517 
00518         KMO_TRY_EXIT_IF_ERROR(
00519             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.detectorimage"));
00520 
00521         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00522                 "kmos.kmo_reconstruct.neighborhoodRange");
00523         KMO_TRY_CHECK_ERROR_STATE();
00524         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00525                 CPL_ERROR_ILLEGAL_INPUT,
00526                 "neighborhoodRange must be greater than 0.0");
00527         KMO_TRY_EXIT_IF_ERROR(
00528             kmo_dfs_print_parameter_help(parlist,
00529                                      "kmos.kmo_reconstruct.neighborhoodRange"));
00530 
00531         kmo_band_pars_load(parlist, "kmos.kmo_reconstruct");
00532 
00533         file_extension = kmo_dfs_get_parameter_bool(parlist,
00534                                         "kmos.kmo_reconstruct.file_extension");
00535         KMO_TRY_CHECK_ERROR_STATE();
00536         KMO_TRY_EXIT_IF_ERROR(
00537            kmo_dfs_print_parameter_help(parlist,
00538                                        "kmos.kmo_reconstruct.file_extension"));
00539 
00540         pix_scale = kmo_dfs_get_parameter_double(parlist,
00541                                         "kmos.kmo_reconstruct.pix_scale");
00542         KMO_TRY_CHECK_ERROR_STATE();
00543         KMO_TRY_EXIT_IF_ERROR(
00544            kmo_dfs_print_parameter_help(parlist,
00545                                        "kmos.kmo_reconstruct.pix_scale"));
00546         KMO_TRY_ASSURE((pix_scale >= 0.01) &&
00547                        (pix_scale <= 0.4),
00548                        CPL_ERROR_ILLEGAL_INPUT,
00549                        "pix_scale must be between 0.01 and 0.4 (results in cubes "
00550                        "with 7x7 to 280x280 pixels)!");
00551 
00552         dev_flip = kmo_dfs_get_parameter_bool(parlist,
00553                                            "kmos.kmo_reconstruct.dev_flip");
00554         KMO_TRY_CHECK_ERROR_STATE();
00555         KMO_TRY_EXIT_IF_ERROR(
00556             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.dev_flip"));
00557         KMO_TRY_ASSURE((dev_flip == TRUE) ||
00558                        (dev_flip == FALSE),
00559                        CPL_ERROR_ILLEGAL_INPUT,
00560                        "dev_flip must be TRUE or FALSE!");
00561 
00562         xcal_interpolation = kmo_dfs_get_parameter_bool(parlist,
00563                                            "kmos.kmo_reconstruct.xcal_interpolation");
00564         KMO_TRY_CHECK_ERROR_STATE();
00565         KMO_TRY_EXIT_IF_ERROR(
00566             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.xcal_interpolation"));
00567         KMO_TRY_ASSURE((xcal_interpolation == TRUE) ||
00568                        (xcal_interpolation == FALSE),
00569                        CPL_ERROR_ILLEGAL_INPUT,
00570                        "xcal_interpolation must be TRUE or FALSE!");
00571 
00572 
00573         cpl_msg_info("", "-------------------------------------------");
00574 
00575         // load descriptor and header of data frame to reconstruct
00576         if (cpl_frameset_count_tags(frameset, DARK) == 1) {
00577             input_frame_name = DARK;
00578             output_frame_name = CUBE_DARK;
00579         } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) {
00580             input_frame_name = FLAT_ON;
00581             output_frame_name = CUBE_FLAT;
00582         } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) {
00583             input_frame_name = ARC_ON;
00584             output_frame_name = CUBE_ARC;
00585         } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) {
00586             input_frame_name = OBJECT;
00587             output_frame_name = CUBE_OBJECT;
00588         } else if (cpl_frameset_count_tags(frameset, STD) == 1) {
00589             input_frame_name = STD;
00590             output_frame_name = CUBE_STD;
00591         } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) {
00592             input_frame_name = SCIENCE;
00593             output_frame_name = CUBE_SCIENCE;
00594         }
00595 
00596         // assure that filters, grating and rotation offsets match for
00597         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00598         // frames)
00599         // check if filter_id and grating_id match for all detectors
00600         KMO_TRY_EXIT_IF_ERROR(
00601             kmo_check_frame_setup(frameset, XCAL, YCAL,
00602                                        TRUE, FALSE, TRUE));
00603         KMO_TRY_EXIT_IF_ERROR(
00604             kmo_check_frame_setup(frameset, XCAL, LCAL,
00605                                        TRUE, FALSE, TRUE));
00606 
00607 // This check doesn't make sense here since OCS.ROT.NAANGLE is compared.
00608 // When creating the calibration files the RAW exposures needn't have been
00609 // provided in the same order
00610 //        KMO_TRY_EXIT_IF_ERROR(
00611 //            kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL));
00612 //        KMO_TRY_EXIT_IF_ERROR(
00613 //            kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL));
00614 
00615         if (cpl_frameset_count_tags(frameset, DARK) != 1) {
00616 
00617             // check if filters, gratings and rotator offset match
00618             // (except for DARK frames)
00619             KMO_TRY_EXIT_IF_ERROR(
00620                 kmo_check_frame_setup(frameset, XCAL, input_frame_name,
00621                                            TRUE, FALSE, FALSE));
00622 /*
00623             // check if rotator offset don't differ to much
00624             cpl_frame        *f1 = NULL, *f2 = NULL;
00625             cpl_propertylist *h1 = NULL, *h2 = NULL;
00626             char             *kw = NULL;
00627             double           tmp_dbl1 = 0.0, tmp_dbl2 = 0.0;
00628 
00629             KMO_TRY_EXIT_IF_NULL(
00630                 f1 = kmo_dfs_get_frame(frameset, XCAL));
00631 
00632             KMO_TRY_EXIT_IF_NULL(
00633                 f2 = kmo_dfs_get_frame(frameset, input_frame_name));
00634             h1 = kmclipm_propertylist_load(cpl_frame_get_filename(f1), 0);
00635             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00636                 cpl_msg_error("","File not found: %s!",
00637                               cpl_frame_get_filename(f1));
00638                 KMO_TRY_CHECK_ERROR_STATE();
00639             }
00640 
00641             h2 = kmclipm_propertylist_load(cpl_frame_get_filename(f2), 0);
00642             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00643                 cpl_msg_error("","File not found: %s!",
00644                               cpl_frame_get_filename(f2));
00645                 KMO_TRY_CHECK_ERROR_STATE();
00646             }
00647             KMO_TRY_EXIT_IF_NULL(
00648                 kw = cpl_sprintf("%s", ROTANGLE));
00649             tmp_dbl1 = cpl_propertylist_get_double(h1, kw);
00650             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00651                 KMO_TRY_ASSURE(1 == 0,
00652                                CPL_ERROR_ILLEGAL_INPUT,
00653                                "keyword \n%s\n of frame %s is missing!",
00654                                keyword, XCAL);
00655             }
00656 
00657             tmp_dbl2 = cpl_propertylist_get_double(h2, kw);
00658             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00659                 KMO_TRY_ASSURE(1 == 0,
00660                                CPL_ERROR_ILLEGAL_INPUT,
00661                                "keyword \n%s\n of frame %s is missing!",
00662                                keyword, input_frame_name);
00663             }
00664 
00665             // strip angles below 0 deg and above 360 deg
00666             kmclipm_strip_angle(&tmp_dbl1);
00667             kmclipm_strip_angle(&tmp_dbl2);
00668 
00669             if (fabs(tmp_dbl1 - tmp_dbl2) > 30.) {
00670                 if ((fabs(tmp_dbl1) < 0.001) && (tmp_dbl2>330) && (tmp_dbl2<360)) {
00671                     // singularity!
00672                     // we have rot=0 for XCAL and rot>330 | rot<360 for input frame
00673                 } else {
00674                 cpl_msg_warning("","The angle of the calibration files (%g deg) "
00675                                 "and the angle of the frame to reconstruct"
00676                                 " (%g deg) differ by %g deg! Think about using "
00677                                 "calibration files matching better the actual "
00678                                 "rotator offset (ESO OCS ROT NAANGLE)",
00679                                 tmp_dbl1, tmp_dbl2,
00680                                 fabs(tmp_dbl1 - tmp_dbl2));
00681                 }
00682             }
00683 
00684             cpl_propertylist_delete(h1); h1 = NULL;
00685             cpl_propertylist_delete(h2); h2 = NULL;
00686             cpl_free(kw); kw = NULL;
00687 */
00688         }
00689 
00690         if (cpl_frameset_count_tags(frameset, OH_SPEC) != 0) {
00691             KMO_TRY_EXIT_IF_NULL(
00692                     ref_spectrum_frame = kmo_dfs_get_frame(frameset, OH_SPEC));
00693         }
00694 
00695         KMO_TRY_EXIT_IF_NULL(
00696             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00697         KMO_TRY_EXIT_IF_NULL(
00698             rec_frame = kmo_dfs_get_frame(frameset, input_frame_name));
00699         KMO_TRY_EXIT_IF_NULL(
00700             suffix = kmo_dfs_get_suffix(rec_frame, TRUE, TRUE));
00701 
00702         KMO_TRY_EXIT_IF_ERROR(
00703             kmo_check_frame_setup_md5_xycal(frameset));
00704         KMO_TRY_EXIT_IF_ERROR(
00705             kmo_check_frame_setup_md5(frameset));
00706 
00707         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
00708         cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)");
00709         cpl_msg_info("", "-------------------------------------------");
00710 
00711 
00712         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(rec_frame));
00713         KMO_TRY_CHECK_ERROR_STATE();
00714 
00715         KMO_TRY_ASSURE(((desc1.nr_ext == KMOS_NR_DETECTORS) ||
00716                         ((desc1.nr_ext == 2*KMOS_NR_DETECTORS))) &&
00717                        (desc1.ex_badpix == FALSE) &&
00718                        ((desc1.fits_type == raw_fits) ||
00719                         (desc1.fits_type == f2d_fits)) &&
00720                        (desc1.frame_type == detector_frame),
00721                        CPL_ERROR_ILLEGAL_INPUT,
00722                        "The frame to reconstruct isn't in the correct format!!!"
00723                        "Exactly 3 frames, or 6 with noise are expected!");
00724 
00725         if (!desc1.ex_noise) {
00726             nr_devices = desc1.nr_ext;
00727         } else {
00728             nr_devices = desc1.nr_ext / 2;
00729         }
00730 
00731         // compare descriptor of XCAL and data frame to reconstruct
00732         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00733         KMO_TRY_CHECK_ERROR_STATE();
00734 
00735         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00736                        (desc1.ex_badpix == desc2.ex_badpix) &&
00737                        (desc1.frame_type == desc2.frame_type),
00738                        CPL_ERROR_ILLEGAL_INPUT,
00739                        "XCAL isn't in the correct format!!!");
00740 
00741         kmo_free_fits_desc(&desc2);
00742 
00743         // compare descriptor of YCAL and data frame to reconstruct
00744         kmo_init_fits_desc(&desc2);
00745 
00746         KMO_TRY_EXIT_IF_NULL(
00747             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00748 
00749         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00750         KMO_TRY_CHECK_ERROR_STATE();
00751 
00752         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00753                        (desc1.ex_badpix == desc2.ex_badpix) &&
00754                        (desc1.frame_type == desc2.frame_type),
00755                        CPL_ERROR_ILLEGAL_INPUT,
00756                        "YCAL isn't in the correct format!!!");
00757 
00758         kmo_free_fits_desc(&desc2);
00759 
00760         // compare descriptor of LCAL and data frame to reconstruct
00761         kmo_init_fits_desc(&desc2);
00762 
00763         KMO_TRY_EXIT_IF_NULL(
00764             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00765 
00766         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00767         KMO_TRY_CHECK_ERROR_STATE();
00768 
00769         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00770                        (desc1.ex_badpix == desc2.ex_badpix) &&
00771                        (desc1.frame_type == desc2.frame_type),
00772                        CPL_ERROR_ILLEGAL_INPUT,
00773                        "LCAL isn't in the correct format!!!");
00774 
00775         kmo_free_fits_desc(&desc2);
00776 
00777         //
00778         // --- load, update & save primary header ---
00779         //
00780         KMO_TRY_EXIT_IF_NULL(
00781             main_header = kmo_dfs_load_primary_header(frameset,
00782                                                       input_frame_name));
00783 
00784         KMO_TRY_EXIT_IF_NULL(
00785             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
00786 
00787         // assert that filters have correct IDs and that all detectors of all
00788         // input frames have the same filter set
00789         for (i = 1; i <= nr_devices; i++) {
00790             // ESO INS FILTi ID
00791             KMO_TRY_EXIT_IF_NULL(
00792                 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i,
00793                                       IFU_FILTID_POSTFIX));
00794 
00795             KMO_TRY_EXIT_IF_NULL(
00796                 filter_id = cpl_propertylist_get_string(tmp_header, keyword));
00797 
00798             KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) ||
00799                            (strcmp(filter_id, "YJ") == 0) ||
00800                            (strcmp(filter_id, "H") == 0) ||
00801                            (strcmp(filter_id, "K") == 0) ||
00802                            (strcmp(filter_id, "HK") == 0),
00803                            CPL_ERROR_ILLEGAL_INPUT,
00804                            "Filter ID in primary header of LCAL frame must "
00805                            "be either \"IZ\", \"YJ\", \"H\", \"K\" or "
00806                            "\"HK\" !");
00807 
00808             if (strcmp(input_frame_name, DARK) != 0) {
00809                 // dark needn't to be taken with filter!
00810 
00811                 KMO_TRY_EXIT_IF_NULL(
00812                     filter_id_tmp = cpl_propertylist_get_string(main_header,
00813                                                                 keyword));
00814                 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_tmp) == 0,
00815                                CPL_ERROR_ILLEGAL_INPUT,
00816                                "Filter IDs must be the same for LCAL frame and "
00817                                "the frame to reconstruct!"
00818                                "Detector No.: %d\nLCAL: %s\n%s: %s\n",
00819                                i, filter_id, input_frame_name, filter_id_tmp);
00820             }
00821             cpl_free(keyword); keyword = NULL;
00822         }
00823         KMO_TRY_EXIT_IF_NULL(
00824             my_filter_id = cpl_strdup(filter_id));
00825         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00826 
00827         obs_id = cpl_propertylist_get_int(main_header, OBS_ID);
00828         KMO_TRY_CHECK_ERROR_STATE();
00829 
00830         KMO_TRY_EXIT_IF_NULL(
00831             filename_cube = cpl_sprintf("%s", output_frame_name));
00832         KMO_TRY_EXIT_IF_NULL(
00833             filename_img = cpl_sprintf("%s", DET_IMG_REC));
00834         if (file_extension) {
00835             KMO_TRY_EXIT_IF_NULL(
00836                 obs_suffix = cpl_sprintf("%s%d", "_", obs_id));
00837         } else {
00838             KMO_TRY_EXIT_IF_NULL(
00839                 obs_suffix = cpl_sprintf("%s", ""));
00840         }
00841 
00842         KMO_TRY_EXIT_IF_ERROR(
00843             kmo_dfs_save_main_header(frameset, filename_cube, obs_suffix,
00844                                      rec_frame, NULL, parlist, cpl_func));
00845 
00846         // setup grid definition, wavelength start and end points will be set
00847         // in the detector loop
00848         KMO_TRY_EXIT_IF_ERROR(
00849             kmclipm_setup_grid(&gd, imethod, neighborhoodRange, pix_scale));
00850 
00851         KMO_TRY_EXIT_IF_NULL(
00852             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
00853 
00854         KMO_TRY_EXIT_IF_NULL(
00855             bounds = kmclipm_extract_bounds(tmp_header));
00856         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00857 
00858         if (detectorimage == TRUE) {
00859             KMO_TRY_EXIT_IF_ERROR(
00860                 kmo_dfs_save_main_header(frameset, filename_img, obs_suffix,
00861                                          rec_frame, NULL, parlist, cpl_func));
00862         }
00863 
00864         /* loop through all detectors */
00865         for (i = 1; i <= nr_devices; i++) {
00866             cpl_msg_info("","Processing detector No. %d", i);
00867 
00868             // load lcal
00869             // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
00870             // doesn't differ too much with different ROTANGLEs.
00871             double rotangle_found;
00872             KMO_TRY_EXIT_IF_NULL(
00873                 lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0.,
00874                                               FALSE, NULL, &rotangle_found, -1, 0, 0));
00875 
00876             char *tmp_band_method = getenv("KMO_BAND_METHOD");
00877             int band_method = 0;
00878             if (tmp_band_method != NULL) {
00879                 band_method = atoi(tmp_band_method);
00880             }
00881 
00882             KMO_TRY_EXIT_IF_NULL(
00883                 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE));
00884 
00885             KMO_TRY_EXIT_IF_ERROR(
00886                 kmclipm_setup_grid_band_lcal(&gd, lcal, my_filter_id,
00887                                              band_method, band_table));
00888             cpl_table_delete(band_table); band_table = NULL;
00889 
00890             cpl_image_delete(lcal); lcal = NULL;
00891 
00892             if (detectorimage == TRUE) {
00893                 KMO_TRY_EXIT_IF_NULL(
00894                     det_img_data[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR,
00895                                                       gd.l.dim, CPL_TYPE_FLOAT));
00896                 KMO_TRY_EXIT_IF_NULL(
00897                     pdet_img_data = cpl_image_get_data_float(det_img_data[i-1]));
00898 
00899                 KMO_TRY_EXIT_IF_NULL(
00900                     det_img_noise[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_noise = cpl_image_get_data_float(det_img_noise[i-1]));
00904             }
00905 
00906 
00907             for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
00908                 /* update sub-header */
00909                 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
00910 
00911                 /* load raw image and sub-header*/
00912                 KMO_TRY_EXIT_IF_NULL(
00913                     sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name,
00914                                                          i, FALSE));
00915                 KMO_TRY_EXIT_IF_NULL(
00916                     sub_header_orig = cpl_propertylist_duplicate(sub_header));
00917 
00918                 // check if IFU is valid according to main header keywords &
00919                 // calibration files
00920 
00921                 if (getenv("KMOS_RECONSTRUCT_ALL") == NULL) {
00922                     KMO_TRY_EXIT_IF_NULL(
00923                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr,
00924                                               IFU_VALID_POSTFIX));
00925                     KMO_TRY_CHECK_ERROR_STATE();
00926                     cpl_propertylist_get_string(main_header, keyword);
00927                     cpl_free(keyword); keyword = NULL;
00928                 } else {
00929                     // if KMOS_RECONSTRUCT_ALL is set all IFUs should be
00930                     // reconstructed
00931                     cpl_propertylist_get_string(main_header, "ggg");
00932                 }
00933 
00934                 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
00935                     (bounds[2*(ifu_nr-1)] != -1) &&
00936                     (bounds[2*(ifu_nr-1)+1] != -1))
00937                 {
00938                     cpl_error_reset();
00939                     // IFU is valid
00940                     actual_sub_header = sub_header;
00941 
00942                     // calculate WCS
00943                     KMO_TRY_EXIT_IF_ERROR(
00944                         kmo_calc_wcs_gd(main_header, actual_sub_header, ifu_nr, gd));
00945 
00946                     // reconstruct data and noise (if available)
00947                     if (j == 0) {
00948                         sat_mode_msg = FALSE;
00949                     } else {
00950                         sat_mode_msg = TRUE;
00951                     }
00952                     KMO_TRY_EXIT_IF_ERROR(
00953                         kmo_reconstruct_sci(ifu_nr,
00954                                             bounds[2*(ifu_nr-1)],
00955                                             bounds[2*(ifu_nr-1)+1],
00956                                             rec_frame,
00957                                             input_frame_name,
00958                                             NULL,
00959                                             NULL,
00960                                             NULL,
00961                                             xcal_frame,
00962                                             ycal_frame,
00963                                             lcal_frame,
00964                                             NULL,
00965                                             &gd,
00966                                             &cube_data,
00967                                             &cube_noise,
00968                                             flux,
00969                                             background,
00970                                             xcal_interpolation));
00971 
00972                     if (ref_spectrum_frame != NULL && cube_data != NULL) {
00973                         if (peaks == NULL) {
00974                             KMO_TRY_EXIT_IF_NULL(
00975                                 range = cpl_vector_new(2));
00976                             KMO_TRY_EXIT_IF_ERROR(
00977                                 cpl_vector_set(range, 0, gd.l.start));
00978                             KMO_TRY_EXIT_IF_ERROR(
00979                                 cpl_vector_set(range, 1, gd.l.start + gd.l.delta * gd.l.dim));
00980                              KMO_TRY_EXIT_IF_NULL(
00981                                 ref_spectrum = kmo_lcorr_read_reference_spectrum(
00982                                                   cpl_frame_get_filename(ref_spectrum_frame),NULL));
00983                             KMO_TRY_EXIT_IF_NULL(
00984                                 peaks = kmo_lcorr_get_peak_lambdas(ref_spectrum, 0.2, range));
00985 
00986                             cpl_vector_delete(range);
00987                         }
00988 
00989                         KMO_TRY_EXIT_IF_ERROR(
00990                             cpl_propertylist_set_int(actual_sub_header,NAXIS,3));
00991                         KMO_TRY_EXIT_IF_NULL(
00992                             tmp_img = cpl_imagelist_get(cube_data, 0));
00993                         KMO_TRY_EXIT_IF_ERROR(
00994                             cpl_propertylist_set_int(actual_sub_header,NAXIS1,
00995                                                      cpl_image_get_size_x(tmp_img)));
00996                         KMO_TRY_EXIT_IF_ERROR(
00997                             cpl_propertylist_set_int(actual_sub_header,NAXIS2,
00998                                                      cpl_image_get_size_y(tmp_img)));
00999                         KMO_TRY_EXIT_IF_ERROR(
01000                             cpl_propertylist_append_int(actual_sub_header,NAXIS3,
01001                                                         cpl_imagelist_get_size(cube_data)));
01002                         KMO_TRY_EXIT_IF_NULL(
01003                             obj_spectrum = kmo_lcorr_extract_spectrum(
01004                                                     cube_data, actual_sub_header, 0.8, NULL));
01005 
01006 /*
01007  // enables additional debugging output
01008                         char *idlfilename = cpl_sprintf("idl_%2.2d.dat",ifu_nr);
01009                         kmo_lcorr_open_debug_file(idlfilename);
01010                         cpl_free(idlfilename);
01011 */
01012 
01013                         KMO_TRY_EXIT_IF_NULL(
01014                             lcorr_coeffs = kmo_lcorr_crosscorrelate_spectra(
01015                                                 obj_spectrum, ref_spectrum, peaks, my_filter_id));
01016 /*
01017  // debugging output is a single file for each IFU, so close it now
01018                          kmo_lcorr_close_debug_file();
01019 */
01020 
01021                         cpl_bivector_delete(obj_spectrum);
01022 
01023                         const int format_width = 14;
01024                         const int max_coeffs = 6;
01025                         char *coeff_string = NULL;
01026                         char coeff_dump[format_width * max_coeffs + 1];
01027                         cpl_size pows[1];
01028                         coeff_dump[0] = 0;
01029                         for (ic = 0; ic <= cpl_polynomial_get_degree(lcorr_coeffs) && ic < max_coeffs; ic++) {
01030                             pows[0] = ic;
01031                             coeff_string = cpl_sprintf(" %*g,",
01032                                     format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs,pows));
01033                             strncat(coeff_dump, coeff_string, format_width);
01034                             cpl_free(coeff_string);
01035                         }
01036                         cpl_msg_debug("","Lambda correction coeffs for IFU %d %s",ifu_nr, coeff_dump);
01037 
01038                         cpl_imagelist_delete(cube_data); cube_data = NULL;
01039                         if (cube_noise != NULL) {
01040                             cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01041                         }
01042                         KMO_TRY_EXIT_IF_ERROR(
01043                             kmo_reconstruct_sci(ifu_nr,
01044                                                 bounds[2*(ifu_nr-1)],
01045                                                 bounds[2*(ifu_nr-1)+1],
01046                                                 rec_frame,
01047                                                 input_frame_name,
01048                                                 NULL,
01049                                                 NULL,
01050                                                 NULL,
01051                                                 xcal_frame,
01052                                                 ycal_frame,
01053                                                 lcal_frame,
01054                                                 lcorr_coeffs,
01055                                                 &gd,
01056                                                 &cube_data,
01057                                                 &cube_noise,
01058                                                 flux,
01059                                                 background,
01060                                                 xcal_interpolation));
01061 /*
01062  // show that lambda correction improved the data cube, a second one would improve even more
01063 
01064                         cpl_bivector *obj_spectrum2, *obj_spectrum3;
01065                         cpl_polynomial *lcorr_coeffs2, *lcorr_coeffs3;
01066                         KMO_TRY_EXIT_IF_NULL(
01067                                 obj_spectrum2 = kmo_lcorr_extract_spectrum(
01068                                         cube_data, actual_sub_header, 0.8, NULL));
01069 
01070                         KMO_TRY_EXIT_IF_NULL(
01071                                 lcorr_coeffs2 = kmo_lcorr_crosscorrelate_spectra(
01072                                         obj_spectrum2, ref_spectrum, peaks, 0.002));
01073 
01074                         cpl_bivector_delete(obj_spectrum2);
01075 
01076                         coeff_dump[0] = 0;
01077                         for (ic=0; ic<=cpl_polynomial_get_degree(lcorr_coeffs2) && ic < max_coeffs; ic++) {
01078                             pows[0] = ic;
01079                             coeff_string = cpl_sprintf(" %*g,",
01080                                     format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs2,pows));
01081                             strncat(coeff_dump, coeff_string, format_width);
01082                             cpl_free(coeff_string);
01083                             double c1 =  cpl_polynomial_get_coeff(lcorr_coeffs,pows);
01084                             double c2 =  cpl_polynomial_get_coeff(lcorr_coeffs2,pows);
01085                             cpl_polynomial_set_coeff(lcorr_coeffs, pows, c1+c2);
01086                         }
01087                         cpl_msg_debug("","Lambda correction coeffs for ifu %d %s",ifu_nr, coeff_dump);
01088                         cpl_polynomial_delete(lcorr_coeffs2); lcorr_coeffs2=NULL;
01089 
01090                         cpl_imagelist_delete(cube_data); cube_data = NULL;
01091                         cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01092                         KMO_TRY_EXIT_IF_ERROR(
01093                             kmo_reconstruct_sci(ifu_nr,
01094                                                 bounds[2*(ifu_nr-1)],
01095                                                 bounds[2*(ifu_nr-1)+1],
01096                                                 rec_frame,
01097                                                 input_frame_name,
01098                                                 NULL,
01099                                                 NULL,
01100                                                 NULL,
01101                                                 xcal_frame,
01102                                                 ycal_frame,
01103                                                 lcal_frame,
01104                                                 lcorr_coeffs,
01105                                                 &gd,
01106                                                 &cube_data,
01107                                                 &cube_noise,
01108                                                 flux,
01109                                                 background,
01110                                                 xcal_interpolation));
01111 
01112                         KMO_TRY_EXIT_IF_NULL(
01113                                 obj_spectrum3 = kmo_lcorr_extract_spectrum(
01114                                         cube_data, actual_sub_header, 0.8, NULL));
01115 
01116                         KMO_TRY_EXIT_IF_NULL(
01117                                 lcorr_coeffs3 = kmo_lcorr_crosscorrelate_spectra(
01118                                         obj_spectrum3, ref_spectrum, peaks, 0.002));
01119 
01120                         cpl_bivector_delete(obj_spectrum3);
01121 
01122                         coeff_dump[0] = 0;
01123                         for (ic=0; ic<=cpl_polynomial_get_degree(lcorr_coeffs3) && ic < max_coeffs; ic++) {
01124                             pows[0] = ic;
01125                             coeff_string = cpl_sprintf(" %*g,",
01126                                     format_width-2, cpl_polynomial_get_coeff(lcorr_coeffs3,pows));
01127                             strncat(coeff_dump, coeff_string, format_width);
01128                             cpl_free(coeff_string);
01129                         }
01130                         cpl_msg_debug("","Lambda correction coeffs for iFu %d %s",ifu_nr, coeff_dump);
01131                         cpl_polynomial_delete(lcorr_coeffs3); lcorr_coeffs3=NULL;
01132 */
01133                         cpl_polynomial_delete(lcorr_coeffs); lcorr_coeffs = NULL;
01134 
01135                     }
01136 
01137                     // scale flux according to pixel_scale
01138                     KMO_TRY_EXIT_IF_NULL(
01139                         tmp_img = cpl_imagelist_get(cube_data, 0));
01140                     double scaling = (cpl_image_get_size_x(tmp_img)*cpl_image_get_size_y(tmp_img)) /
01141                                      (KMOS_SLITLET_X*KMOS_SLITLET_Y);
01142                     KMO_TRY_EXIT_IF_ERROR(
01143                         cpl_imagelist_divide_scalar(cube_data, scaling));
01144                     if (cube_noise != NULL) {
01145                         KMO_TRY_EXIT_IF_ERROR(
01146                             cpl_imagelist_divide_scalar(cube_noise, scaling));
01147                     }
01148                 } else {
01149                     // IFU is invalid
01150                     actual_sub_header = sub_header_orig;
01151                     cpl_error_reset();
01152                 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) ..
01153 
01154                 if (detectorimage) {
01155                     if (cube_data != NULL) {
01156                         for (l = 0; l < gd.l.dim; l++) {
01157                             KMO_TRY_EXIT_IF_NULL(
01158                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_data, l)));
01159                             for (y = 0; y < gd.y.dim; y++) {
01160                                 for (x = 0; x < gd.x.dim; x++) {
01161                                     int ix = x +
01162                                              y * gd.x.dim +
01163                                              j * gd.x.dim*gd.y.dim +     //IFU offset
01164                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
01165                                     pdet_img_data[ix] = slice[x + y*gd.x.dim];
01166                                 }
01167                             }
01168                         }
01169                     }
01170                     if (cube_noise != NULL) {
01171                         if (detectorimage) {
01172                             detImgCube = TRUE;
01173                         }
01174                         for (l = 0; l < gd.l.dim; l++) {
01175                             KMO_TRY_EXIT_IF_NULL(
01176                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_noise, l)));
01177                             for (y = 0; y < gd.y.dim; y++) {
01178                                 for (x = 0; x < gd.x.dim; x++) {
01179                                     int ix = x +
01180                                              y * gd.x.dim +
01181                                              j * gd.x.dim*gd.y.dim +     //IFU offset
01182                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
01183                                     pdet_img_noise[ix] = slice[x + y*gd.x.dim];
01184                                 }
01185                             }
01186                         }
01187                     }
01188                 }
01189 
01190                 // save output
01191                 KMO_TRY_EXIT_IF_NULL(
01192                     extname = kmo_extname_creator(ifu_frame, ifu_nr,
01193                                                   EXT_DATA));
01194 
01195                 KMO_TRY_EXIT_IF_ERROR(
01196                     kmclipm_update_property_string(actual_sub_header,
01197                                             EXTNAME,
01198                                             extname,
01199                                             "FITS extension name"));
01200 
01201                 cpl_free(extname); extname = NULL;
01202 
01203                 KMO_TRY_EXIT_IF_ERROR(
01204                     kmo_dfs_save_cube(cube_data, filename_cube, obs_suffix,
01205                                       actual_sub_header, 0./0.));
01206 
01207                 if (cube_noise != NULL) {
01208                     KMO_TRY_EXIT_IF_NULL(
01209                         extname = kmo_extname_creator(ifu_frame, ifu_nr,
01210                                                       EXT_NOISE));
01211 
01212                     KMO_TRY_EXIT_IF_ERROR(
01213                         kmclipm_update_property_string(actual_sub_header,
01214                                                 EXTNAME,
01215                                                 extname,
01216                                                 "FITS extension name"));
01217 
01218                     cpl_free(extname); extname = NULL;
01219 
01220                     KMO_TRY_EXIT_IF_ERROR(
01221                         kmo_dfs_save_cube(cube_noise, filename_cube, obs_suffix,
01222                                           actual_sub_header, 0./0.));
01223                 }
01224 
01225                 cpl_imagelist_delete(cube_data); cube_data = NULL;
01226                 cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01227                 cpl_propertylist_delete(sub_header); sub_header = NULL;
01228                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01229             } // for j IFUs
01230 
01231             if (detectorimage) {
01232                 index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
01233                                            i, FALSE);
01234                 KMO_TRY_CHECK_ERROR_STATE();
01235 
01236                 KMO_TRY_EXIT_IF_NULL(
01237                     tmp_header = kmclipm_propertylist_load(
01238                                          cpl_frame_get_filename(rec_frame), index));
01239                 KMO_TRY_EXIT_IF_ERROR(
01240                     kmo_save_det_img_ext(det_img_data[i-1], gd, i, filename_img,
01241                                          obs_suffix, tmp_header, dev_flip, FALSE));
01242                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01243 
01244                 if (detImgCube) {
01245                     if (desc1.ex_noise) {
01246                         index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
01247                                                    i, TRUE);
01248                         KMO_TRY_CHECK_ERROR_STATE();
01249                     } else {
01250                         // use same index as for data frame, since input frame
01251                         // has just 3 extensions
01252                     }
01253                     KMO_TRY_EXIT_IF_NULL(
01254                         tmp_header = kmclipm_propertylist_load(
01255                                              cpl_frame_get_filename(rec_frame), index));
01256                     KMO_TRY_EXIT_IF_ERROR(
01257                         kmo_save_det_img_ext(det_img_noise[i-1], gd, i, filename_img,
01258                                              obs_suffix, tmp_header, dev_flip, TRUE));
01259                     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01260                 }
01261             }
01262 
01263             // free memory
01264             cpl_imagelist_delete(cube_data); cube_data = NULL;
01265             cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01266             cpl_propertylist_delete(sub_header); sub_header = NULL;
01267             cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01268         } // for i devices
01269     }
01270     KMO_CATCH
01271     {
01272         KMO_CATCH_MSG();
01273         ret_val = -1;
01274     }
01275 
01276     kmo_free_fits_desc(&desc1);
01277     kmo_free_fits_desc(&desc2);
01278     for (i = 0; i < KMOS_NR_DETECTORS; i++) {
01279         cpl_image_delete(det_img_data[i]); det_img_data[i] = NULL;
01280         cpl_image_delete(det_img_noise[i]); det_img_noise[i] = NULL;
01281     }
01282     cpl_free(my_filter_id); my_filter_id = NULL;
01283     cpl_free(bounds); bounds = NULL;
01284     cpl_propertylist_delete(main_header); main_header = NULL;
01285     cpl_propertylist_delete(sub_header); sub_header = NULL;
01286     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01287     cpl_imagelist_delete(cube_data); cube_data = NULL;
01288     cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01289     cpl_free(obs_suffix); obs_suffix = NULL;
01290     cpl_free(suffix); suffix = NULL;
01291     cpl_free(filename_img); filename_img = NULL;
01292     cpl_free(filename_cube); filename_cube = NULL;
01293     if (peaks != NULL ) {cpl_vector_delete(peaks);}
01294     if (ref_spectrum  != NULL ) {cpl_bivector_delete(ref_spectrum);}
01295     sat_mode_msg = FALSE;
01296 
01297     return ret_val;
01298 }
01299