KMOS Pipeline Reference Manual  1.1.4
kmo_extract_spec.c
00001 /* $Id: kmo_extract_spec.c,v 1.13 2013/05/23 10:19:14 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/05/23 10:19:14 $
00024  * $Revision: 1.13 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033  *                              Includes
00034  *----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 #include <math.h>
00038 
00039 #include <cpl.h>
00040 
00041 #include "kmo_utils.h"
00042 #include "kmo_dfs.h"
00043 #include "kmo_error.h"
00044 #include "kmo_priv_extract_spec.h"
00045 #include "kmo_priv_functions.h"
00046 #include "kmo_cpl_extensions.h"
00047 #include "kmo_constants.h"
00048 #include "kmo_priv_fit_profile.h"
00049 #include "kmo_debug.h"
00050 
00051 
00052 /*-----------------------------------------------------------------------------
00053  *                          Functions prototypes
00054  *----------------------------------------------------------------------------*/
00055 
00056 static int kmo_extract_spec_create(cpl_plugin *);
00057 static int kmo_extract_spec_exec(cpl_plugin *);
00058 static int kmo_extract_spec_destroy(cpl_plugin *);
00059 static int kmo_extract_spec(cpl_parameterlist *, cpl_frameset *);
00060 
00061 /*-----------------------------------------------------------------------------
00062  *                          Static variables
00063  *----------------------------------------------------------------------------*/
00064 
00065 static char kmo_extract_spec_description[] =
00066 "This recipe extracts a spectrum from a datacube. The datacube must be in\n"
00067 "F3I KMOS FITS format (either with or without noise). The output will be a\n"
00068 "similarly formatted F1I KMOS FITS file.\n"
00069 "\n"
00070 "BASIC PARAMETERS:\n"
00071 "-----------------\n"
00072 "--mask_method\n"
00073 "There are several ways to define the region to consider for spectrum calculation:\n"
00074 "  * 'integrated'' (default)\n"
00075 "  A circular mask with defined centre and radius is created (--centre and\n"
00076 "  --radius have to be defined). This mask is applied to all extensions.\n"
00077 "\n"
00078 "  * 'mask'\n"
00079 "  An arbitrary mask can be provided (for example the mask created by kmo_sky_mask\n"
00080 "  can be used). The mask must be in F2I KMOS FITS format, mustn't contain noise\n"
00081 "  and must have as many extensions as the input cube. The mask can be binary as\n"
00082 "  well as it can contain float values, so a weighted mask is also possible.\n"
00083 "  (0: pixels is ignored, 1: pixel is included) The mask must be of the same size\n"
00084 "  that the input datacube.\n"
00085 "\n"
00086 "  * 'optimal'\n"
00087 "  The mask is created automatically by fitting a normalised profile (using\n"
00088 "  kmo_fit_profile) to the image of the datacube (using kmo_make_image the data-\n"
00089 "  cube is summed up in spectral direction according to the specified --cmethod).\n"
00090 "  This profile is then used as mask input. When --save_mask is set to true the\n"
00091 "  mask is saved on disk. The remaining parameters not described here apply to\n"
00092 "  the fitting of the profile.\n"
00093 "\n"
00094 "If the spectra of several objects in a IFU should be extracted, --mask_method=\n"
00095 "'mask' is recommended. With several calls to kmo_extract_spec using different\n"
00096 "masks all spectra can be extracted.\n"
00097 "\n"
00098 "ADVANCED PARAMETERS\n"
00099 "-------------------\n"
00100 "--centre\n"
00101 "--radius\n"
00102 "see --mask_method = 'integrated'\n"
00103 "\n"
00104 "--save_mask\n"
00105 "see --mask_method = 'optimal'\n"
00106 "\n"
00107 "--cmethod\n"
00108 "Applies only if –mask_method = 'integral'\n"
00109 "Following methods of frame combination are available:\n"
00110 "   * 'ksigma' (Default)\n"
00111 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00112 "   are examined. If they deviate significantly, they will be rejected according\n"
00113 "   to the conditions:\n"
00114 "       val > mean + stdev * cpos_rej\n"
00115 "   and\n"
00116 "       val < mean - stdev * cneg_rej\n"
00117 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00118 "   parameters. In the first iteration median and percentile level are used.\n"
00119 "\n"
00120 "   * 'median'\n"
00121 "   At each pixel position the median is calculated.\n"
00122 "\n"
00123 "   * 'average'\n"
00124 "   At each pixel position the average is calculated.\n"
00125 "\n"
00126 "   * 'sum'\n"
00127 "   At each pixel position the sum is calculated.\n"
00128 "\n"
00129 "   * 'min_max'\n"
00130 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00131 "   --cmax and --cmin apply to this method.\n"
00132 "\n"
00133 "--cpos_rej\n"
00134 "--cneg_rej\n"
00135 "--citer\n"
00136 "see --cmethod='ksigma'\n"
00137 "\n"
00138 "--cmax\n"
00139 "--cmin\n"
00140 "see --cmethod='min_max'\n"
00141 
00142 "\n"
00143 "-------------------------------------------------------------------------------\n"
00144 "  Input files:\n"
00145 "\n"
00146 "   DO                    KMOS                                                  \n"
00147 "   category              Type   Explanation                    Required #Frames\n"
00148 "   --------              -----  -----------                    -------- -------\n"
00149 "   <none or any>         F3I    The datacubes                     Y        1   \n"
00150 "   EXTRACT_MASK          F2I    The mask                          N       0,1  \n"
00151 "\n"
00152 "  Output files:\n"
00153 "\n"
00154 "   DO                    KMOS\n"
00155 "   category              Type   Explanation\n"
00156 "   --------              -----  -----------\n"
00157 "   EXTRACT_SPEC          F3I    Extracted spectrum                             \n"
00158 "   EXTRACT_SPEC_MASK     F2I    (optional, if --save_mask=true and             \n"
00159 "                                --mask_method='optimal': The calculated mask)  \n"
00160 "-------------------------------------------------------------------------------\n"
00161 "\n";
00162 
00163 /*-----------------------------------------------------------------------------
00164  *                              Functions code
00165  *----------------------------------------------------------------------------*/
00166 
00183 int cpl_plugin_get_info(cpl_pluginlist *list)
00184 {
00185     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00186     cpl_plugin *plugin = &recipe->interface;
00187 
00188     cpl_plugin_init(plugin,
00189                         CPL_PLUGIN_API,
00190                         KMOS_BINARY_VERSION,
00191                         CPL_PLUGIN_TYPE_RECIPE,
00192                         "kmo_extract_spec",
00193                         "Extract a spectrum from a cube.",
00194                         kmo_extract_spec_description,
00195                         "Alex Agudo Berbel",
00196                         "kmos-spark@mpe.mpg.de",
00197                         kmos_get_license(),
00198                         kmo_extract_spec_create,
00199                         kmo_extract_spec_exec,
00200                         kmo_extract_spec_destroy);
00201 
00202     cpl_pluginlist_append(list, plugin);
00203 
00204     return 0;
00205 }
00206 
00214 static int kmo_extract_spec_create(cpl_plugin *plugin)
00215 {
00216     cpl_recipe *recipe;
00217     cpl_parameter *p;
00218 
00219     /* Check that the plugin is part of a valid recipe */
00220     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00221         recipe = (cpl_recipe *)plugin;
00222     else
00223         return -1;
00224 
00225     /* Create the parameters list in the cpl_recipe object */
00226     recipe->parameters = cpl_parameterlist_new();
00227 
00228     /* Fill the parameters list */
00229     /* --mask_method */
00230     p = cpl_parameter_new_value("kmos.kmo_extract_spec.mask_method",
00231                                 CPL_TYPE_STRING,
00232                                 "Either apply 'mask', 'integrated' or "
00233                                     "'optimal' masking method.",
00234                                 "kmos.kmo_extract_spec",
00235                                 "integrated");
00236     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "mask_method");
00237     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00238     cpl_parameterlist_append(recipe->parameters, p);
00239 
00240     /* --centre */
00241     p = cpl_parameter_new_value("kmos.kmo_extract_spec.centre",
00242                                 CPL_TYPE_STRING,
00243                                 "The centre of the circular mask (pixel).",
00244                                 "kmos.kmo_extract_spec",
00245                                 "7.5,7.5");
00246     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "centre");
00247     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00248     cpl_parameterlist_append(recipe->parameters, p);
00249 
00250     /* --radius */
00251     p = cpl_parameter_new_value("kmos.kmo_extract_spec.radius",
00252                                 CPL_TYPE_DOUBLE,
00253                                 "The radius of the circular mask (pixel).",
00254                                 "kmos.kmo_extract_spec",
00255                                 3.0);
00256     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "radius");
00257     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00258     cpl_parameterlist_append(recipe->parameters, p);
00259 
00260     /* --save_mask */
00261     p = cpl_parameter_new_value("kmos.kmo_extract_spec.save_mask",
00262                                 CPL_TYPE_BOOL,
00263                                 "True if the calculated mask should be saved.",
00264                                 "kmos.kmo_extract_spec",
00265                                 FALSE);
00266     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "save_mask");
00267     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00268     cpl_parameterlist_append(recipe->parameters, p);
00269 
00270     return kmo_combine_pars_create(recipe->parameters,
00271                                    "kmos.kmo_extract_spec",
00272                                    DEF_REJ_METHOD,
00273                                    FALSE);
00274 }
00275 
00281 static int kmo_extract_spec_exec(cpl_plugin *plugin)
00282 {
00283     cpl_recipe  *recipe;
00284 
00285     /* Get the recipe out of the plugin */
00286     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00287         recipe = (cpl_recipe *)plugin;
00288     else return -1;
00289 
00290     return kmo_extract_spec(recipe->parameters, recipe->frames);
00291 }
00292 
00298 static int kmo_extract_spec_destroy(cpl_plugin *plugin)
00299 {
00300     cpl_recipe *recipe;
00301 
00302     /* Get the recipe out of the plugin */
00303     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00304         recipe = (cpl_recipe *)plugin;
00305     else return -1 ;
00306 
00307     cpl_parameterlist_delete(recipe->parameters);
00308     return 0 ;
00309 }
00310 
00325 static int kmo_extract_spec(cpl_parameterlist *parlist, cpl_frameset *frameset)
00326 {
00327     cpl_imagelist    *data_in            = NULL,
00328                      *noise_in           = NULL;
00329 
00330     cpl_image        *mask               = NULL,
00331                      *made_data_img      = NULL;
00332 
00333     cpl_vector       *spec_data_out      = NULL,
00334                      *spec_noise_out     = NULL,
00335                      *centre             = NULL,
00336                      *fit_par            = NULL;
00337 
00338     int              ret_val             = 0,
00339                      nr_devices          = 0,
00340                      i                   = 0,
00341                      valid_ifu           = FALSE,
00342                      citer               = 0,
00343                      cmin                = 0,
00344                      cmax                = 0,
00345                      x                   = 0,
00346                      y                   = 0,
00347                      save_mask           = FALSE,
00348                      devnr1              = 0,
00349                      devnr2              = 0,
00350                      index_data          = 0,
00351                      index_noise          = 0;
00352 
00353     cpl_propertylist *sub_header_data    = NULL,
00354                      *sub_header_noise   = NULL,
00355                      *sub_header_mask    = NULL,
00356                      *fit_pl             = NULL;
00357 
00358     const char       *mask_method        = NULL,
00359                      *cmethod            = NULL,
00360                      *centre_txt         = NULL;
00361 
00362     double           cpos_rej            = 0.0,
00363                      cneg_rej            = 0.0,
00364                      radius              = 0.0,
00365                      r                   = 0.0,
00366                      x_lo                = 0.0,
00367                      y_lo                = 0.0,
00368                      x_hi                = 0.0,
00369                      y_hi                = 0.0,
00370                      cen_x               = 0.0,
00371                      cen_y               = 0.0;
00372 
00373     float            *pmask              = NULL;
00374 
00375     main_fits_desc   desc1,
00376                      desc2;
00377 
00378     cpl_frame        *op1_frame          = NULL,
00379                      *op2_frame          = NULL;
00380 
00381     char             do_mode1[256],
00382                      do_mode2[256];
00383 
00384     KMO_TRY
00385     {
00386         kmo_init_fits_desc(&desc1);
00387         kmo_init_fits_desc(&desc2);
00388 
00389         /* --- check input --- */
00390         KMO_TRY_ASSURE((parlist != NULL) &&
00391                        (frameset != NULL),
00392                        CPL_ERROR_NULL_INPUT,
00393                        "Not all input data is provided!");
00394 
00395         KMO_TRY_ASSURE((cpl_frameset_get_size(frameset) == 1) ||
00396                        ((cpl_frameset_get_size(frameset) == 2)),
00397                        CPL_ERROR_NULL_INPUT,
00398                        "Either one data cube or a datacube and a mask"
00399                        "must be provided!");
00400 
00401         if (cpl_frameset_get_size(frameset) == 1) {
00402             strcpy(do_mode1, "0");
00403             strcpy(do_mode2, "");
00404         } else {
00405             if (cpl_frameset_count_tags(frameset, EXTRACT_MASK) == 1) {
00406                 strcpy(do_mode1, "0");
00407                 strcpy(do_mode2, EXTRACT_MASK);
00408             } else {
00409                 strcpy(do_mode1, "0");
00410                 strcpy(do_mode2, "1");
00411             }
00412             KMO_TRY_EXIT_IF_NULL(
00413                 op2_frame = kmo_dfs_get_frame(frameset, do_mode2));
00414         }
00415         KMO_TRY_EXIT_IF_NULL(
00416             op1_frame = kmo_dfs_get_frame(frameset, do_mode1));
00417 
00418         desc1 = kmo_identify_fits_header(
00419                     cpl_frame_get_filename(op1_frame));
00420         KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem to be "
00421                                       "in KMOS-format!");
00422 
00423         KMO_TRY_ASSURE(desc1.fits_type == f3i_fits,
00424                CPL_ERROR_ILLEGAL_INPUT,
00425                "The input data hasn't the correct data type "
00426                "(KMOSTYPE must be F3I)!");
00427 
00428         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_extract_spec") == 1,
00429                        CPL_ERROR_ILLEGAL_INPUT,
00430                        "Cannot identify RAW and CALIB frames!");
00431 
00432         cpl_msg_info("", "--- Parameter setup for kmo_extract_spec ---");
00433 
00434         KMO_TRY_EXIT_IF_NULL(
00435             mask_method = kmo_dfs_get_parameter_string(parlist,
00436                                           "kmos.kmo_extract_spec.mask_method"));
00437 
00438         KMO_TRY_EXIT_IF_ERROR(
00439             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_extract_spec.mask_method"));
00440 
00441         if (strcmp(mask_method, "integrated") == 0) {
00442             KMO_TRY_EXIT_IF_NULL(
00443                 centre_txt = kmo_dfs_get_parameter_string(parlist,
00444                                             "kmos.kmo_extract_spec.centre"));
00445             KMO_TRY_EXIT_IF_ERROR(
00446                 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_extract_spec.centre"));
00447 
00448             centre = kmo_identify_ranges(centre_txt);
00449             KMO_TRY_CHECK_ERROR_STATE();
00450 
00451             KMO_TRY_ASSURE(cpl_vector_get_size(centre) == 2,
00452                            CPL_ERROR_ILLEGAL_INPUT,
00453                          "centre must have exactly 2 values like \"2.0:3.1\"!");
00454 
00455             cen_x = cpl_vector_get(centre, 0);
00456             cen_y = cpl_vector_get(centre, 1);
00457 
00458             KMO_TRY_ASSURE((cen_x >= 0.0) &&
00459                            (cen_y >= 0.0),
00460                            CPL_ERROR_ILLEGAL_INPUT,
00461                            "centre must be greater than 0.0!");
00462 
00463             radius = kmo_dfs_get_parameter_double(parlist,
00464                                             "kmos.kmo_extract_spec.radius");
00465             KMO_TRY_CHECK_ERROR_STATE();
00466             KMO_TRY_EXIT_IF_ERROR(
00467                 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_extract_spec.radius"));
00468 
00469             KMO_TRY_ASSURE(radius >= 0.0,
00470                            CPL_ERROR_ILLEGAL_INPUT,
00471                            "radius must be greater than 0.0!");
00472 
00473         } else if (strcmp(mask_method, "mask") == 0) {
00474             /* load descriptor of second operand */
00475             desc2 = kmo_identify_fits_header(
00476                         cpl_frame_get_filename(op2_frame));
00477             KMO_TRY_CHECK_ERROR_STATE_MSG("Mask doesn't seem to be "
00478                                           "in KMOS-format!");
00479 
00480             KMO_TRY_ASSURE(desc2.fits_type == f2i_fits,
00481                            CPL_ERROR_ILLEGAL_INPUT,
00482                            "Mask hasn't correct data type "
00483                            "(KMOSTYPE must be F2I)!");
00484 
00485             KMO_TRY_ASSURE(desc2.ex_noise == FALSE,
00486                            CPL_ERROR_ILLEGAL_INPUT,
00487                            "Mask must not contain noise extensions!");
00488 
00489             KMO_TRY_ASSURE(
00490                 ((desc1.ex_noise == TRUE) &&
00491                  (desc1.nr_ext / 2 == desc2.nr_ext)) ||
00492                 ((desc1.ex_noise == FALSE) &&
00493                  (desc1.nr_ext == desc2.nr_ext)),
00494                         CPL_ERROR_ILLEGAL_INPUT,
00495                         "Cube and mask haven't same number of extensions!");
00496 
00497             KMO_TRY_ASSURE((desc1.naxis1 == desc2.naxis1) &&
00498                            (desc1.naxis2 == desc2.naxis2),
00499                            CPL_ERROR_ILLEGAL_INPUT,
00500                            "Cube and mask haven't same dimensions in x and y!");
00501 
00502         } else if (strcmp(mask_method, "optimal") == 0) {
00503             KMO_TRY_EXIT_IF_ERROR(
00504                 kmo_combine_pars_load(parlist,
00505                                       "kmos.kmo_extract_spec",
00506                                       &cmethod,
00507                                       &cpos_rej,
00508                                       &cneg_rej,
00509                                       &citer,
00510                                       &cmin,
00511                                       &cmax,
00512                                       FALSE));
00513 
00514             save_mask = kmo_dfs_get_parameter_bool(parlist,
00515                                             "kmos.kmo_extract_spec.save_mask");
00516             KMO_TRY_CHECK_ERROR_STATE();
00517             KMO_TRY_EXIT_IF_ERROR(
00518                 kmo_dfs_print_parameter_help(parlist, "kmos.kmo_extract_spec.save_mask"));
00519 
00520         } else {
00521             KMO_TRY_ERROR_SET_MSG(CPL_ERROR_ILLEGAL_INPUT,
00522                                          "Wrong mask method!");
00523         }
00524 
00525         cpl_msg_info(cpl_func, "-------------------------------------------");
00526 
00527         /* --- load, update & save primary header --- */
00528         KMO_TRY_EXIT_IF_ERROR(
00529             kmo_dfs_save_main_header(frameset, EXTRACT_SPEC, "", op1_frame,
00530                                      NULL, parlist, cpl_func));
00531 
00532         if (save_mask) {
00533             KMO_TRY_EXIT_IF_ERROR(
00534                 kmo_dfs_save_main_header(frameset, EXTRACT_SPEC_MASK, "", op1_frame,
00535                                          NULL, parlist, cpl_func));
00536         }
00537 
00538         /* --- load data --- */
00539         if (desc1.ex_noise == TRUE) {
00540             nr_devices = desc1.nr_ext / 2;
00541         } else {
00542             nr_devices = desc1.nr_ext;
00543         }
00544 
00545         // create mask for integrated-method just once here
00546         // and not in the for-loop
00547         if (strcmp(mask_method, "integrated") == 0) {
00548             KMO_TRY_EXIT_IF_NULL(
00549                 mask = cpl_image_new(desc1.naxis1, desc1.naxis2,
00550                                      CPL_TYPE_FLOAT));
00551 
00552             KMO_TRY_EXIT_IF_ERROR(
00553                 kmo_image_fill(mask,0.0));
00554 
00555             KMO_TRY_EXIT_IF_NULL(
00556                 pmask = cpl_image_get_data_float(mask));
00557 
00558             /* draw circle */
00559             x_lo = floor(cen_x - radius);
00560             if (x_lo < 0) {
00561                 x_lo = 0;
00562             }
00563 
00564             y_lo = floor(cen_y - radius);
00565             if (y_lo < 0) {
00566                 y_lo = 0;
00567             }
00568 
00569             x_hi = ceil(cen_x + radius);
00570             if (x_hi > desc1.naxis1) {
00571                 x_hi = desc1.naxis1;
00572             }
00573 
00574             y_hi = ceil(cen_y + radius);
00575             if (y_hi > desc1.naxis2) {
00576                 y_hi = desc1.naxis2;
00577             }
00578 
00579             for (x = x_lo; x < x_hi; x++) {
00580                 for (y = y_lo; y < y_hi; y++) {
00581                     r = sqrt(pow(x - cen_x,2) + pow(y - cen_y,2));
00582                     if (r <= radius) {
00583                         pmask[x + y * desc1.naxis1] = 1.0;
00584                     }
00585                 }
00586             }            
00587         }
00588 
00589         for (i = 1; i <= nr_devices; i++) {
00590             if (desc1.ex_noise == FALSE) {
00591                 devnr1 = desc1.sub_desc[i - 1].device_nr;
00592             } else {
00593                 devnr1 = desc1.sub_desc[2 * i - 1].device_nr;
00594             }
00595             // mask doesn't contain any noise extensions
00596             if (strcmp(mask_method, "mask") == 0) {
00597                 devnr2 = desc2.sub_desc[i - 1].device_nr;
00598             }
00599 
00600             if (desc1.ex_badpix == FALSE) {
00601                 index_data = kmo_identify_index_desc(desc1, devnr1, FALSE);
00602             } else {
00603                 index_data = kmo_identify_index_desc(desc1, devnr1, 2);
00604             }
00605             KMO_TRY_CHECK_ERROR_STATE();
00606 
00607             if (desc1.ex_noise) {
00608                 index_noise = kmo_identify_index_desc(desc1, devnr1, TRUE);
00609             }
00610             KMO_TRY_CHECK_ERROR_STATE();
00611 
00612             KMO_TRY_EXIT_IF_NULL(
00613                 sub_header_data = kmo_dfs_load_sub_header(frameset, do_mode1,
00614                                                           devnr1, FALSE));
00615 
00616             // check if IFU is valid
00617             valid_ifu = FALSE;
00618             if (desc1.sub_desc[index_data-1].valid_data == TRUE) {
00619                 if ((strcmp(mask_method, "mask") != 0) ||
00620                     ((strcmp(mask_method, "mask") == 0) &&
00621                     (desc2.sub_desc[i - 1].valid_data == TRUE))
00622                    )
00623                 {
00624                     valid_ifu = TRUE;
00625                 }
00626             }
00627 
00628             if (desc1.ex_noise) {
00629                 KMO_TRY_EXIT_IF_NULL(
00630                     sub_header_noise = kmo_dfs_load_sub_header(frameset,
00631                                                                do_mode1,
00632                                                                devnr1, TRUE));
00633             }
00634 
00635             if (valid_ifu) {
00636                 // load data
00637                 KMO_TRY_EXIT_IF_NULL(
00638                     data_in = kmo_dfs_load_cube(frameset, do_mode1, devnr1, FALSE));
00639 
00640                 // load noise, if existing
00641                 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) {
00642                     KMO_TRY_EXIT_IF_NULL(
00643                         noise_in = kmo_dfs_load_cube(frameset, do_mode1, devnr1, TRUE));
00644                 }
00645 
00646                 // create or load mask (for integrated-method already
00647                 // done outside the for-loop)
00648                 if (strcmp(mask_method, "mask") == 0) {
00649                     KMO_TRY_EXIT_IF_NULL(
00650                         mask = kmo_dfs_load_image(frameset, do_mode2,
00651                                                   devnr2, FALSE, FALSE, NULL));
00652                 } else if (strcmp(mask_method, "optimal") == 0) {
00653                     KMO_TRY_EXIT_IF_ERROR(
00654                         kmclipm_make_image(data_in, NULL,
00655                                        &made_data_img, NULL,
00656                                        NULL,
00657                                        cmethod, cpos_rej, cneg_rej, citer,
00658                                        cmax, cmin));
00659 
00660                     KMO_TRY_EXIT_IF_NULL(
00661                         fit_par = kmo_fit_profile_2D(made_data_img,
00662                                                      NULL,
00663                                                      "gauss",
00664                                                      &mask,
00665                                                      &fit_pl));
00666 
00667                     // update subheader with fit parameters
00668                     KMO_TRY_EXIT_IF_ERROR(
00669                         cpl_propertylist_append(sub_header_data, fit_pl));
00670 
00671                     cpl_propertylist_delete(fit_pl); fit_pl = NULL;
00672 
00673                     // normalise mask
00674                     // (subtract first background and then normalise)
00675                     cpl_image_subtract_scalar(mask, cpl_vector_get(fit_par, 0));
00676                     cpl_image_divide_scalar(mask, cpl_vector_get(fit_par, 1));
00677                     cpl_vector_delete(fit_par); fit_par = NULL;
00678                     cpl_image_delete(made_data_img); made_data_img = NULL;
00679                 }
00680 
00681                 // process & save data
00682                 KMO_TRY_EXIT_IF_ERROR(
00683                     kmo_priv_extract_spec(data_in,
00684                                           noise_in,
00685                                           mask,
00686                                           &spec_data_out,
00687                                           &spec_noise_out));
00688 
00689                 KMO_TRY_EXIT_IF_NULL(
00690                     sub_header_mask = cpl_propertylist_duplicate(
00691                                                               sub_header_data));
00692 
00693                 // change WCS here (CRPIX3 goes to CRPIX1 etc...)
00694                 KMO_TRY_EXIT_IF_NULL(
00695                     sub_header_data = kmo_priv_update_header(sub_header_data));
00696 
00697                 kmclipm_vector *ddd = kmclipm_vector_create(spec_data_out);
00698                 KMO_TRY_CHECK_ERROR_STATE();
00699 
00700                 KMO_TRY_EXIT_IF_ERROR(
00701                     kmo_dfs_save_vector(ddd, EXTRACT_SPEC, "",
00702                                         sub_header_data, 0./0.));
00703                 kmclipm_vector_delete(ddd); ddd = NULL; spec_data_out = NULL;
00704 
00705                 if (save_mask) {
00706                     // delete WCS for 3rd dimension since mask is 2D
00707                     KMO_TRY_EXIT_IF_ERROR(
00708                         cpl_propertylist_erase(sub_header_data, CRPIX3));
00709                     KMO_TRY_EXIT_IF_ERROR(
00710                         cpl_propertylist_erase(sub_header_data, CRVAL3));
00711                     KMO_TRY_EXIT_IF_ERROR(
00712                         cpl_propertylist_erase(sub_header_data, CDELT3));
00713                     KMO_TRY_EXIT_IF_ERROR(
00714                         cpl_propertylist_erase(sub_header_data, CTYPE3));
00715                     KMO_TRY_EXIT_IF_ERROR(
00716                         cpl_propertylist_erase(sub_header_data, CD1_3));
00717                     KMO_TRY_EXIT_IF_ERROR(
00718                         cpl_propertylist_erase(sub_header_data, CD2_3));
00719                     KMO_TRY_EXIT_IF_ERROR(
00720                         cpl_propertylist_erase(sub_header_data, CD3_3));
00721                     KMO_TRY_EXIT_IF_ERROR(
00722                         cpl_propertylist_erase(sub_header_data, CD3_1));
00723                     KMO_TRY_EXIT_IF_ERROR(
00724                         cpl_propertylist_erase(sub_header_data, CD3_2));
00725 
00726                     KMO_TRY_EXIT_IF_ERROR(
00727                         kmo_dfs_save_image(mask, EXTRACT_SPEC_MASK, "",
00728                                            sub_header_mask, 0.));
00729                 }
00730                 cpl_propertylist_delete(sub_header_mask);
00731                 sub_header_mask = NULL;
00732 
00733                 // process & save noise, if existing
00734                 if (desc1.ex_noise) {
00735                     kmclipm_vector *nnn = NULL;
00736                     if (spec_noise_out != NULL) {
00737                         nnn = kmclipm_vector_create(spec_noise_out);
00738                     }
00739                     KMO_TRY_EXIT_IF_NULL(
00740                         sub_header_noise = kmo_priv_update_header(
00741                                                              sub_header_noise));
00742 
00743                     KMO_TRY_EXIT_IF_ERROR(
00744                         kmo_dfs_save_vector(nnn, EXTRACT_SPEC, "",
00745                                             sub_header_noise, 0./0.));
00746                     kmclipm_vector_delete(nnn); nnn = NULL; spec_noise_out = NULL;
00747                 }
00748 
00749                 // free memory
00750                 cpl_imagelist_delete(data_in); data_in = NULL;
00751                 cpl_imagelist_delete(noise_in); noise_in = NULL;
00752                 KMO_TRY_CHECK_ERROR_STATE();
00753 
00754                 if (strcmp(mask_method, "integrated") != 0) {
00755                     // for integrated-method the mask will be deleted
00756                     // at the very end!
00757                     cpl_image_delete(mask); mask = NULL;
00758                 }
00759             } else {
00760                 // invalid IFU, just save sub_headers
00761                 KMO_TRY_EXIT_IF_ERROR(
00762                     kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_data));
00763 
00764                 if (desc1.ex_noise) {
00765                     KMO_TRY_EXIT_IF_ERROR(
00766                         kmo_dfs_save_sub_header(EXTRACT_SPEC, "", sub_header_noise));
00767                 }
00768             }
00769 
00770             // free memory
00771             cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00772             cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00773         }
00774 
00775         if (strcmp(mask_method, "integrated") == 0) {
00776             cpl_image_delete(mask); mask = NULL;
00777             cpl_vector_delete(centre); centre = NULL;
00778         }
00779     }
00780     KMO_CATCH
00781     {
00782         KMO_CATCH_MSG();
00783 
00784         ret_val = -1;
00785     }
00786 
00787     kmo_free_fits_desc(&desc1);
00788     kmo_free_fits_desc(&desc2);
00789 
00790     cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00791     cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00792     cpl_propertylist_delete(sub_header_mask); sub_header_mask = NULL;
00793     cpl_imagelist_delete(data_in); data_in = NULL;
00794     cpl_imagelist_delete(noise_in); noise_in = NULL;
00795     cpl_vector_delete(spec_data_out); spec_data_out = NULL;
00796     cpl_vector_delete(spec_noise_out); spec_noise_out = NULL;
00797     cpl_image_delete(mask); mask = NULL;
00798     cpl_vector_delete(centre); centre = NULL;
00799 
00800     return ret_val;
00801 }
00802