KMOS Pipeline Reference Manual  1.2.6
kmo_combine.c
00001 /* $Id: kmo_combine.c,v 1.32 2013-06-27 13:10:21 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-27 13:10:21 $
00024  * $Revision: 1.32 $
00025  * $Name: not supported by cvs2svn $
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 
00419 static int kmo_combine(cpl_parameterlist *parlist, cpl_frameset *frameset)
00420 {
00421     const char       *method             = NULL,
00422                      *cmethod            = NULL,
00423                      *fmethod            = NULL,
00424                      *filename           = NULL,
00425                      *frame_filename     = NULL,
00426                      *ifus_txt           = NULL,
00427                      *tmp_strc           = NULL;
00428 
00429     char             *tmp_str            = NULL,
00430                      *mapping_mode       = NULL,
00431                      *name               = NULL,
00432                      **name_vec          = NULL;
00433 
00434     cpl_imagelist    **data_cube_list    = NULL,
00435                      **noise_cube_list   = NULL,
00436                      *cube_combined_data = NULL,
00437                      *cube_combined_noise= NULL;
00438 
00439     cpl_vector       *ifus               = NULL;
00440 
00441     int              ret_val             = 0,
00442                      nr_frames           = 0,
00443                      index               = 0,
00444                      data_cube_counter   = 0,
00445                      noise_cube_counter  = 0,
00446                      citer               = 0,
00447                      cmin                = 0,
00448                      cmax                = 0,
00449                      flux                = FALSE,
00450                      edge_nan            = FALSE,
00451                      name_vec_size       = 0,
00452                      found               = 0,
00453                      suppress_extension  = FALSE,
00454                      suppress_index      = 0,
00455                      i                   = 0,
00456                      j                   = 0,
00457                      ifu_nr              = 0,
00458                      nv                  = 0;
00459 
00460     double           cpos_rej            = 0.0,
00461                      cneg_rej            = 0.0;
00462 
00463     cpl_propertylist *main_header        = NULL,
00464                      **data_header_list  = NULL,
00465                      **noise_header_list = NULL,
00466                      *tmp_header         = NULL;
00467 
00468     cpl_frame        *frame              = NULL;
00469     cpl_size         ci                  = 0;
00470     main_fits_desc   desc;
00471 
00472     enum extrapolationType extrapol_enum = NONE_CLIPPING;
00473 
00474     KMO_TRY
00475     {
00476         /* --- check input --- */
00477         KMO_TRY_ASSURE((parlist != NULL) &&
00478                        (frameset != NULL),
00479                        CPL_ERROR_NULL_INPUT,
00480                        "Not all input data is provided!");
00481 
00482         nr_frames = cpl_frameset_get_size(frameset);
00483 
00484         KMO_TRY_ASSURE(nr_frames >= 2,
00485                        CPL_ERROR_NULL_INPUT,
00486                        "At least two frames must be provided to combine!");
00487 
00488         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_combine") == 1,
00489                        CPL_ERROR_ILLEGAL_INPUT,
00490                        "Cannot identify RAW and CALIB frames!");
00491 
00492         cpl_msg_info("", "--- Parameter setup for kmo_combine -------");
00493 
00494         KMO_TRY_EXIT_IF_NULL(
00495             method = kmo_dfs_get_parameter_string(parlist,
00496                                            "kmos.kmo_combine.method"));
00497 
00498         KMO_TRY_EXIT_IF_NULL(
00499             fmethod = kmo_dfs_get_parameter_string(parlist,
00500                                            "kmos.kmo_combine.fmethod"));
00501 
00502         KMO_TRY_ASSURE((strcmp(method, "none") == 0) ||
00503                        (strcmp(method, "header") == 0) ||
00504                        (strcmp(method, "center") == 0) ||
00505                        (strcmp(method, "user") == 0),
00506                        CPL_ERROR_ILLEGAL_INPUT,
00507                        "Following shift methods are available : 'none', "
00508                        "'header', 'center' or 'user'");
00509 
00510         if (strcmp(method, "user") == 0) {
00511             filename = kmo_dfs_get_parameter_string(parlist,
00512                                                    "kmos.kmo_combine.filename");
00513             KMO_TRY_CHECK_ERROR_STATE();
00514 
00515             KMO_TRY_ASSURE(strcmp(filename, "") != 0,
00516                            CPL_ERROR_ILLEGAL_INPUT,
00517                            "path of file with shift information must be "
00518                            "provided!");
00519 
00520             KMO_TRY_EXIT_IF_ERROR(
00521                 kmo_dfs_print_parameter_help(parlist,
00522                                              "kmos.kmo_combine.filename"));
00523         }
00524 
00525         KMO_TRY_EXIT_IF_ERROR(
00526             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.method"));
00527 
00528         ifus_txt = kmo_dfs_get_parameter_string(parlist,
00529                                                   "kmos.kmo_combine.ifus");
00530         KMO_TRY_CHECK_ERROR_STATE();
00531 
00532         name = (char*)kmo_dfs_get_parameter_string(parlist, "kmos.kmo_combine.name");
00533         KMO_TRY_CHECK_ERROR_STATE();
00534 
00535         if (strcmp(ifus_txt, "") != 0) {
00536             KMO_TRY_ASSURE(strcmp(name, "") == 0,
00537                            CPL_ERROR_ILLEGAL_INPUT,
00538                            "name parameter must be NULL if IFU indices are "
00539                            "provided!");
00540 
00541             KMO_TRY_EXIT_IF_NULL(
00542                 ifus = kmo_identify_values(ifus_txt));
00543 
00544             KMO_TRY_ASSURE(cpl_vector_get_size(ifus) == nr_frames,
00545                            CPL_ERROR_ILLEGAL_INPUT,
00546                            "ifus parameter must have the same number of values "
00547                            "than frames provided ) (%lld!=%d)",
00548                            cpl_vector_get_size(ifus), nr_frames);
00549         }
00550 
00551         if (strcmp(name, "") != 0) {
00552             KMO_TRY_ASSURE(strcmp(ifus_txt, "") == 0,
00553                            CPL_ERROR_ILLEGAL_INPUT,
00554                            "ifus parameter must be NULL if name is provided!");
00555         }
00556 
00557         flux = kmo_dfs_get_parameter_bool(parlist,
00558                                           "kmos.kmo_combine.flux");
00559         KMO_TRY_CHECK_ERROR_STATE();
00560         KMO_TRY_EXIT_IF_ERROR(
00561             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.flux"));
00562 
00563         KMO_TRY_ASSURE((flux == TRUE) || (flux == FALSE),
00564                        CPL_ERROR_ILLEGAL_INPUT,
00565                        "flux must be TRUE or FALSE!");
00566 
00567         edge_nan = kmo_dfs_get_parameter_bool(parlist,
00568                                           "kmos.kmo_combine.edge_nan");
00569         KMO_TRY_CHECK_ERROR_STATE();
00570         KMO_TRY_EXIT_IF_ERROR(
00571             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.edge_nan"));
00572 
00573         KMO_TRY_ASSURE((edge_nan == TRUE) || (edge_nan == FALSE),
00574                        CPL_ERROR_ILLEGAL_INPUT,
00575                        "edge_nan must be TRUE or FALSE!");
00576 
00577         suppress_extension = kmo_dfs_get_parameter_bool(parlist,
00578                                           "kmos.kmo_combine.suppress_extension");
00579         KMO_TRY_CHECK_ERROR_STATE();
00580         KMO_TRY_EXIT_IF_ERROR(
00581             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.suppress_extension"));
00582 
00583         KMO_TRY_ASSURE((suppress_extension == TRUE) || (suppress_extension == FALSE),
00584                        CPL_ERROR_ILLEGAL_INPUT,
00585                        "suppress_extension must be TRUE or FALSE!");
00586 
00587         KMO_TRY_EXIT_IF_ERROR(
00588             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.ifus"));
00589 
00590         KMO_TRY_EXIT_IF_ERROR(
00591             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_combine.name"));
00592 
00593         KMO_TRY_EXIT_IF_ERROR(
00594             kmo_combine_pars_load(parlist,
00595                                   "kmos.kmo_combine",
00596                                   &cmethod,
00597                                   &cpos_rej,
00598                                   &cneg_rej,
00599                                   &citer,
00600                                   &cmin,
00601                                   &cmax,
00602                                   FALSE));
00603 
00604         cpl_msg_info("", "-------------------------------------------");
00605 
00606         // load data and noise
00607         KMO_TRY_EXIT_IF_NULL(
00608             data_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00609                                         sizeof(cpl_imagelist*)));
00610 
00611         KMO_TRY_EXIT_IF_NULL(
00612             data_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00613                                           sizeof(cpl_propertylist*)));
00614 
00615         KMO_TRY_EXIT_IF_NULL(
00616             noise_cube_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00617                                          sizeof(cpl_imagelist*)));
00618 
00619         KMO_TRY_EXIT_IF_NULL(
00620             noise_header_list = cpl_calloc(nr_frames*KMOS_NR_IFUS,
00621                                            sizeof(cpl_propertylist*)));
00622 
00623         //
00624         // check for mapping mode
00625         //
00626         cpl_size fs_size = cpl_frameset_get_size(frameset);
00627         KMO_TRY_CHECK_ERROR_STATE();
00628 
00629         for (ci = 0; ci < fs_size; ci++) {
00630             KMO_TRY_EXIT_IF_NULL(
00631                 frame = cpl_frameset_get_position(frameset, ci));
00632 
00633             KMO_TRY_EXIT_IF_NULL(
00634                 tmp_header = kmclipm_propertylist_load(cpl_frame_get_filename(frame), 0));
00635             if (cpl_propertylist_has(tmp_header, TPL_ID)) {
00636                 KMO_TRY_EXIT_IF_NULL(
00637                     tmp_strc = cpl_propertylist_get_string(tmp_header, TPL_ID));
00638                 if (mapping_mode == NULL) {
00639                     if (strcmp(tmp_strc, MAPPING8) == 0)
00640                     {
00641                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00642                     }
00643                     if (strcmp(tmp_strc, MAPPING24) == 0)
00644                     {
00645                         mapping_mode = cpl_sprintf("%s", tmp_strc);
00646                     }
00647                 } else {
00648                     if (strcmp(tmp_strc, mapping_mode) != 0)
00649                     {
00650                         cpl_msg_warning("","There are different TPL IDs present in "
00651                                            "the set of frames: %s and %s",
00652                                            tmp_strc, mapping_mode);
00653                     }
00654                 }
00655             }
00656             cpl_propertylist_delete(tmp_header); tmp_header = NULL;
00657         }
00658 
00659         if (mapping_mode != NULL) {
00660             if ((strcmp(ifus_txt, "") == 0)  && (strcmp(name, "") == 0)) {
00661                 cpl_msg_info("","**************************************************");
00662                 cpl_msg_info("","*  A map containing all IFUs will be generated!  *");
00663                 cpl_msg_info("","**************************************************");
00664                 extrapol_enum = BCS_NATURAL;
00665             } else {
00666                 cpl_msg_info("","The frames aren't combined into a map although they originate "
00667                                 "from a mapping template. But since the name- or ifu-parameter "
00668                                 "has been specified, the default behaviour is overridden.");
00669                 cpl_free(mapping_mode); mapping_mode = NULL;
00670             }
00671         }
00672 
00673         //
00674         // create name/ifu map...
00675         //
00676         KMO_TRY_EXIT_IF_NULL(
00677             name_vec = cpl_calloc(nr_frames*KMOS_NR_IFUS, sizeof(char*)));
00678 
00679         if ((strcmp(ifus_txt, "") == 0) &&
00680             (strcmp(name, "") == 0) &&
00681             (mapping_mode == NULL))
00682         {
00683             // all available names should be combined in one go
00684             name_vec_size = 0;
00685             for (i = 0; i < nr_frames; i++) {
00686                 KMO_TRY_EXIT_IF_NULL(
00687                     tmp_str = cpl_sprintf("%d", i));
00688                 KMO_TRY_EXIT_IF_NULL(
00689                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00690                 cpl_free(tmp_str); tmp_str = NULL;
00691 
00692                 for (ifu_nr = 1; ifu_nr <= KMOS_NR_IFUS; ifu_nr++) {
00693                     tmp_str = kmo_get_name_from_ocs_ifu(frame, ifu_nr);
00694                     KMO_TRY_CHECK_ERROR_STATE();
00695                     found = 0;
00696                     for (j = 0; j < name_vec_size; j++) {
00697                         if (strcmp(name_vec[j], tmp_str) == 0) {
00698                             found = TRUE;
00699                             break;
00700                         }
00701                     }
00702                     if (!found) {
00703                         name_vec[name_vec_size++] = tmp_str;
00704                     } else {
00705                         cpl_free(tmp_str); tmp_str = NULL;
00706                     }
00707                 }
00708             }
00709         } else {
00710             // standard behavior: either ifu_nr- or name- or mapping-case
00711             name_vec_size = 1;
00712             if (mapping_mode != NULL) {
00713                 KMO_TRY_EXIT_IF_NULL(
00714                     name_vec[0] = cpl_sprintf("mapping"));
00715             } else {
00716                 if (ifus != NULL) {
00717                     KMO_TRY_EXIT_IF_NULL(
00718                         name_vec[0] = cpl_sprintf("IFU%s", ifus_txt));
00719                 } else {
00720                     KMO_TRY_EXIT_IF_NULL(
00721                         name_vec[0] = cpl_sprintf("%s", name));
00722                 }
00723             }
00724         }
00725 
00726         //
00727         // load all data (and noise if existent) cubes and store them
00728         //
00729         for (nv = 0; nv < name_vec_size; nv++){
00730             name = name_vec[nv];
00731 
00732             data_cube_counter = 0;
00733             noise_cube_counter = 0;
00734             for (i = 0; i < nr_frames; i++) {
00735                 KMO_TRY_EXIT_IF_NULL(
00736                     tmp_str = cpl_sprintf("%d", i));
00737 
00738                 KMO_TRY_EXIT_IF_NULL(
00739                     frame = kmo_dfs_get_frame(frameset, tmp_str));
00740 
00741                 KMO_TRY_EXIT_IF_NULL(
00742                     frame_filename = cpl_frame_get_filename(frame));
00743 
00744                 kmo_init_fits_desc(&desc);
00745 
00746                 desc = kmo_identify_fits_header(frame_filename);
00747                 KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to "
00748                                               "be in KMOS-format!");
00749 
00750                 KMO_TRY_ASSURE(desc.fits_type == f3i_fits,
00751                                CPL_ERROR_ILLEGAL_INPUT,
00752                                "Frame No. %d hasn't correct data type "
00753                                "(must be of type F3I)!", i+1);
00754 
00755                 if (mapping_mode != NULL) {
00756                     // we are in mapping mode
00757                     for (j = 1; j <= KMOS_NR_IFUS; j++) {
00758                         //loop over all IFUs
00759                         if (desc.sub_desc[j-1].valid_data == TRUE) {
00760                             // load data frames
00761                             override_err_msg = TRUE;
00762                             data_cube_list[data_cube_counter] =
00763                                 kmo_dfs_load_cube(frameset, tmp_str, j, FALSE);
00764                             override_err_msg = FALSE;
00765                             if (data_cube_list[data_cube_counter] == NULL) {
00766                                 // no data found for this IFU
00767                                 cpl_error_reset();
00768                             } else {
00769                                 if (edge_nan) {
00770                                     KMO_TRY_EXIT_IF_ERROR(
00771                                         kmo_edge_nan(data_cube_list[data_cube_counter], j));
00772                                 }
00773                                 KMO_TRY_EXIT_IF_NULL(
00774                                     data_header_list[data_cube_counter] =
00775                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, FALSE));
00776                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00777                                                         "ESO PRO FRNAME",
00778                                                         frame_filename);
00779                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00780                                                         "ESO PRO IFUNR",
00781                                                         j);
00782                                 data_cube_counter++;
00783                             }
00784 
00785                             // load noise frames
00786                             override_err_msg = TRUE;
00787                             noise_cube_list[noise_cube_counter] =
00788                                 kmo_dfs_load_cube(frameset, tmp_str, j, TRUE);
00789 
00790                             override_err_msg = FALSE;
00791                             if (noise_cube_list[noise_cube_counter] == NULL) {
00792                                 // no noise found for this IFU
00793                                 cpl_error_reset();
00794                             } else {
00795                                 if (edge_nan) {
00796                                     KMO_TRY_EXIT_IF_ERROR(
00797                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], j));
00798                                 }
00799                                 KMO_TRY_EXIT_IF_NULL(
00800                                     noise_header_list[noise_cube_counter] =
00801                                         kmo_dfs_load_sub_header(frameset, tmp_str, j, TRUE));
00802                                 noise_cube_counter++;
00803                             }
00804 
00805                             // check for every iteration if number of data and noise
00806                             // frames is the same
00807                             if (noise_cube_counter > 0) {
00808                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00809                                                CPL_ERROR_ILLEGAL_INPUT,
00810                                                "Frame No. %d (%s) has no noise frame "
00811                                                "while the preceeding ones had!",
00812                                                i+1, frame_filename);
00813                             }
00814                         } // end if valid_data
00815                     }
00816                 } else {
00817                     // we are in name/ifu mode (single)
00818                     if (ifus != NULL) {
00819                         ifu_nr = cpl_vector_get(ifus, i);
00820                         KMO_TRY_CHECK_ERROR_STATE();
00821                     } else {
00822                         ifu_nr = kmo_get_index_from_ocs_name(frame, name);
00823                         KMO_TRY_CHECK_ERROR_STATE();
00824                     }
00825 
00826                     if (ifu_nr > 0) {
00827                         index = kmo_identify_index(frame_filename, ifu_nr , FALSE);
00828                         KMO_TRY_CHECK_ERROR_STATE();
00829 
00830                         if (desc.sub_desc[index-1].valid_data == TRUE) {
00831                             // load data frames
00832                             override_err_msg = TRUE;
00833                             data_cube_list[data_cube_counter] =
00834                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, FALSE);
00835                             override_err_msg = FALSE;
00836                             if (data_cube_list[data_cube_counter] == NULL) {
00837                                 // no data found for this IFU
00838                                 cpl_error_reset();
00839                                 if (ifus != NULL) {
00840                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00841                                                     "doesn't contain IFU No. %d!", i+1,
00842                                                     frame_filename, ifu_nr);
00843                                 } else {
00844                                     cpl_msg_warning(cpl_func, "Frame No. %d (%s) "
00845                                                     "doesn't contain IFU with object "
00846                                                     "name '%s'!", i+1,
00847                                                     frame_filename, name);
00848                                 }
00849                             } else {
00850                                 if (edge_nan) {
00851                                     KMO_TRY_EXIT_IF_ERROR(
00852                                         kmo_edge_nan(data_cube_list[data_cube_counter], ifu_nr));
00853                                 }
00854 
00855                                 KMO_TRY_EXIT_IF_NULL(
00856                                     data_header_list[data_cube_counter] =
00857                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00858                                                                 ifu_nr, FALSE));
00859                                 cpl_propertylist_update_string(data_header_list[data_cube_counter],
00860                                                                "ESO PRO FRNAME",
00861                                                                frame_filename);
00862                                 cpl_propertylist_update_int(data_header_list[data_cube_counter],
00863                                                             "ESO PRO IFUNR",
00864                                                             ifu_nr);
00865                                 data_cube_counter++;
00866                             }
00867 
00868                             // load noise frames
00869                             override_err_msg = TRUE;
00870                             noise_cube_list[noise_cube_counter] =
00871                                 kmo_dfs_load_cube(frameset, tmp_str, ifu_nr, TRUE);
00872                             override_err_msg = FALSE;
00873                             if (noise_cube_list[noise_cube_counter] == NULL) {
00874                                 // no noise found for this IFU
00875                                 cpl_error_reset();
00876                             } else {
00877                                 if (edge_nan) {
00878                                     KMO_TRY_EXIT_IF_ERROR(
00879                                         kmo_edge_nan(noise_cube_list[noise_cube_counter], ifu_nr));
00880                                 }
00881 
00882                                 KMO_TRY_EXIT_IF_NULL(
00883                                     noise_header_list[noise_cube_counter] =
00884                                         kmo_dfs_load_sub_header(frameset, tmp_str,
00885                                                                 ifu_nr, TRUE));
00886                                 noise_cube_counter++;
00887                             }
00888 
00889                             // check for every iteration if number of data and noise
00890                             // frames is the same
00891                             if (noise_cube_counter > 0) {
00892                                 KMO_TRY_ASSURE(data_cube_counter == noise_cube_counter,
00893                                                CPL_ERROR_ILLEGAL_INPUT,
00894                                                "Frame No. %d (%s) has no noise frame "
00895                                                "while the preceeding ones had!",
00896                                                i+1, frame_filename);
00897                             }
00898                         } // end if valid_data
00899                     } // end if (ifu_nr > 0)
00900                 }
00901 
00902                 kmo_free_fits_desc(&desc);
00903                 cpl_free(tmp_str); tmp_str = NULL;
00904             } // for i = nr_frames
00905             KMO_TRY_CHECK_ERROR_STATE();
00906 
00907             //
00908             // combine data
00909             //
00910             KMO_TRY_EXIT_IF_ERROR(
00911                 kmo_priv_combine(data_cube_list,
00912                                  noise_cube_list,
00913                                  data_header_list,
00914                                  noise_header_list,
00915                                  data_cube_counter,
00916                                  noise_cube_counter,
00917                                  name,
00918                                  ifus_txt,
00919                                  method,
00920                                  "BCS",
00921                                  fmethod,
00922                                  filename,
00923                                  cmethod,
00924                                  cpos_rej,
00925                                  cneg_rej,
00926                                  citer,
00927                                  cmin,
00928                                  cmax,
00929                                  extrapol_enum,
00930                                  flux,
00931                                  &cube_combined_data,
00932                                  &cube_combined_noise));
00933 
00934             //
00935             // save data
00936             //
00937             /* save data and noise (if existing) */
00938             // --- load, update & save primary header ---
00939 
00940 
00941             if (!suppress_extension) {
00942                 // setup output category COMBINE + ESO PRO CATG
00943                 KMO_TRY_EXIT_IF_NULL(
00944                     main_header = kmo_dfs_load_primary_header(frameset, "0"));
00945                 KMO_TRY_EXIT_IF_NULL(
00946                     tmp_str = cpl_sprintf("%s_%s_%s",
00947                                           COMBINE,
00948                                           cpl_propertylist_get_string(main_header, CPL_DFS_PRO_CATG),
00949                                           name_vec[nv]));
00950                 cpl_propertylist_delete(main_header); main_header = NULL;
00951             } else {
00952                 KMO_TRY_EXIT_IF_NULL(
00953                     tmp_str = cpl_sprintf("%s_%d", COMBINE, suppress_index++));
00954             }
00955 
00956             frame = cpl_frameset_get_first(frameset);
00957             KMO_TRY_EXIT_IF_ERROR(
00958                 kmo_dfs_save_main_header(frameset, tmp_str, "", frame, NULL,
00959                                          parlist, cpl_func));
00960 
00961             if (data_header_list[0] != NULL) {
00962                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO FRNAME")) {
00963                     cpl_propertylist_erase(data_header_list[0], "ESO PRO FRNAME");
00964                 }
00965                 if (cpl_propertylist_has(data_header_list[0], "ESO PRO IFUNR")) {
00966                     cpl_propertylist_erase(data_header_list[0], "ESO PRO IFUNR");
00967                 }
00968             }
00969             KMO_TRY_CHECK_ERROR_STATE();
00970 
00971             KMO_TRY_EXIT_IF_ERROR(
00972                 kmo_dfs_save_cube(cube_combined_data, tmp_str, "",
00973                                   data_header_list[0], 0./0.));
00974 
00975             KMO_TRY_EXIT_IF_ERROR(
00976                 kmo_dfs_save_cube(cube_combined_noise, tmp_str, "",
00977                                   noise_header_list[0], 0./0.));
00978 
00979             cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
00980             cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
00981             if (data_cube_list != NULL) {
00982                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00983                     cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
00984                 }
00985             }
00986             if (noise_cube_list != NULL) {
00987                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00988                     cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
00989                 }
00990             }
00991             if (data_header_list != NULL) {
00992                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00993                     cpl_propertylist_delete(data_header_list[i]);
00994                     data_header_list[i] = NULL;
00995                 }
00996             }
00997             if (noise_header_list != NULL) {
00998                 for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
00999                     cpl_propertylist_delete(noise_header_list[i]);
01000                     noise_header_list[i] = NULL;
01001                 }
01002             }
01003             cpl_free(tmp_str); tmp_str = NULL;
01004         }
01005     }
01006     KMO_CATCH
01007     {
01008         KMO_CATCH_MSG();
01009         ret_val = -1;
01010     }
01011 
01012     cpl_propertylist_delete(main_header); main_header = NULL;
01013     cpl_vector_delete(ifus); ifus = NULL;
01014     cpl_imagelist_delete(cube_combined_data); cube_combined_data = NULL;
01015     cpl_imagelist_delete(cube_combined_noise); cube_combined_noise = NULL;
01016 
01017     if (data_cube_list != NULL) {
01018         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01019             cpl_imagelist_delete(data_cube_list[i]); data_cube_list[i] = NULL;
01020         }
01021         cpl_free(data_cube_list); data_cube_list = NULL;
01022     }
01023 
01024     if (noise_cube_list != NULL) {
01025         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01026             cpl_imagelist_delete(noise_cube_list[i]); noise_cube_list[i] = NULL;
01027         }
01028         cpl_free(noise_cube_list); noise_cube_list = NULL;
01029     }
01030 
01031     if (data_header_list != NULL) {
01032         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01033             cpl_propertylist_delete(data_header_list[i]);
01034             data_header_list[i] = NULL;
01035         }
01036         cpl_free(data_header_list); data_header_list = NULL;
01037     }
01038 
01039     if (noise_header_list != NULL) {
01040         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01041             cpl_propertylist_delete(noise_header_list[i]);
01042             noise_header_list[i] = NULL;
01043         }
01044         cpl_free(noise_header_list); noise_header_list = NULL;
01045     }
01046 
01047     if (name_vec != NULL) {
01048         for (i = 0; i < nr_frames*KMOS_NR_IFUS; i++) {
01049             cpl_free(name_vec[i]); name_vec[i] = NULL;
01050         }
01051         cpl_free(name_vec); name_vec = NULL;
01052     }
01053     cpl_free(mapping_mode);mapping_mode = NULL;
01054 
01055     return ret_val;
01056 }
01057