KMOS Pipeline Reference Manual  1.2.0
kmo_combine.c
00001 /* $Id: kmo_combine.c,v 1.31 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.31 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <string.h>
00033 #include <math.h>
00034 
00035 #include <cpl.h>
00036 #include <cpl_wcs.h>
00037 
00038 #include "kmo_debug.h"
00039 #include "kmo_utils.h"
00040 #include "kmo_dfs.h"
00041 #include "kmo_error.h"
00042 #include "kmo_priv_functions.h"
00043 #include "kmo_cpl_extensions.h"
00044 #include "kmo_constants.h"
00045 #include "kmo_priv_combine.h"
00046 
00047 static int kmo_combine_create(cpl_plugin *);
00048 static int kmo_combine_exec(cpl_plugin *);
00049 static int kmo_combine_destroy(cpl_plugin *);
00050 static int kmo_combine(cpl_parameterlist *, cpl_frameset *);
00051 
00052 static char kmo_combine_description[] =
00053 "This recipe shifts several exposures of an object and combines them. The diffe-\n"
00054 "rent methods to match the exposures are described below (--method parameter).\n"
00055 "The output cube is larger than the input cubes, according to the shifts to be\n"
00056 "applied. Additionally a border of NaN values is added. The WCS is the same as\n"
00057 "for the first exposure.\n"
00058 "For each spatial/spectral pixel a new value will be calculated (according the\n"
00059 "--cmethod parameter) and written into the output cube.\n"
00060 "Only exposures with equal orientation regarding the WCS can be combined (except\n"
00061 "-–method=”none”), north must point to the same direction. It is recommended to\n"
00062 "apply any rotation possibly after combining.\n"
00063 "\n"
00064 "The behavior of the selection of IFUs to combine differs for some templates and\n"
00065 "can be controlled with the parameters --name and --ifus.\n"
00066 "If the input data cubes stem from templates KMOS_spec_obs_mapping8 or\n"
00067 "KMOS_spec_obs_mapping24 all extensions from all input frames are combined into\n"
00068 "a single map by default (like in recipe kmo_sci_red). If just the area of a\n"
00069 "specific IFU should be combined, the parameter --ifus can be specified, or more\n"
00070 "easily --name.\n"
00071 "If the input data cubes stem from other templates like e.g.\n"
00072 "KMOS_spec_obs_freedither all extensions of all input frames are combined into\n"
00073 "several output frames by default. The input IFUs are grouped according their\n"
00074 "targeted object name stored in the keywords ESO OCS ARMx NAME. If just a\n"
00075 "specific object should be combined, its name can be specified with parameter\n"
00076 "--name. If arbitrary IFUs shoukd be comined, one can specify these with the\n"
00077 "parameter --ifus.\n"
00078 "\n"
00079 "The default mapping mode is done via the --name parameter, where the name of\n"
00080 "the object has to be provided. The recipe searches in all input data cubes IFUs\n"
00081 "pointing to that object.\n"
00082 "\n"
00083 "BASIC PARAMETERS:\n"
00084 "-----------------\n"
00085 "--name\n"
00086 "--ifus\n"
00087 "Since an object can be present only once per exposure and since it can be\n"
00088 "located in different IFUs for the existing exposures, there are two modes to\n"
00089 "identify the objects:\n"
00090 "   * Combine by object names (default)\n"
00091 "   In this case the object name must be provided via the --name parameter. The\n"
00092 "   object name will be searched for in all primary headers of all provided frames\n"
00093 "   in the keyword ESO OCS ARMx NAME.\n"
00094 "\n"
00095 "   * Combine by index (advanced)\n"
00096 "   In this case the --ifus parameter must be provided. The parameter must have\n"
00097 "   the same number of entries as frames are provided, e.g. \"3;1;24\" for 3 expo-\n"
00098 "   sures. The index doesn't reference the extension in the frame but the real\n"
00099 "   index of the IFU as defined in the EXTNAME keyword (e.g. 'IFU.3.DATA').\n"
00100 "\n"
00101 "--method\n"
00102 "There are following sources to get the shift parameters from:\n"
00103 "   * 'none' (default)\n"
00104 "   The cubes are directly recombined, not shifting at all. The ouput frame will\n"
00105 "   have the same dimensions as the input cubes.\n"
00106 "   If the size differs a warning will be emitted and the cubes will be aligned\n"
00107 "   to the lower left corner. If the orientation differs a warning will be emit-\n"
00108 "   ted, but the cubes are combined anyway.\n"
00109 "\n"
00110 "   * 'header'\n"
00111 "   The shifts are calculated according to the WCS information stored in the\n"
00112 "   header of every IFU. The output frame will get larger, except the object is\n"
00113 "   at the exact same position for all exposures. The size of the exposures can\n"
00114 "   differ, but the orientation must be the same for all exposures.\n"
00115 "\n"
00116 "   * 'center'\n"
00117 "   The shifts are calculated using a centering algorithm. The cube will be col-\n"
00118 "   lapsed and a 2D profile will be fitted to it to identify the centre. With \n"
00119 "   the parameter --fmethod the function to fit can be provided. The size of the\n"
00120 "   exposures can differ, but the orientation must be the same for all exposures.\n"
00121 "\n"
00122 "   * 'user'\n"
00123 "   Read the shifts from a user specified file. The path of the file must be pro-\n"
00124 "   vided using the --filename parameter. For every exposure (except the first one)\n"
00125 "   two shift values are expected per line, they have to be separated with simple\n"
00126 "   spaces. The values indicate pixel shifts and are referenced to the first\n"
00127 "   frame. The 1st value is the shift in x-direction to the left, the 2nd the\n"
00128 "   shift in y-direction upwards. The size of the exposures can differ, but the\n"
00129 "   orientation must be the same for all exposures.\n"
00130 "\n"
00131 "--cmethod\n"
00132 "Following methods of frame combination are available:\n"
00133 "   * 'ksigma' (Default)\n"
00134 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00135 "   are examined. If they deviate significantly, they will be rejected according\n"
00136 "   to the conditions:\n"
00137 "       val > mean + stdev * cpos_rej\n"
00138 "   and\n"
00139 "       val < mean - stdev * cneg_rej\n"
00140 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00141 "   parameters. In the first iteration median and percentile level are used.\n"
00142 "\n"
00143 "   * 'median'\n"
00144 "   At each pixel position the median is calculated.\n"
00145 "\n"
00146 "   * 'average'\n"
00147 "   At each pixel position the average is calculated.\n"
00148 "\n"
00149 "   * 'sum'\n"
00150 "   At each pixel position the sum is calculated.\n"
00151 "\n"
00152 "   * 'min_max'\n"
00153 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00154 "   --cmax and --cmin apply to this method.\n"
00155 "\n"
00156 "ADVANCED PARAMETERS\n"
00157 "-------------------\n"
00158 "--edge_nan\n"
00159 "Set borders of two sides of the cubes to NaN before combining them. This minimises\n"
00160 "unwanted border effects when dithering.\n"
00161 "\n"
00162 "--fmethod\n"
00163 "see --method='center'\n"
00164 "The type of function that should be fitted spatially to the collapsed image.\n"
00165 "This fit is used to create a mask to extract the spectrum of the object. Valid\n"
00166 "values are “gauss” and “moffat”.\n"
00167 "\n"
00168 "--filename\n"
00169 "see --method='user'\n"
00170 "\n"
00171 "--cpos_rej\n"
00172 "--cneg_rej\n"
00173 "--citer\n"
00174 "see --cmethod='ksigma'\n"
00175 "\n"
00176 "--cmax\n"
00177 "--cmin\n"
00178 "see --cmethod='min_max'\n"
00179 "\n"
00180 "--flux\n"
00181 "Specify if flux conservation should be applied.\n"
00182 "\n"
00183 "--suppress_extension\n"
00184 "If set to TRUE, the arbitrary filename extensions are supressed. If multiple\n"
00185 "products with the same category are produced, they will be numered consecutively\n"
00186 "starting from 0.\n"
00187 "\n"
00188 "-------------------------------------------------------------------------------\n"
00189 "  Input files:\n"
00190 "\n"
00191 "   DO                      KMOS                                                \n"
00192 "   category                Type   Explanation                  Required #Frames\n"
00193 "   --------                -----  -----------                  -------- -------\n"
00194 "   <none or any>           F3I    data frame                       Y      2-n  \n"
00195 "\n"
00196 "  Output files:\n"
00197 "\n"
00198 "   DO                      KMOS\n"
00199 "   category                Type   Explanation\n"
00200 "   --------                -----  -----------\n"
00201 "   COMBINE_<ESO PRO CATG>  F3I    Combined data cube\n"
00202 "-------------------------------------------------------------------------------\n"
00203 "\n";
00204 
00221 int cpl_plugin_get_info(cpl_pluginlist *list)
00222 {
00223     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00224     cpl_plugin *plugin = &recipe->interface;
00225 
00226     cpl_plugin_init(plugin,
00227                         CPL_PLUGIN_API,
00228                         KMOS_BINARY_VERSION,
00229                         CPL_PLUGIN_TYPE_RECIPE,
00230                         "kmo_combine",
00231                         "Combine reconstructed cubes",
00232                         kmo_combine_description,
00233                         "Alex Agudo Berbel",
00234                         "kmos-spark@mpe.mpg.de",
00235                         kmos_get_license(),
00236                         kmo_combine_create,
00237                         kmo_combine_exec,
00238                         kmo_combine_destroy);
00239 
00240     cpl_pluginlist_append(list, plugin);
00241 
00242     return 0;
00243 }
00244 
00252 static int kmo_combine_create(cpl_plugin *plugin)
00253 {
00254     cpl_recipe *recipe;
00255     cpl_parameter *p;
00256 
00257     /* Check that the plugin is part of a valid recipe */
00258     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00259         recipe = (cpl_recipe *)plugin;
00260     else
00261         return -1;
00262 
00263     /* Create the parameters list in the cpl_recipe object */
00264     recipe->parameters = cpl_parameterlist_new();
00265 
00266     /* Fill the parameters list */
00267     /* --name */
00268     p = cpl_parameter_new_value("kmos.kmo_combine.name",
00269                                 CPL_TYPE_STRING,
00270                                 "Name of the object to combine.",
00271                                 "kmos.kmo_combine",
00272                                 "");
00273     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "name");
00274     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00275     cpl_parameterlist_append(recipe->parameters, p);
00276 
00277     /* --ifus */
00278     p = cpl_parameter_new_value("kmos.kmo_combine.ifus",
00279                                 CPL_TYPE_STRING,
00280                                 "The indices of the IFUs to combine. "
00281                                 "\"ifu1;ifu2;...\"",
00282                                 "kmos.kmo_combine",
00283                                 "");
00284     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ifus");
00285     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00286     cpl_parameterlist_append(recipe->parameters, p);
00287 
00288     /* --method */
00289     p = cpl_parameter_new_value("kmos.kmo_combine.method",
00290                                 CPL_TYPE_STRING,
00291                                 "The shifting method:   "
00292                                 "'none': no shifting, combined directly "
00293                                                                   "(default), "
00294                                 "'header': shift according to WCS, "
00295                                 "'center': centering algorithm, "
00296                                 "'user': read shifts from file",
00297                                 "kmos.kmo_combine",
00298                                 "none");
00299     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00300     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00301     cpl_parameterlist_append(recipe->parameters, p);
00302 
00303     /* --fmethod */
00304     p = cpl_parameter_new_value("kmos.kmo_combine.fmethod",
00305                                 CPL_TYPE_STRING,
00306                                 "The fitting method (applies only when "
00307                                 "method='center'):   "
00308                                 "'gauss': fit a gauss function to collapsed "
00309                                 "image (default), "
00310                                 "'moffat': fit a moffat function to collapsed"
00311                                 " image",
00312                                 "kmos.kmo_combine",
00313                                 "gauss");
00314     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fmethod");
00315     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00316     cpl_parameterlist_append(recipe->parameters, p);
00317 
00318     /* --filename */
00319     p = cpl_parameter_new_value("kmos.kmo_combine.filename",
00320                                 CPL_TYPE_STRING,
00321                                 "The path to the file with the shift vectors."
00322                                 "(Applies only to method='user')",
00323                                 "kmos.kmo_combine",
00324                                 "");
00325     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filename");
00326     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00327     cpl_parameterlist_append(recipe->parameters, p);
00328 
00329     /* --flux */
00330     p = cpl_parameter_new_value("kmos.kmo_combine.flux",
00331                                 CPL_TYPE_BOOL,
00332                                 "Apply flux conservation: "
00333                                 "(TRUE (apply) or "
00334                                 "FALSE (don't apply)",
00335                                 "kmos.kmo_combine",
00336                                 FALSE);
00337     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
00338     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00339     cpl_parameterlist_append(recipe->parameters, p);
00340 
00341     /* --edge_nan */
00342     p = cpl_parameter_new_value("kmos.kmo_combine.edge_nan",
00343                                 CPL_TYPE_BOOL,
00344                                 "Set borders of cubes to NaN before combining them."
00345                                 "(TRUE (apply) or "
00346                                 "FALSE (don't apply)",
00347                                 "kmos.kmo_combine",
00348                                 FALSE);
00349     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "edge_nan");
00350     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00351     cpl_parameterlist_append(recipe->parameters, p);
00352 
00353     /* --suppress_extension */
00354     p = cpl_parameter_new_value("kmos.kmo_combine.suppress_extension",
00355                                 CPL_TYPE_BOOL,
00356                                 "Suppress arbitrary filename extension."
00357                                 "(TRUE (apply) or FALSE (don't apply)",
00358                                 "kmos.kmo_combine",
00359                                 FALSE);
00360     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "suppress_extension");
00361     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00362     cpl_parameterlist_append(recipe->parameters, p);
00363 
00364     return kmo_combine_pars_create(recipe->parameters,
00365                                    "kmos.kmo_combine",
00366                                    DEF_REJ_METHOD,
00367                                    FALSE);
00368 }
00369 
00375 static int kmo_combine_exec(cpl_plugin *plugin)
00376 {
00377     cpl_recipe  *recipe;
00378 
00379     /* Get the recipe out of the plugin */
00380     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00381         recipe = (cpl_recipe *)plugin;
00382     else return -1 ;
00383 
00384     return kmo_combine(recipe->parameters, recipe->frames);
00385 }
00386 
00392 static int kmo_combine_destroy(cpl_plugin *plugin)
00393 {
00394     cpl_recipe *recipe;
00395 
00396     /* Get the recipe out of the plugin */
00397     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00398         recipe = (cpl_recipe *)plugin;
00399     else return -1 ;
00400 
00401     cpl_parameterlist_delete(recipe->parameters);
00402     return 0 ;
00403 }
00404 
00405 //int kmo_tolerance_round(double x, double tol)
00406 //{
00407 //    int ret = 0;
00408 
00409 //    KMO_TRY
00410 //    {
00411 //        if (fabs(x - floor(x)) < tol) {
00412 //            // value is slightly greater than the real int value
00413 //            ret = floor(x);
00414 //        } else {
00415 //            if (fabs(x - floor(x+tol)) < tol) {
00416 //                // value is slightly greater than the real int value
00417 //                ret = floor(x+tol);
00418 //            } else {
00419 //                // error: sub pixel shift
00420 //                KMO_TRY_ASSURE(1 == 0,
00421 //                               CPL_ERROR_ILLEGAL_INPUT,
00422 //                               "Please apply only whole pixel shifts here "
00423 //                               "and no subpixel shifts!");
00424 //            }
00425 //        }
00426 //    }
00427 //    KMO_CATCH
00428 //    {
00429 //        KMO_CATCH_MSG();
00430 
00431 //        ret = 0;
00432 //    }
00433 
00434 //    return ret;
00435 //}
00436 
00451 static int kmo_combine(cpl_parameterlist *parlist, cpl_frameset *frameset)
00452 {
00453     const char       *method             = NULL,
00454                      *cmethod            = NULL,
00455                      *fmethod            = NULL,
00456                      *filename           = NULL,
00457                      *frame_filename     = NULL,
00458                      *ifus_txt           = NULL,
00459                      *tmp_strc           = NULL;
00460 
00461     char             *tmp_str            = NULL,
00462                      *mapping_mode       = NULL,
00463                      *name               = NULL,
00464                      **name_vec          = NULL;
00465 
00466     cpl_imagelist    **data_cube_list    = NULL,
00467                      **noise_cube_list   = NULL,
00468                      *cube_combined_data = NULL,
00469                      *cube_combined_noise= NULL;
00470 
00471     cpl_vector       *ifus               = NULL;
00472 
00473     int              ret_val             = 0,
00474                      nr_frames           = 0,
00475                      index               = 0,
00476                      data_cube_counter   = 0,
00477                      noise_cube_counter  = 0,
00478                      citer               = 0,
00479                      cmin                = 0,
00480                      cmax                = 0,
00481                      flux                = FALSE,
00482                      edge_nan            = FALSE,
00483                      name_vec_size       = 0,
00484                      found               = 0,
00485                      suppress_extension  = FALSE,
00486                      suppress_index      = 0,
00487                      i                   = 0,
00488                      j                   = 0,
00489                      ifu_nr              = 0,
00490                      nv                  = 0;
00491 
00492     double           cpos_rej            = 0.0,
00493                      cneg_rej            = 0.0;
00494 
00495     cpl_propertylist *main_header        = NULL,
00496                      **data_header_list  = NULL,
00497                      **noise_header_list = NULL,
00498                      *tmp_header         = NULL;
00499 
00500     cpl_frame        *frame              = NULL;
00501     cpl_size         ci                  = 0;
00502     main_fits_desc   desc;
00503 
00504     enum extrapolationType extrapol_enum = NONE_CLIPPING;
00505 
00506     KMO_TRY
00507     {
00508         /* --- check input --- */
00509         KMO_TRY_ASSURE((parlist != NULL) &&
00510                        (frameset != NULL),
00511                        CPL_ERROR_NULL_INPUT,
00512                        "Not all input data is provided!");
00513 
00514         nr_frames = cpl_frameset_get_size(frameset);
00515 
00516         KMO_TRY_ASSURE(nr_frames >= 2,
00517                        CPL_ERROR_NULL_INPUT,
00518                        "At least two frames must be provided to combine!");
00519 
00520         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_combine") == 1,
00521                        CPL_ERROR_ILLEGAL_INPUT,
00522                        "Cannot identify RAW and CALIB frames!");
00523 
00524         cpl_msg_info("", "--- Parameter setup for kmo_combine -------");
00525 
00526         KMO_TRY_EXIT_IF_NULL(
00527             method = kmo_dfs_get_parameter_string(parlist,
00528                                            "kmos.kmo_combine.method"));
00529 
00530         KMO_TRY_EXIT_IF_NULL(
00531             fmethod = kmo_dfs_get_parameter_string(parlist,
00532                                            "kmos.kmo_combine.fmethod"));
00533 
00534         KMO_TRY_ASSURE((strcmp(method, "none") == 0) ||
00535                        (strcmp(method, "header") == 0) ||
00536                        (strcmp(method, "center") == 0) ||
00537                        (strcmp(method, "user") == 0),
00538                        CPL_ERROR_ILLEGAL_INPUT,
00539                        "Following shift methods are available : 'none', "
00540                        "'header', 'center' or 'user'");
00541 
00542         if (strcmp(method, "user") == 0) {
00543             filename = kmo_dfs_get_parameter_string(parlist,
00544                                                    "kmos.kmo_combine.filename");
00545             KMO_TRY_CHECK_ERROR_STATE();
00546 
00547             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00548                            CPL_ERROR_ILLEGAL_INPUT,
00549                            "path of file with shift information must be "
00550                            "provided!");
00551 
00552             KMO_TRY_EXIT_IF_ERROR(
00553                 kmo_dfs_print_parameter_help(parlist,
00554                                              "kmos.kmo_combine.filename"));
00555         }
00556 
00557         KMO_TRY_EXIT_IF_ERROR(
00558             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.method"));
00559 
00560         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00561                                                   "kmos.kmo_combine.ifus");
00562         KMO_TRY_CHECK_ERROR_STATE();
00563 
00564         name = (char*)kmo_dfs_get_parameter_string(parlist, "kmos.kmo_combine.name");
00565         KMO_TRY_CHECK_ERROR_STATE();
00566 
00567         if (strcmp(ifus_txt, "") != 0) {
00568             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00569                            CPL_ERROR_ILLEGAL_INPUT,
00570                            "name parameter must be NULL if IFU indices are "
00571                            "provided!");
00572 
00573             KMO_TRY_EXIT_IF_NULL(
00574                 ifus = kmo_identify_values(ifus_txt));
00575 
00576             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_frames,
00577                            CPL_ERROR_ILLEGAL_INPUT,
00578                            "ifus parameter must have the same number of values "
00579                            "than frames provided ) (%lld!=%d)",
00580                            cpl_vector_get_size(ifus), nr_frames);
00581         }
00582 
00583         if (strcmp(name, "") != 0) {
00584             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00585                            CPL_ERROR_ILLEGAL_INPUT,
00586                            "ifus parameter must be NULL if name is provided!");
00587         }
00588 
00589         flux = kmo_dfs_get_parameter_bool(parlist,
00590                                           "kmos.kmo_combine.flux");
00591         KMO_TRY_CHECK_ERROR_STATE();
00592         KMO_TRY_EXIT_IF_ERROR(
00593             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.flux"));
00594 
00595         KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE),
00596                        CPL_ERROR_ILLEGAL_INPUT,
00597                        "flux must be TRUE or FALSE!");
00598 
00599         edge_nan = kmo_dfs_get_parameter_bool(parlist,
00600                                           "kmos.kmo_combine.edge_nan");
00601         KMO_TRY_CHECK_ERROR_STATE();
00602         KMO_TRY_EXIT_IF_ERROR(
00603             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.edge_nan"));
00604 
00605         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
00606                        CPL_ERROR_ILLEGAL_INPUT,
00607                        "edge_nan must be TRUE or FALSE!");
00608 
00609         suppress_extension = kmo_dfs_get_parameter_bool(parlist,
00610                                           "kmos.kmo_combine.suppress_extension");
00611         KMO_TRY_CHECK_ERROR_STATE();
00612         KMO_TRY_EXIT_IF_ERROR(
00613             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.suppress_extension"));
00614 
00615         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00616                        CPL_ERROR_ILLEGAL_INPUT,
00617                        "suppress_extension must be TRUE or FALSE!");
00618 
00619         KMO_TRY_EXIT_IF_ERROR(
00620             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.ifus"));
00621 
00622         KMO_TRY_EXIT_IF_ERROR(
00623             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.name"));
00624 
00625         KMO_TRY_EXIT_IF_ERROR(
00626             kmo_combine_pars_load(parlist,
00627                                   "kmos.kmo_combine",
00628                                   &cmethod,
00629                                   &cpos_rej,
00630                                   &cneg_rej,
00631                                   &citer,
00632                                   &cmin,
00633                                   &cmax,
00634                                   FALSE));
00635 
00636         cpl_msg_info("", "-------------------------------------------");
00637 
00638         // load data and noise
00639         KMO_TRY_EXIT_IF_NULL(
00640             data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00641                                         sizeof(cpl_imagelist*)));
00642 
00643         KMO_TRY_EXIT_IF_NULL(
00644             data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00645                                           sizeof(cpl_propertylist*)));
00646 
00647         KMO_TRY_EXIT_IF_NULL(
00648             noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00649                                          sizeof(cpl_imagelist*)));
00650 
00651         KMO_TRY_EXIT_IF_NULL(
00652             noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00653                                            sizeof(cpl_propertylist*)));
00654 
00655         //
00656         // check for mapping mode
00657         //
00658         cpl_size fs_size = cpl_frameset_get_size(frameset);
00659         KMO_TRY_CHECK_ERROR_STATE();
00660 
00661         for (ci = 0; ci < fs_size; ci++) {
00662             KMO_TRY_EXIT_IF_NULL(
00663                 frame = cpl_frameset_get_position(frameset, ci));
00664 
00665             KMO_TRY_EXIT_IF_NULL(
00666                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0));
00667             if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00668                 KMO_TRY_EXIT_IF_NULL(
00669                     tmp_strc = cpl_propertylist_get_string(tmp_header, TPL_ID));
00670                 if (mapping_mode == NULL) {
00671                     if (strcmp(tmp_strc, MAPPING8) == 0)
00672                     {
00673                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00674                     }
00675                     if (strcmp(tmp_strc, MAPPING24) == 0)
00676                     {
00677                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00678                     }
00679                 } else {
00680                     if (strcmp(tmp_strc, mapping_mode) != 0)
00681                     {
00682                         cpl_msg_warning("","There are different TPL IDs present in "
00683                                            "the set of frames: %s and %s",
00684                                            tmp_strc, mapping_mode);
00685                     }
00686                 }
00687             }
00688             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00689         }
00690 
00691         if (mapping_mode != NULL) {
00692             if ((strcmp(ifus_txt, "") == 0)  && (strcmp(name, "") == 0)) {
00693                 cpl_msg_info("","**************************************************");
00694                 cpl_msg_info("","*  A map containing all IFUs will be generated!  *");
00695                 cpl_msg_info("","**************************************************");
00696                 extrapol_enum = BCS_NATURAL;
00697             } else {
00698                 cpl_msg_info("","The frames aren't combined into a map although they originate "
00699                                 "from a mapping template. But since the name- or ifu-parameter "
00700                                 "has been specified, the default behaviour is overridden.");
00701                 cpl_free(mapping_mode); mapping_mode = NULL;
00702             }
00703         }
00704 
00705         //
00706         // create name/ifu map...
00707         //
00708         KMO_TRY_EXIT_IF_NULL(
00709             name_vec = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(char*)));
00710 
00711         if ((strcmp(ifus_txt, "") == 0) &&
00712             (strcmp(name, "") == 0) &&
00713             (mapping_mode == NULL))
00714         {
00715             // all available names should be combined in one go
00716             name_vec_size = 0;
00717             for (i = 0; i < nr_frames; i++) {
00718                 KMO_TRY_EXIT_IF_NULL(
00719                     tmp_str = cpl_sprintf("%d", i));
00720                 KMO_TRY_EXIT_IF_NULL(
00721                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00722                 cpl_free(tmp_str); tmp_str = NULL;
00723 
00724                 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
00725                     tmp_str = kmo_get_name_from_ocs_ifu(frame, ifu_nr);
00726                     KMO_TRY_CHECK_ERROR_STATE();
00727                     found = 0;
00728                     for (j = 0; j < name_vec_size; j++) {
00729                         if (strcmp(name_vec[j], tmp_str) == 0) {
00730                             found = TRUE;
00731                             break;
00732                         }
00733                     }
00734                     if (!found) {
00735                         name_vec[name_vec_size++] = tmp_str;
00736                     } else {
00737                         cpl_free(tmp_str); tmp_str = NULL;
00738                     }
00739                 }
00740             }
00741         } else {
00742             // standard behavior: either ifu_nr- or name- or mapping-case
00743             name_vec_size = 1;
00744             if (mapping_mode != NULL) {
00745                 KMO_TRY_EXIT_IF_NULL(
00746                     name_vec[0] = cpl_sprintf("mapping"));
00747             } else {
00748                 if (ifus != NULL) {
00749                     KMO_TRY_EXIT_IF_NULL(
00750                         name_vec[0] = cpl_sprintf("IFU%s", ifus_txt));
00751                 } else {
00752                     KMO_TRY_EXIT_IF_NULL(
00753                         name_vec[0] = cpl_sprintf("%s", name));
00754                 }
00755             }
00756         }
00757 
00758         //
00759         // load all data (and noise if existent) cubes and store them
00760         //
00761         for (nv = 0; nv < name_vec_size; nv++){
00762             name = name_vec[nv];
00763 
00764             data_cube_counter = 0;
00765             noise_cube_counter = 0;
00766             for (i = 0; i < nr_frames; i++) {
00767                 KMO_TRY_EXIT_IF_NULL(
00768                     tmp_str = cpl_sprintf("%d", i));
00769 
00770                 KMO_TRY_EXIT_IF_NULL(
00771                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00772 
00773                 KMO_TRY_EXIT_IF_NULL(
00774                     frame_filename = cpl_frame_get_filename(frame));
00775 
00776                 kmo_init_fits_desc(&desc);
00777 
00778                 desc = kmo_identify_fits_header(frame_filename);
00779                 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00780                                               "be in KMOS-format!");
00781 
00782                 KMO_TRY_ASSURE(desc.fits_type == f3i_fits,
00783                                CPL_ERROR_ILLEGAL_INPUT,
00784                                "Frame No. %d hasn't correct data type "
00785                                "(must be of type F3I)!", i+1);
00786 
00787                 if (mapping_mode != NULL) {
00788                     // we are in mapping mode
00789                     for (j = 1; j <= KMOS_NR_IFUS; j++) {
00790                         //loop over all IFUs
00791                         if (desc.sub_desc[j-1].valid_data == TRUE) {
00792                             // load data frames
00793                             override_err_msg = TRUE;
00794                             data_cube_list[data_cube_counter] =
00795                                 kmo_dfs_load_cube(frameset, tmp_str, j, FALSE);
00796                             override_err_msg = FALSE;
00797                             if (data_cube_list[data_cube_counter] == NULL) {
00798                                 // no data found for this IFU
00799                                 cpl_error_reset();
00800                             } else {
00801                                 if (edge_nan) {
00802                                     KMO_TRY_EXIT_IF_ERROR(
00803                                         kmo_edge_nan(data_cube_list[data_cube_counter], j));
00804                                 }
00805                                 KMO_TRY_EXIT_IF_NULL(
00806                                     data_header_list[data_cube_counter] =
00807                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, FALSE));
00808                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00809                                                         "ESO PRO FRNAME",
00810                                                         frame_filename);
00811                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00812                                                         "ESO PRO IFUNR",
00813                                                         j);
00814                                 data_cube_counter++;
00815                             }
00816 
00817                             // load noise frames
00818                             override_err_msg = TRUE;
00819                             noise_cube_list[noise_cube_counter] =
00820                                 kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00821 
00822                             override_err_msg = FALSE;
00823                             if (noise_cube_list[noise_cube_counter] == NULL) {
00824                                 // no noise found for this IFU
00825                                 cpl_error_reset();
00826                             } else {
00827                                 if (edge_nan) {
00828                                     KMO_TRY_EXIT_IF_ERROR(
00829                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], j));
00830                                 }
00831                                 KMO_TRY_EXIT_IF_NULL(
00832                                     noise_header_list[noise_cube_counter] =
00833                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, TRUE));
00834                                 noise_cube_counter++;
00835                             }
00836 
00837                             // check for every iteration if number of data and noise
00838                             // frames is the same
00839                             if (noise_cube_counter > 0) {
00840                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00841                                                CPL_ERROR_ILLEGAL_INPUT,
00842                                                "Frame No. %d (%s) has no noise frame "
00843                                                "while the preceeding ones had!",
00844                                                i+1, frame_filename);
00845                             }
00846                         } // end if valid_data
00847                     }
00848                 } else {
00849                     // we are in name/ifu mode (single)
00850                     if (ifus != NULL) {
00851                         ifu_nr = cpl_vector_get(ifus, i);
00852                         KMO_TRY_CHECK_ERROR_STATE();
00853                     } else {
00854                         ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00855                         KMO_TRY_CHECK_ERROR_STATE();
00856                     }
00857 
00858                     if (ifu_nr > 0) {
00859                         index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00860                         KMO_TRY_CHECK_ERROR_STATE();
00861 
00862                         if (desc.sub_desc[index-1].valid_data == TRUE) {
00863                             // load data frames
00864                             override_err_msg = TRUE;
00865                             data_cube_list[data_cube_counter] =
00866                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, FALSE);
00867                             override_err_msg = FALSE;
00868                             if (data_cube_list[data_cube_counter] == NULL) {
00869                                 // no data found for this IFU
00870                                 cpl_error_reset();
00871                                 if (ifus != NULL) {
00872                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00873                                                     "doesn't contain IFU No. %d!", i+1,
00874                                                     frame_filename, ifu_nr);
00875                                 } else {
00876                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00877                                                     "doesn't contain IFU with object "
00878                                                     "name '%s'!", i+1,
00879                                                     frame_filename, name);
00880                                 }
00881                             } else {
00882                                 if (edge_nan) {
00883                                     KMO_TRY_EXIT_IF_ERROR(
00884                                         kmo_edge_nan(data_cube_list[data_cube_counter], ifu_nr));
00885                                 }
00886 
00887                                 KMO_TRY_EXIT_IF_NULL(
00888                                     data_header_list[data_cube_counter] =
00889                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00890                                                                 ifu_nr, FALSE));
00891                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00892                                                                "ESO PRO FRNAME",
00893                                                                frame_filename);
00894                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00895                                                             "ESO PRO IFUNR",
00896                                                             ifu_nr);
00897                                 data_cube_counter++;
00898                             }
00899 
00900                             // load noise frames
00901                             override_err_msg = TRUE;
00902                             noise_cube_list[noise_cube_counter] =
00903                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, TRUE);
00904                             override_err_msg = FALSE;
00905                             if (noise_cube_list[noise_cube_counter] == NULL) {
00906                                 // no noise found for this IFU
00907                                 cpl_error_reset();
00908                             } else {
00909                                 if (edge_nan) {
00910                                     KMO_TRY_EXIT_IF_ERROR(
00911                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], ifu_nr));
00912                                 }
00913 
00914                                 KMO_TRY_EXIT_IF_NULL(
00915                                     noise_header_list[noise_cube_counter] =
00916                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00917                                                                 ifu_nr, TRUE));
00918                                 noise_cube_counter++;
00919                             }
00920 
00921                             // check for every iteration if number of data and noise
00922                             // frames is the same
00923                             if (noise_cube_counter > 0) {
00924                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00925                                                CPL_ERROR_ILLEGAL_INPUT,
00926                                                "Frame No. %d (%s) has no noise frame "
00927                                                "while the preceeding ones had!",
00928                                                i+1, frame_filename);
00929                             }
00930                         } // end if valid_data
00931                     } // end if (ifu_nr > 0)
00932                 }
00933 
00934                 kmo_free_fits_desc(&desc);
00935                 cpl_free(tmp_str); tmp_str = NULL;
00936             } // for i = nr_frames
00937             KMO_TRY_CHECK_ERROR_STATE();
00938 
00939             //
00940             // combine data
00941             //
00942             KMO_TRY_EXIT_IF_ERROR(
00943                 kmo_priv_combine(data_cube_list,
00944                                  noise_cube_list,
00945                                  data_header_list,
00946                                  noise_header_list,
00947                                  data_cube_counter,
00948                                  noise_cube_counter,
00949                                  name,
00950                                  ifus_txt,
00951                                  method,
00952                                  "BCS",
00953                                  fmethod,
00954                                  filename,
00955                                  cmethod,
00956                                  cpos_rej,
00957                                  cneg_rej,
00958                                  citer,
00959                                  cmin,
00960                                  cmax,
00961                                  extrapol_enum,
00962                                  flux,
00963                                  &cube_combined_data,
00964                                  &cube_combined_noise));
00965 
00966             //
00967             // save data
00968             //
00969             /* save data and noise (if existing) */
00970             // --- load, update & save primary header ---
00971 
00972 
00973             if (!suppress_extension) {
00974                 // setup output category COMBINE + ESO PRO CATG
00975                 KMO_TRY_EXIT_IF_NULL(
00976                     main_header = kmo_dfs_load_primary_header(frameset, "0"));
00977                 KMO_TRY_EXIT_IF_NULL(
00978                     tmp_str = cpl_sprintf("%s_%s_%s",
00979                                           COMBINE,
00980                                           cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00981                                           name_vec[nv]));
00982                 cpl_propertylist_delete(main_header); main_header = NULL;
00983             } else {
00984                 KMO_TRY_EXIT_IF_NULL(
00985                     tmp_str = cpl_sprintf("%s_%d", COMBINE, suppress_index++));
00986             }
00987 
00988             frame = cpl_frameset_get_first(frameset);
00989             KMO_TRY_EXIT_IF_ERROR(
00990                 kmo_dfs_save_main_header(frameset, tmp_str, "", frame, NULL,
00991                                          parlist, cpl_func));
00992 
00993             if (data_header_list[0] != NULL) {
00994                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00995                     cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00996                 }
00997                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00998                     cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00999                 }
01000             }
01001             KMO_TRY_CHECK_ERROR_STATE();
01002 
01003             KMO_TRY_EXIT_IF_ERROR(
01004                 kmo_dfs_save_cube(cube_combined_data, tmp_str, "",
01005                                   data_header_list[0], 0./0.));
01006 
01007             KMO_TRY_EXIT_IF_ERROR(
01008                 kmo_dfs_save_cube(cube_combined_noise, tmp_str, "",
01009                                   noise_header_list[0], 0./0.));
01010 
01011             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01012             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01013             if (data_cube_list != NULL) {
01014                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01015                     cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
01016                 }
01017             }
01018             if (noise_cube_list != NULL) {
01019                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01020                     cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
01021                 }
01022             }
01023             if (data_header_list != NULL) {
01024                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01025                     cpl_propertylist_delete(data_header_list[i]);
01026                     data_header_list[i] = NULL;
01027                 }
01028             }
01029             if (noise_header_list != NULL) {
01030                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01031                     cpl_propertylist_delete(noise_header_list[i]);
01032                     noise_header_list[i] = NULL;
01033                 }
01034             }
01035             cpl_free(tmp_str); tmp_str = NULL;
01036         }
01037     }
01038     KMO_CATCH
01039     {
01040         KMO_CATCH_MSG();
01041         ret_val = -1;
01042     }
01043 
01044     cpl_propertylist_delete(main_header); main_header = NULL;
01045     cpl_vector_delete(ifus); ifus = NULL;
01046     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01047     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01048 
01049     if (data_cube_list != NULL) {
01050         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01051             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
01052         }
01053         cpl_free(data_cube_list); data_cube_list = NULL;
01054     }
01055 
01056     if (noise_cube_list != NULL) {
01057         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01058             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
01059         }
01060         cpl_free(noise_cube_list); noise_cube_list = NULL;
01061     }
01062 
01063     if (data_header_list != NULL) {
01064         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01065             cpl_propertylist_delete(data_header_list[i]);
01066             data_header_list[i] = NULL;
01067         }
01068         cpl_free(data_header_list); data_header_list = NULL;
01069     }
01070 
01071     if (noise_header_list != NULL) {
01072         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01073             cpl_propertylist_delete(noise_header_list[i]);
01074             noise_header_list[i] = NULL;
01075         }
01076         cpl_free(noise_header_list); noise_header_list = NULL;
01077     }
01078 
01079     if (name_vec != NULL) {
01080         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01081             cpl_free(name_vec[i]); name_vec[i] = NULL;
01082         }
01083         cpl_free(name_vec); name_vec = NULL;
01084     }
01085     cpl_free(mapping_mode);mapping_mode = NULL;
01086 
01087     return ret_val;
01088 }
01089