KMOS Pipeline Reference Manual  1.0.8
kmo_reconstruct.c
00001 /* $Id: kmo_reconstruct.c,v 1.37 2013/02/19 10:51:42 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/02/19 10:51:42 $
00024  * $Revision: 1.37 $
00025  * $Name: kmosp_v1_0_8__20130220 $
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_cpl_extensions.h"
00046 #include "kmo_dfs.h"
00047 #include "kmo_error.h"
00048 #include "kmo_utils.h"
00049 #include "kmo_constants.h"
00050 #include "kmo_debug.h"
00051 
00052 /*-----------------------------------------------------------------------------
00053  *                          Functions prototypes
00054  *----------------------------------------------------------------------------*/
00055 
00056 static int kmo_reconstruct_create(cpl_plugin *);
00057 static int kmo_reconstruct_exec(cpl_plugin *);
00058 static int kmo_reconstruct_destroy(cpl_plugin *);
00059 static int kmo_reconstruct(cpl_parameterlist *, cpl_frameset *);
00060 
00061 /*-----------------------------------------------------------------------------
00062  *                          Static variables
00063  *----------------------------------------------------------------------------*/
00064 
00065 static char kmo_reconstruct_description[] =
00066 "Data with or without noise is reconstructed into a cube using the calibration\n"
00067 "frames XCAL, YCAL and LCAL. XCAL and YCAL are generated using recipe kmo_flat,\n"
00068 "LCAL is generated using recipe kmo_wave_cal.\n"
00069 "The input data can contain noise extensions and will be reconstructed into\n"
00070 "additional extensions.\n"
00071 "\n"
00072 "BASIC PARAMETERS:\n"
00073 "-----------------\n"
00074 "--imethod\n"
00075 "The interpolation method used for reconstruction.\n"
00076 "\n"
00077 "--detimg\n"
00078 "Specify if the resampled image of the input frame should be generated. There-\n"
00079 "fore all slitlets of all IFUs are aligned one next to the other. This frame\n"
00080 "serves for quality control. One can immediately see if the reconstruction was\n"
00081 "successful.\n"
00082 "\n"
00083 "--file_extension"
00084 "Set this parameter to TRUE if the EXPTIME keyword should be appended to\n"
00085 "the output filenames.\n"
00086 "\n"
00087 "ADVANCED PARAMETERS\n"
00088 "-------------------\n"
00089 "--flux\n"
00090 "Specify if flux conservation should be applied.\n"
00091 "\n"
00092 "--neighborhoodRange\n"
00093 "Defines the range to search for neighbors during reconstruction\n"
00094 "\n"
00095 "--b_samples\n"
00096 "The number of samples in spectral direction for the reconstructed cube. Ideal-\n"
00097 "ly this number should be greater than 2048, the detector size.\n"
00098 "\n"
00099 "--b_start\n"
00100 "--b_end\n"
00101 "Used to define manually the start and end wavelength for the reconstructed\n"
00102 "cube. By default the internally defined values are used.\n"
00103 "\n"
00104 "--file_extension"
00105 "Set to TRUE if OBS_ID (from input frame header) should be appended to the\n"
00106 "output frame.\n"
00107 "\n"
00108 "-------------------------------------------------------------------------------\n"
00109 "  Input files:\n"
00110 "\n"
00111 "   DO                  KMOS                                                    \n"
00112 "   category            Type     Explanation                    Required #Frames\n"
00113 "   --------            -----    -----------                    -------- -------\n"
00114 "   DARK    or          RAW/F2D  data with                          Y       1   \n"
00115 "   FLAT_ON or          RAW/F2D  or without noise                               \n"
00116 "   ARC_ON  or          RAW/F2D                                                 \n"
00117 "   OBJECT  or          RAW                                                     \n"
00118 "   STD     or          RAW                                                     \n"
00119 "   SCIENCE             RAW                                                     \n"
00120 "   XCAL                F2D      x-direction calib. frame           Y       1   \n"
00121 "   YCAL                F2D      y-direction calib. frame           Y       1   \n"
00122 "   LCAL                F2D      Wavelength calib. frame            Y       1   \n"
00123 "   WAVE_BAND           F2L      Table with start-/end-wavelengths  Y       1   \n"
00124 "\n"
00125 "  Output files:\n"
00126 "\n"
00127 "   DO                    KMOS\n"
00128 "   category              Type     Explanation\n"
00129 "   --------              -----    -----------\n"
00130 "   CUBE_DARK   or        F3I      Reconstructed cube   \n"
00131 "   CUBE_FLAT   or        RAW/F2D  with or without noise\n"
00132 "   CUBE_ARC    or                                      \n"
00133 "   CUBE_OBJECT or                                      \n"
00134 "   CUBE_STD    or                                      \n"
00135 "   CUBE_SCIENCE                                        \n"
00136 "-------------------------------------------------------------------------------\n"
00137 "\n";
00138 
00139 /*-----------------------------------------------------------------------------
00140  *                              Functions code
00141  *----------------------------------------------------------------------------*/
00142 
00159 int cpl_plugin_get_info(cpl_pluginlist *list)
00160 {
00161     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00162     cpl_plugin *plugin = &recipe->interface;
00163 
00164     cpl_plugin_init(plugin,
00165                         CPL_PLUGIN_API,
00166                         KMOS_BINARY_VERSION,
00167                         CPL_PLUGIN_TYPE_RECIPE,
00168                         "kmo_reconstruct",
00169                         "Performs the cube reconstruction "
00170                         "using different interpolation methods.",
00171                         kmo_reconstruct_description,
00172                         "Alex Agudo Berbel",
00173                         "agudo@mpe.mpg.de",
00174                         kmos_get_license(),
00175                         kmo_reconstruct_create,
00176                         kmo_reconstruct_exec,
00177                         kmo_reconstruct_destroy);
00178 
00179     cpl_pluginlist_append(list, plugin);
00180 
00181     return 0;
00182 }
00183 
00191 static int kmo_reconstruct_create(cpl_plugin *plugin)
00192 {
00193     cpl_recipe *recipe;
00194     cpl_parameter *p;
00195 
00196     /* Check that the plugin is part of a valid recipe */
00197     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00198         recipe = (cpl_recipe *)plugin;
00199     else
00200         return -1;
00201 
00202     /* Create the parameters list in the cpl_recipe object */
00203     recipe->parameters = cpl_parameterlist_new();
00204 
00205     /* Fill the parameters list */
00206     /* --imethod */
00207     p = cpl_parameter_new_value("kmos.kmo_reconstruct.imethod",
00208                                 CPL_TYPE_STRING,
00209                                 "Method to use for interpolation. "
00210                                 "[\"NN\" (nearest neighbour), "
00211                                 "\"lwNN\" (linear weighted nearest neighbor), "
00212                                 "\"swNN\" (square weighted nearest neighbor), "
00213                                 "\"MS\" (Modified Shepard's method)"
00214                                 "\"CS\" (Cubic spline)]",
00215                                 "kmos.kmo_reconstruct",
00216                                 "CS");
00217     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "imethod");
00218     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00219     cpl_parameterlist_append(recipe->parameters, p);
00220 
00221     /* --neighborhoodRange */
00222     p = cpl_parameter_new_value("kmos.kmo_reconstruct.neighborhoodRange",
00223                                 CPL_TYPE_DOUBLE,
00224                                 "Defines the range to search for neighbors. "
00225                                 "in pixels",
00226                                 "kmos.kmo_reconstruct",
00227                                 1.001);
00228     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "neighborhoodRange");
00229     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00230     cpl_parameterlist_append(recipe->parameters, p);
00231 
00232     /* --flux */
00233     p = cpl_parameter_new_value("kmos.kmo_reconstruct.flux",
00234                                 CPL_TYPE_BOOL,
00235                                 "TRUE: Apply flux conservation. FALSE: otherwise",
00236                                 "kmos.kmo_reconstruct",
00237                                 FALSE);
00238     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00239     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00240     cpl_parameterlist_append(recipe->parameters, p);
00241 
00242     /* --detectorimage */
00243     p = cpl_parameter_new_value("kmos.kmo_reconstruct.detectorimage",
00244                                 CPL_TYPE_BOOL,
00245                                 "TRUE: if resampled detector frame should be "
00246                                 "created, FALSE: otherwise",
00247                                 "kmos.kmo_reconstruct",
00248                                 FALSE);
00249     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "detimg");
00250     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00251     cpl_parameterlist_append(recipe->parameters, p);
00252 
00253     /* --file_extension */
00254     p = cpl_parameter_new_value("kmos.kmo_reconstruct.file_extension",
00255                                 CPL_TYPE_BOOL,
00256                                 "TRUE: if OBS_ID keyword should be appended to "
00257                                 "output frames, FALSE: otherwise",
00258                                 "kmos.kmo_reconstruct",
00259                                 FALSE);
00260     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "file_extension");
00261     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00262     cpl_parameterlist_append(recipe->parameters, p);
00263 
00264     /* --dev_flip */
00265     p = cpl_parameter_new_value("kmos.kmo_reconstruct.dev_flip",
00266                                 CPL_TYPE_BOOL,
00267                                 "INTENDED FOR PIPELINE DEVELOPERS ONLY: "
00268                                 "Set this parameter to TRUE if the wavelengths "
00269                                 "are ascending on the detector from bottom to "
00270                                 "top (only for old simulation data).",
00271                                 "kmos.kmo_reconstruct",
00272                                 FALSE);
00273     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dev_flip");
00274     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00275     cpl_parameterlist_append(recipe->parameters, p);
00276 
00277     // add parameters for band-definition
00278     kmo_band_pars_create(recipe->parameters,
00279                          "kmos.kmo_reconstruct");
00280 
00281     return 0;
00282 }
00283 
00289 static int kmo_reconstruct_exec(cpl_plugin *plugin)
00290 {
00291     cpl_recipe  *recipe;
00292 
00293     /* Get the recipe out of the plugin */
00294     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00295         recipe = (cpl_recipe *)plugin;
00296     else return -1;
00297 
00298     return kmo_reconstruct(recipe->parameters, recipe->frames);
00299 }
00300 
00306 static int kmo_reconstruct_destroy(cpl_plugin *plugin)
00307 {
00308     cpl_recipe *recipe;
00309 
00310     /* Get the recipe out of the plugin */
00311     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00312         recipe = (cpl_recipe *)plugin;
00313     else return -1 ;
00314 
00315     cpl_parameterlist_delete(recipe->parameters);
00316     return 0 ;
00317 }
00318 
00333 static int kmo_reconstruct(cpl_parameterlist *parlist, cpl_frameset *frameset)
00334 {
00335     int                 ret_val                 = 0,
00336                         nr_devices              = 0,
00337                         i                       = 0,
00338                         j                       = 0,
00339                         flux                    = 0,
00340                         index                   = 0,
00341                         detectorimage           = 0,
00342                         *bounds                 = NULL,
00343                         ifu_nr                  = 0,
00344                         obs_id                  = 0,
00345                         file_extension          = FALSE,
00346                         dev_flip                = FALSE,
00347                         detImgCube              = FALSE;
00348     float               *pdet_img_data          = NULL,
00349                         *pdet_img_noise         = NULL,
00350                         *slice                  = NULL;
00351     double              neighborhoodRange       = 1.001;
00352 
00353     const char          *imethod                = NULL,
00354                         *input_frame_name       = NULL,
00355                         *output_frame_name      = NULL,
00356                         *filter_id              = NULL,
00357                         *filter_id_tmp          = NULL;
00358     char                *keyword                = NULL,
00359                         *filename_cube          = NULL,
00360                         *filename_img           = NULL,
00361 //                        *fn_lut                 = NULL,
00362                         *suffix                 = NULL,
00363                         *obs_suffix             = NULL,
00364                         *my_filter_id           = NULL,
00365                         *extname                = NULL;
00366     cpl_image           *lcal                   = NULL,
00367                         *det_img_data[KMOS_NR_DETECTORS],
00368                         *det_img_noise[KMOS_NR_DETECTORS];
00369     cpl_imagelist       *cube_data              = NULL,
00370                         *cube_noise             = NULL;
00371     cpl_frame           *rec_frame              = NULL,
00372                         *xcal_frame             = NULL,
00373                         *ycal_frame             = NULL,
00374                         *lcal_frame             = NULL;
00375     cpl_propertylist    *main_header           = NULL,
00376                         *sub_header            = NULL,
00377                         *sub_header_orig       = NULL,
00378                         *actual_sub_header     = NULL,
00379                         *tmp_header            = NULL;
00380     cpl_table           *band_table            = NULL;
00381     gridDefinition      gd;
00382     main_fits_desc      desc1,
00383                         desc2;
00384 
00385     for (int i=0; i<KMOS_NR_DETECTORS; i++) {
00386         det_img_data[i] = NULL;
00387         det_img_noise[i] = NULL;
00388     }
00389 
00390     KMO_TRY
00391     {
00392         kmo_init_fits_desc(&desc1);
00393         kmo_init_fits_desc(&desc2);
00394 
00395         // --- check input ---
00396         KMO_TRY_ASSURE((parlist != NULL) &&
00397                        (frameset != NULL),
00398                        CPL_ERROR_NULL_INPUT,
00399                        "Not all input data is provided!");
00400 
00401         KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, DARK) == 1) ||
00402                        (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) ||
00403                        (cpl_frameset_count_tags(frameset, ARC_ON) == 1) ||
00404                        (cpl_frameset_count_tags(frameset, OBJECT) == 1) ||
00405                        (cpl_frameset_count_tags(frameset, STD) == 1) ||
00406                        (cpl_frameset_count_tags(frameset, SCIENCE) == 1),
00407                        CPL_ERROR_NULL_INPUT,
00408                        "A data frame (DARK, FLAT_ON, ARC_ON, OBJECT, STD or SCIENCE) must "
00409                        "be provided!");
00410 
00411         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, XCAL) == 1,
00412                        CPL_ERROR_FILE_NOT_FOUND,
00413                        "XCAL frame missing in frameset!!");
00414 
00415         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, YCAL) == 1,
00416                        CPL_ERROR_FILE_NOT_FOUND,
00417                        "YCAL frame missing in frameset!!");
00418 
00419         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, LCAL) == 1,
00420                        CPL_ERROR_FILE_NOT_FOUND,
00421                        "LCAL frame missing in frameset!!");
00422 
00423         KMO_TRY_ASSURE(cpl_frameset_count_tags(frameset, WAVE_BAND) == 1,
00424                        CPL_ERROR_FILE_NOT_FOUND,
00425                        "WAVE_BAND frame missing in frameset!!");
00426 
00427         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_reconstruct") == 1,
00428                        CPL_ERROR_ILLEGAL_INPUT,
00429                        "Cannot identify RAW and CALIB frames!");
00430 
00431         // --- get parameters ---
00432         cpl_msg_info("", "--- Parameter setup for kmo_reconstruct ---");
00433 
00434         KMO_TRY_EXIT_IF_NULL(
00435             imethod = kmo_dfs_get_parameter_string(parlist,
00436                                               "kmos.kmo_reconstruct.imethod"));
00437 
00438         KMO_TRY_ASSURE((strcmp(imethod, "NN") == 0) ||
00439                        (strcmp(imethod, "lwNN") == 0) ||
00440                        (strcmp(imethod, "swNN") == 0) ||
00441                        (strcmp(imethod, "MS") == 0) ||
00442                        (strcmp(imethod, "CS") == 0),
00443                        CPL_ERROR_ILLEGAL_INPUT,
00444                        "imethod must be either \"NN\", \"lwNN\", "
00445                        "\"swNN\", \"MS\" or \"CS\"!");
00446 
00447         KMO_TRY_EXIT_IF_ERROR(
00448             kmo_dfs_print_parameter_help(parlist,
00449                                         "kmos.kmo_reconstruct.imethod"));
00450 
00451         flux = kmo_dfs_get_parameter_bool(parlist,
00452                                           "kmos.kmo_reconstruct.flux");
00453 
00454         KMO_TRY_ASSURE((flux == 0) ||
00455                        (flux == 1),
00456                        CPL_ERROR_ILLEGAL_INPUT,
00457                        "flux must be either FALSE or TRUE!");
00458 
00459         KMO_TRY_EXIT_IF_ERROR(
00460             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.flux"));
00461 
00462         detectorimage = kmo_dfs_get_parameter_bool(parlist,
00463                                           "kmos.kmo_reconstruct.detectorimage");
00464 
00465         KMO_TRY_ASSURE((detectorimage == 0) ||
00466                        (detectorimage == 1),
00467                        CPL_ERROR_ILLEGAL_INPUT,
00468                        "detectorimage must be either 0 or 1 !");
00469 
00470         KMO_TRY_EXIT_IF_ERROR(
00471             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.detectorimage"));
00472 
00473         neighborhoodRange = kmo_dfs_get_parameter_double(parlist,
00474                 "kmos.kmo_reconstruct.neighborhoodRange");
00475         KMO_TRY_CHECK_ERROR_STATE();
00476 
00477         KMO_TRY_ASSURE(neighborhoodRange > 0.0,
00478                 CPL_ERROR_ILLEGAL_INPUT,
00479                 "neighborhoodRange must be greater than 0.0");
00480 
00481         KMO_TRY_EXIT_IF_ERROR(
00482             kmo_dfs_print_parameter_help(parlist,
00483                                      "kmos.kmo_reconstruct.neighborhoodRange"));
00484 
00485         kmo_band_pars_load(parlist, "kmos.kmo_reconstruct");
00486 
00487         file_extension = kmo_dfs_get_parameter_bool(parlist,
00488                                         "kmos.kmo_reconstruct.file_extension");
00489         KMO_TRY_CHECK_ERROR_STATE();
00490 
00491         KMO_TRY_EXIT_IF_ERROR(
00492            kmo_dfs_print_parameter_help(parlist,
00493                                        "kmos.kmo_reconstruct.file_extension"));
00494 
00495         dev_flip = kmo_dfs_get_parameter_bool(parlist,
00496                                            "kmos.kmo_reconstruct.dev_flip");
00497         KMO_TRY_CHECK_ERROR_STATE();
00498         KMO_TRY_EXIT_IF_ERROR(
00499             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_reconstruct.dev_flip"));
00500         KMO_TRY_ASSURE((dev_flip == TRUE) ||
00501                        (dev_flip == FALSE),
00502                        CPL_ERROR_ILLEGAL_INPUT,
00503                        "dev_flip must be TRUE or FALSE!");
00504 
00505 
00506         cpl_msg_info("", "-------------------------------------------");
00507 
00508         // load descriptor and header of data frame to reconstruct
00509         if (cpl_frameset_count_tags(frameset, DARK) == 1) {
00510             input_frame_name = DARK;
00511             output_frame_name = CUBE_DARK;
00512         } else if (cpl_frameset_count_tags(frameset, FLAT_ON) == 1) {
00513             input_frame_name = FLAT_ON;
00514             output_frame_name = CUBE_FLAT;
00515         } else if (cpl_frameset_count_tags(frameset, ARC_ON) == 1) {
00516             input_frame_name = ARC_ON;
00517             output_frame_name = CUBE_ARC;
00518         } else if (cpl_frameset_count_tags(frameset, OBJECT) == 1) {
00519             input_frame_name = OBJECT;
00520             output_frame_name = CUBE_OBJECT;
00521         } else if (cpl_frameset_count_tags(frameset, STD) == 1) {
00522             input_frame_name = STD;
00523             output_frame_name = CUBE_STD;
00524         } else if (cpl_frameset_count_tags(frameset, SCIENCE) == 1) {
00525             input_frame_name = SCIENCE;
00526             output_frame_name = CUBE_SCIENCE;
00527         }
00528 
00529         // assure that filters, grating and rotation offsets match for
00530         // XCAL, YCAL, LCAL and for data frame to reconstruct (except DARK
00531         // frames)
00532         // check if filter_id and grating_id match for all detectors
00533         KMO_TRY_EXIT_IF_ERROR(
00534             kmo_check_frame_setup(frameset, XCAL, YCAL,
00535                                        TRUE, FALSE, TRUE));
00536         KMO_TRY_EXIT_IF_ERROR(
00537             kmo_check_frame_setup(frameset, XCAL, LCAL,
00538                                        TRUE, FALSE, TRUE));
00539 
00540 // This check doesn't make sense here since OCS.ROT.NAANGLE is compared.
00541 // When creating the calibration files the RAW exposures needn't have been
00542 // provided in the same order
00543 //        KMO_TRY_EXIT_IF_ERROR(
00544 //            kmo_check_cal_frames_rotangle(frameset, XCAL, YCAL));
00545 //        KMO_TRY_EXIT_IF_ERROR(
00546 //            kmo_check_cal_frames_rotangle(frameset, XCAL, LCAL));
00547 
00548         if (cpl_frameset_count_tags(frameset, DARK) != 1) {
00549 
00550             // check if filters, gratings and rotator offset match
00551             // (except for DARK frames)
00552             KMO_TRY_EXIT_IF_ERROR(
00553                 kmo_check_frame_setup(frameset, XCAL, input_frame_name,
00554                                            TRUE, FALSE, FALSE));
00555 /*
00556             // check if rotator offset don't differ to much
00557             cpl_frame        *f1 = NULL, *f2 = NULL;
00558             cpl_propertylist *h1 = NULL, *h2 = NULL;
00559             char             *kw = NULL;
00560             double           tmp_dbl1 = 0.0, tmp_dbl2 = 0.0;
00561 
00562             KMO_TRY_EXIT_IF_NULL(
00563                 f1 = kmo_dfs_get_frame(frameset, XCAL));
00564 
00565             KMO_TRY_EXIT_IF_NULL(
00566                 f2 = kmo_dfs_get_frame(frameset, input_frame_name));
00567             h1 = kmclipm_propertylist_load(cpl_frame_get_filename(f1), 0);
00568             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00569                 cpl_msg_error("","File not found: %s!",
00570                               cpl_frame_get_filename(f1));
00571                 KMO_TRY_CHECK_ERROR_STATE();
00572             }
00573 
00574             h2 = kmclipm_propertylist_load(cpl_frame_get_filename(f2), 0);
00575             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00576                 cpl_msg_error("","File not found: %s!",
00577                               cpl_frame_get_filename(f2));
00578                 KMO_TRY_CHECK_ERROR_STATE();
00579             }
00580             KMO_TRY_EXIT_IF_NULL(
00581                 kw = cpl_sprintf("%s", ROTANGLE));
00582             tmp_dbl1 = cpl_propertylist_get_double(h1, kw);
00583             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00584                 KMO_TRY_ASSURE(1 == 0,
00585                                CPL_ERROR_ILLEGAL_INPUT,
00586                                "keyword \n%s\n of frame %s is missing!",
00587                                keyword, XCAL);
00588             }
00589 
00590             tmp_dbl2 = cpl_propertylist_get_double(h2, kw);
00591             if (cpl_error_get_code() != CPL_ERROR_NONE) {
00592                 KMO_TRY_ASSURE(1 == 0,
00593                                CPL_ERROR_ILLEGAL_INPUT,
00594                                "keyword \n%s\n of frame %s is missing!",
00595                                keyword, input_frame_name);
00596             }
00597 
00598             // strip angles below 0 deg and above 360 deg
00599             kmclipm_strip_angle(&tmp_dbl1);
00600             kmclipm_strip_angle(&tmp_dbl2);
00601 
00602             if (fabs(tmp_dbl1 - tmp_dbl2) > 30.) {
00603                 if ((fabs(tmp_dbl1) < 0.001) && (tmp_dbl2>330) && (tmp_dbl2<360)) {
00604                     // singularity!
00605                     // we have rot=0 for XCAL and rot>330 | rot<360 for input frame
00606                 } else {
00607                 cpl_msg_warning("","The angle of the calibration files (%g deg) "
00608                                 "and the angle of the frame to reconstruct"
00609                                 " (%g deg) differ by %g deg! Think about using "
00610                                 "calibration files matching better the actual "
00611                                 "rotator offset (ESO OCS ROT NAANGLE)",
00612                                 tmp_dbl1, tmp_dbl2,
00613                                 fabs(tmp_dbl1 - tmp_dbl2));
00614                 }
00615             }
00616 
00617             cpl_propertylist_delete(h1); h1 = NULL;
00618             cpl_propertylist_delete(h2); h2 = NULL;
00619             cpl_free(kw); kw = NULL;
00620 */
00621         }
00622 
00623         KMO_TRY_EXIT_IF_NULL(
00624             xcal_frame = kmo_dfs_get_frame(frameset, XCAL));
00625         KMO_TRY_EXIT_IF_NULL(
00626             rec_frame = kmo_dfs_get_frame(frameset, input_frame_name));
00627         KMO_TRY_EXIT_IF_NULL(
00628             suffix = kmo_dfs_get_suffix(rec_frame, TRUE, TRUE));
00629 
00630         cpl_msg_info("", "Detected instrument setup:   %s", suffix+1);
00631         cpl_msg_info("", "(grating 1, 2 & 3, rotation angle)");
00632         cpl_msg_info("", "-------------------------------------------");
00633 
00634 
00635         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(rec_frame));
00636         KMO_TRY_CHECK_ERROR_STATE();
00637 
00638         KMO_TRY_ASSURE(((desc1.nr_ext == KMOS_NR_DETECTORS) ||
00639                         ((desc1.nr_ext == 2*KMOS_NR_DETECTORS))) &&
00640                        (desc1.ex_badpix == FALSE) &&
00641                        ((desc1.fits_type == raw_fits) ||
00642                         (desc1.fits_type == f2d_fits)) &&
00643                        (desc1.frame_type == detector_frame),
00644                        CPL_ERROR_ILLEGAL_INPUT,
00645                        "The frame to reconstruct isn't in the correct format!!!"
00646                        "Exactly 3 frames, or 6 with noise are expected!");
00647 
00648         if (!desc1.ex_noise) {
00649             nr_devices = desc1.nr_ext;
00650         } else {
00651             nr_devices = desc1.nr_ext / 2;
00652         }
00653 
00654         // compare descriptor of XCAL and data frame to reconstruct
00655         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(xcal_frame));
00656         KMO_TRY_CHECK_ERROR_STATE();
00657 
00658         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00659                        (desc1.ex_badpix == desc2.ex_badpix) &&
00660                        (desc1.frame_type == desc2.frame_type),
00661                        CPL_ERROR_ILLEGAL_INPUT,
00662                        "XCAL isn't in the correct format!!!");
00663 
00664         kmo_free_fits_desc(&desc2);
00665 
00666         // compare descriptor of YCAL and data frame to reconstruct
00667         kmo_init_fits_desc(&desc2);
00668 
00669         KMO_TRY_EXIT_IF_NULL(
00670             ycal_frame = kmo_dfs_get_frame(frameset, YCAL));
00671 
00672         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(ycal_frame));
00673         KMO_TRY_CHECK_ERROR_STATE();
00674 
00675         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00676                        (desc1.ex_badpix == desc2.ex_badpix) &&
00677                        (desc1.frame_type == desc2.frame_type),
00678                        CPL_ERROR_ILLEGAL_INPUT,
00679                        "YCAL isn't in the correct format!!!");
00680 
00681         kmo_free_fits_desc(&desc2);
00682 
00683         // compare descriptor of LCAL and data frame to reconstruct
00684         kmo_init_fits_desc(&desc2);
00685 
00686         KMO_TRY_EXIT_IF_NULL(
00687             lcal_frame = kmo_dfs_get_frame(frameset, LCAL));
00688 
00689         desc2 = kmo_identify_fits_header(cpl_frame_get_filename(lcal_frame));
00690         KMO_TRY_CHECK_ERROR_STATE();
00691 
00692         KMO_TRY_ASSURE((desc2.nr_ext % 3 == 0) &&
00693                        (desc1.ex_badpix == desc2.ex_badpix) &&
00694                        (desc1.frame_type == desc2.frame_type),
00695                        CPL_ERROR_ILLEGAL_INPUT,
00696                        "LCAL isn't in the correct format!!!");
00697 
00698         kmo_free_fits_desc(&desc2);
00699 
00700         //
00701         // --- load, update & save primary header ---
00702         //
00703         KMO_TRY_EXIT_IF_NULL(
00704             main_header = kmo_dfs_load_primary_header(frameset,
00705                                                       input_frame_name));
00706 
00707         KMO_TRY_EXIT_IF_NULL(
00708             tmp_header = kmo_dfs_load_primary_header(frameset, LCAL));
00709 
00710         // assert that filters have correct IDs and that all detectors of all
00711         // input frames have the same filter set
00712         for (i = 1; i <= nr_devices; i++) {
00713             // ESO INS FILTi ID
00714             KMO_TRY_EXIT_IF_NULL(
00715                 keyword = cpl_sprintf("%s%d%s", IFU_FILTID_PREFIX, i,
00716                                       IFU_FILTID_POSTFIX));
00717 
00718             KMO_TRY_EXIT_IF_NULL(
00719                 filter_id = cpl_propertylist_get_string(tmp_header, keyword));
00720 
00721             KMO_TRY_ASSURE((strcmp(filter_id, "IZ") == 0) ||
00722                            (strcmp(filter_id, "YJ") == 0) ||
00723                            (strcmp(filter_id, "H") == 0) ||
00724                            (strcmp(filter_id, "K") == 0) ||
00725                            (strcmp(filter_id, "HK") == 0),
00726                            CPL_ERROR_ILLEGAL_INPUT,
00727                            "Filter ID in primary header of LCAL frame must "
00728                            "be either \"IZ\", \"YJ\", \"H\", \"K\" or "
00729                            "\"HK\" !");
00730 
00731             if (strcmp(input_frame_name, DARK) != 0) {
00732                 // dark needn't to be taken with filter!
00733 
00734                 KMO_TRY_EXIT_IF_NULL(
00735                     filter_id_tmp = cpl_propertylist_get_string(main_header,
00736                                                                 keyword));
00737                 KMO_TRY_ASSURE(strcmp(filter_id, filter_id_tmp) == 0,
00738                                CPL_ERROR_ILLEGAL_INPUT,
00739                                "Filter IDs must be the same for LCAL frame and "
00740                                "the frame to reconstruct!"
00741                                "Detector No.: %d\nLCAL: %s\n%s: %s\n",
00742                                i, filter_id, input_frame_name, filter_id_tmp);
00743             }
00744             cpl_free(keyword); keyword = NULL;
00745         }
00746         KMO_TRY_EXIT_IF_NULL(
00747             my_filter_id = cpl_strdup(filter_id));
00748         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00749 
00750         obs_id = cpl_propertylist_get_int(main_header, OBS_ID);
00751         KMO_TRY_CHECK_ERROR_STATE();
00752 
00753         KMO_TRY_EXIT_IF_NULL(
00754             filename_cube = cpl_sprintf("%s", output_frame_name));
00755         KMO_TRY_EXIT_IF_NULL(
00756             filename_img = cpl_sprintf("%s", DET_IMG_REC));
00757         if (file_extension) {
00758             KMO_TRY_EXIT_IF_NULL(
00759                 obs_suffix = cpl_sprintf("%s%d", "_", obs_id));
00760         } else {
00761             KMO_TRY_EXIT_IF_NULL(
00762                 obs_suffix = cpl_sprintf("%s", ""));
00763         }
00764 
00765         KMO_TRY_EXIT_IF_ERROR(
00766             kmo_dfs_save_main_header(frameset, filename_cube, obs_suffix,
00767                                      rec_frame, NULL, parlist, cpl_func));
00768 
00769         // setup grid definition, wavelength start and end points will be set
00770         // in the detector loop
00771         KMO_TRY_EXIT_IF_ERROR(
00772             kmclipm_setup_grid(&gd, imethod, neighborhoodRange));
00773 
00774         KMO_TRY_EXIT_IF_NULL(
00775             tmp_header = kmo_dfs_load_primary_header(frameset, XCAL));
00776 
00777         KMO_TRY_EXIT_IF_NULL(
00778             bounds = kmclipm_extract_bounds(tmp_header));
00779         cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00780 
00781         if (detectorimage == TRUE) {
00782             KMO_TRY_EXIT_IF_ERROR(
00783                 kmo_dfs_save_main_header(frameset, filename_img, obs_suffix,
00784                                          rec_frame, NULL, parlist, cpl_func));
00785         }
00786 
00787         /* loop through all detectors */
00788         for (i = 1; i <= nr_devices; i++) {
00789             cpl_msg_info("","Processing detector No. %d", i);
00790 
00791             // load lcal
00792             // extract LCAL image close to ROTANGLE 0. assuming that the wavelength range
00793             // doesn't differ too much with different ROTANGLEs.
00794             double rotangle_found;
00795             KMO_TRY_EXIT_IF_NULL(
00796                 lcal = kmo_dfs_load_cal_image(frameset, LCAL, i, FALSE, 0.,
00797                                               FALSE, NULL, &rotangle_found));
00798 
00799             char *tmp_band_method = getenv("KMO_BAND_METHOD");
00800             int band_method = 0;
00801             if (tmp_band_method != NULL) {
00802                 band_method = atoi(tmp_band_method);
00803             }
00804 
00805             KMO_TRY_EXIT_IF_NULL(
00806                 band_table = kmo_dfs_load_table(frameset, WAVE_BAND, 1, FALSE));
00807 
00808             KMO_TRY_EXIT_IF_ERROR(
00809                 kmclipm_setup_grid_band_lcal(&gd, lcal, my_filter_id,
00810                                              band_method, band_table));
00811             cpl_table_delete(band_table); band_table = NULL;
00812 
00813             cpl_image_delete(lcal); lcal = NULL;
00814 
00815             if (detectorimage == TRUE) {
00816                 KMO_TRY_EXIT_IF_NULL(
00817                     det_img_data[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR,
00818                                                       gd.l.dim, CPL_TYPE_FLOAT));
00819                 KMO_TRY_EXIT_IF_NULL(
00820                     pdet_img_data = cpl_image_get_data_float(det_img_data[i-1]));
00821 
00822                 KMO_TRY_EXIT_IF_NULL(
00823                     det_img_noise[i-1] = cpl_image_new(gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR,
00824                                                       gd.l.dim, CPL_TYPE_FLOAT));
00825                 KMO_TRY_EXIT_IF_NULL(
00826                     pdet_img_noise = cpl_image_get_data_float(det_img_noise[i-1]));
00827             }
00828 
00829 
00830             for (j = 0; j < KMOS_IFUS_PER_DETECTOR; j++) {
00831                 /* update sub-header */
00832                 ifu_nr = (i-1)*KMOS_IFUS_PER_DETECTOR + j + 1;
00833 
00834                 /* load raw image and sub-header*/
00835                 KMO_TRY_EXIT_IF_NULL(
00836                     sub_header = kmo_dfs_load_sub_header(frameset, input_frame_name,
00837                                                          i, FALSE));
00838                 KMO_TRY_EXIT_IF_NULL(
00839                     sub_header_orig = cpl_propertylist_duplicate(sub_header));
00840 
00841                 // check if IFU is valid according to main header keywords &
00842                 // calibration files
00843 
00844                 if (getenv("KMOS_RECONSTRUCT_ALL") == NULL) {
00845                     KMO_TRY_EXIT_IF_NULL(
00846                         keyword = cpl_sprintf("%s%d%s", IFU_VALID_PREFIX, ifu_nr,
00847                                               IFU_VALID_POSTFIX));
00848                     KMO_TRY_CHECK_ERROR_STATE();
00849                     cpl_propertylist_get_string(main_header, keyword);
00850                     cpl_free(keyword); keyword = NULL;
00851                 } else {
00852                     // if KMOS_RECONSTRUCT_ALL is set all IFUs should be
00853                     // reconstructed
00854                     cpl_propertylist_get_string(main_header, "ggg");
00855                 }
00856 
00857                 if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) &&
00858                     (bounds[2*(ifu_nr-1)] != -1) &&
00859                     (bounds[2*(ifu_nr-1)+1] != -1))
00860                 {
00861                     cpl_error_reset();
00862                     // IFU is valid
00863                     actual_sub_header = sub_header;
00864 
00865                     // calculate WCS
00866                     KMO_TRY_EXIT_IF_ERROR(
00867                         kmo_calc_wcs(main_header, actual_sub_header, ifu_nr,
00868                                      gd.l.start, gd.l.delta));
00869 
00870                     // reconstruct data and noise (if available)
00871                     if (j == 0) {
00872                         sat_mode_msg = FALSE;
00873                     } else {
00874                         sat_mode_msg = TRUE;
00875                     }
00876                     KMO_TRY_EXIT_IF_ERROR(
00877                         kmo_reconstruct_sci(ifu_nr,
00878                                             bounds[2*(ifu_nr-1)],
00879                                             bounds[2*(ifu_nr-1)+1],
00880                                             rec_frame,
00881                                             input_frame_name,
00882                                             NULL,
00883                                             NULL,
00884                                             NULL,
00885                                             xcal_frame,
00886                                             ycal_frame,
00887                                             lcal_frame,
00888                                             &gd,
00889                                             &cube_data,
00890                                             &cube_noise,
00891                                             flux));
00892                 } else {
00893                     // IFU is invalid
00894                     actual_sub_header = sub_header_orig;
00895                     cpl_error_reset();
00896                 } // if ((cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) ..
00897 
00898                 if (detectorimage) {
00899                     if (cube_data != NULL) {
00900                         for (int l=0; l<gd.l.dim; l++) {
00901                             KMO_TRY_EXIT_IF_NULL(
00902                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_data, l)));
00903                             for (int y=0; y<gd.y.dim; y++) {
00904                                 for (int x=0; x<gd.x.dim; x++) {
00905                                     int ix = x +
00906                                              y * gd.x.dim +
00907                                              j * gd.x.dim*gd.y.dim +     //IFU offset
00908                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
00909                                     pdet_img_data[ix] = slice[x + y*gd.x.dim];
00910                                 }
00911                             }
00912                         }
00913                     }
00914                     if (cube_noise != NULL) {
00915                         if (detectorimage) {
00916                             detImgCube = TRUE;
00917                         }
00918                         for (int l=0; l<gd.l.dim; l++) {
00919                             KMO_TRY_EXIT_IF_NULL(
00920                                 slice = cpl_image_get_data_float(cpl_imagelist_get(cube_noise, l)));
00921                             for (int y=0; y<gd.y.dim; y++) {
00922                                 for (int x=0; x<gd.x.dim; x++) {
00923                                     int ix = x +
00924                                              y * gd.x.dim +
00925                                              j * gd.x.dim*gd.y.dim +     //IFU offset
00926                                              l * gd.x.dim*gd.y.dim*KMOS_IFUS_PER_DETECTOR;
00927                                     pdet_img_noise[ix] = slice[x + y*gd.x.dim];
00928                                 }
00929                             }
00930                         }
00931                     }
00932                 }
00933 
00934                 // save output
00935                 KMO_TRY_EXIT_IF_NULL(
00936                     extname = kmo_extname_creator(ifu_frame, ifu_nr,
00937                                                   EXT_DATA));
00938 
00939                 KMO_TRY_EXIT_IF_ERROR(
00940                     kmclipm_update_property_string(actual_sub_header,
00941                                             EXTNAME,
00942                                             extname,
00943                                             "FITS extension name"));
00944 
00945                 cpl_free(extname); extname = NULL;
00946 
00947                 KMO_TRY_EXIT_IF_ERROR(
00948                     kmo_dfs_save_cube(cube_data, filename_cube, obs_suffix,
00949                                       actual_sub_header, 0./0.));
00950 
00951                 if (cube_noise != NULL) {
00952                     KMO_TRY_EXIT_IF_NULL(
00953                         extname = kmo_extname_creator(ifu_frame, ifu_nr,
00954                                                       EXT_NOISE));
00955 
00956                     KMO_TRY_EXIT_IF_ERROR(
00957                         kmclipm_update_property_string(actual_sub_header,
00958                                                 EXTNAME,
00959                                                 extname,
00960                                                 "FITS extension name"));
00961 
00962                     cpl_free(extname); extname = NULL;
00963 
00964                     KMO_TRY_EXIT_IF_ERROR(
00965                         kmo_dfs_save_cube(cube_noise, filename_cube, obs_suffix,
00966                                           actual_sub_header, 0./0.));
00967                 }
00968 
00969                 cpl_imagelist_delete(cube_data); cube_data = NULL;
00970                 cpl_imagelist_delete(cube_noise); cube_noise = NULL;
00971                 cpl_propertylist_delete(sub_header); sub_header = NULL;
00972                 cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
00973             } // for j IFUs
00974 
00975             if (detectorimage) {
00976                 index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
00977                                            i, FALSE);
00978                 KMO_TRY_CHECK_ERROR_STATE();
00979 
00980                 KMO_TRY_EXIT_IF_NULL(
00981                     tmp_header = kmclipm_propertylist_load(
00982                                          cpl_frame_get_filename(rec_frame), index));
00983                 KMO_TRY_EXIT_IF_ERROR(
00984                     kmo_save_det_img_ext(det_img_data[i-1], gd, i, filename_img,
00985                                          obs_suffix, tmp_header, dev_flip, FALSE));
00986                 cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00987 
00988                 if (detImgCube) {
00989                     if (desc1.ex_noise) {
00990                         index = kmo_identify_index(cpl_frame_get_filename(rec_frame),
00991                                                    i, TRUE);
00992                         KMO_TRY_CHECK_ERROR_STATE();
00993                     } else {
00994                         // use same index as for data frame, since input frame
00995                         // has just 3 extensions
00996                     }
00997                     KMO_TRY_EXIT_IF_NULL(
00998                         tmp_header = kmclipm_propertylist_load(
00999                                              cpl_frame_get_filename(rec_frame), index));
01000                     KMO_TRY_EXIT_IF_ERROR(
01001                         kmo_save_det_img_ext(det_img_noise[i-1], gd, i, filename_img,
01002                                              obs_suffix, tmp_header, dev_flip, TRUE));
01003                     cpl_propertylist_delete(tmp_header); tmp_header = NULL;
01004                 }
01005             }
01006 
01007             // free memory
01008             cpl_imagelist_delete(cube_data); cube_data = NULL;
01009             cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01010             cpl_propertylist_delete(sub_header); sub_header = NULL;
01011             cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01012         } // for i devices
01013     }
01014     KMO_CATCH
01015     {
01016         KMO_CATCH_MSG();
01017         ret_val = -1;
01018     }
01019 
01020     kmo_free_fits_desc(&desc1);
01021     kmo_free_fits_desc(&desc2);
01022     for (int i=0; i<KMOS_NR_DETECTORS; i++) {
01023         cpl_image_delete(det_img_data[i]); det_img_data[i] = NULL;
01024         cpl_image_delete(det_img_noise[i]); det_img_noise[i] = NULL;
01025     }
01026     cpl_free(my_filter_id); my_filter_id = NULL;
01027     cpl_free(bounds); bounds = NULL;
01028     cpl_propertylist_delete(main_header); main_header = NULL;
01029     cpl_propertylist_delete(sub_header); sub_header = NULL;
01030     cpl_propertylist_delete(sub_header_orig); sub_header_orig = NULL;
01031     cpl_imagelist_delete(cube_data); cube_data = NULL;
01032     cpl_imagelist_delete(cube_noise); cube_noise = NULL;
01033     cpl_free(obs_suffix); obs_suffix = NULL;
01034     cpl_free(suffix); suffix = NULL;
01035     cpl_free(filename_img); filename_img = NULL;
01036     cpl_free(filename_cube); filename_cube = NULL;
01037     sat_mode_msg = FALSE;
01038 
01039     return ret_val;
01040 }
01041