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