KMOS Pipeline Reference Manual  1.0.7
kmo_make_image.c
00001 /* $Id: kmo_make_image.c,v 1.12 2013/01/09 13:54:20 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/01/09 13:54:20 $
00024  * $Revision: 1.12 $
00025  * $Name: HEAD $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 #include <string.h>
00033 
00034 #include <cpl.h>
00035 
00036 #include "kmo_debug.h"
00037 #include "kmo_utils.h"
00038 #include "kmo_dfs.h"
00039 #include "kmo_error.h"
00040 #include "kmo_priv_make_image.h"
00041 #include "kmo_priv_functions.h"
00042 #include "kmo_constants.h"
00043 
00044 static int kmo_make_image_create(cpl_plugin *);
00045 static int kmo_make_image_exec(cpl_plugin *);
00046 static int kmo_make_image_destroy(cpl_plugin *);
00047 static int kmo_make_image(cpl_parameterlist *, cpl_frameset *);
00048 
00049 static char kmo_make_image_description[] =
00050 "This recipe collapses a cube along the spectral axis using rejection. By \n"
00051 "default all spectral slices are averaged.\n"
00052 "Errors are propagated for the same spectral ranges as for the input data if\n"
00053 "a noise map is provided.\n"
00054 "\n"
00055 "BASIC PARAMETERS:\n"
00056 "-----------------\n"
00057 "--range\n"
00058 "The spectral range can be delimited to one or several sub-ranges like \"1.8,1.9\"\n"
00059 "or \"1.8,1.9; 2.0,2.11\"\n"
00060 "\n"
00061 "--cmethod\n"
00062 "Following methods of frame combination are available:\n"
00063 "   * 'ksigma' (Default)\n"
00064 "   An iterative sigma clipping. For each position all pixels in the spectrum\n"
00065 "   are examined. If they deviate significantly, they will be rejected according\n"
00066 "   to the conditions:\n"
00067 "       val > mean + stdev * cpos_rej\n"
00068 "   and\n"
00069 "       val < mean - stdev * cneg_rej\n"
00070 "   where --cpos_rej, --cneg_rej and --citer are the corresponding configuration\n"
00071 "   parameters. In the first iteration median and percentile level are used.\n"
00072 "\n"
00073 "   * 'median'\n"
00074 "   At each pixel position the median is calculated.\n"
00075 "\n"
00076 "   * 'average'\n"
00077 "   At each pixel position the average is calculated.\n"
00078 "\n"
00079 "   * 'sum'\n"
00080 "   At each pixel position the sum is calculated.\n"
00081 "\n"
00082 "   * 'min_max'\n"
00083 "   The specified number of minimum and maximum pixel values will be rejected.\n"
00084 "   --cmax and --cmin apply to this method.\n"
00085 "\n"
00086 "ADVANCED PARAMETERS\n"
00087 "-------------------\n"
00088 "--threshold\n"
00089 "Optionally an OH spectrum can be provided. In this case a threshold can be\n"
00090 "defined. The wavelengths of values above the threshold level in the OH spectrum\n"
00091 "are omitted in the input frame. This parameter can be combined with the --range\n"
00092 "parameter. Negative threshold values are ignored.\n"
00093 "Own spectra can be converted into the required F1S KMOS FITS format for the OH\n"
00094 "spectrum using kmo_fits_stack.\n"
00095 "\n"
00096 "--cpos_rej\n"
00097 "--cneg_rej\n"
00098 "--citer\n"
00099 "see --cmethod='ksigma'\n"
00100 "\n"
00101 "--cmax\n"
00102 "--cmin\n"
00103 "see --cmethod='min_max'\n"
00104 "\n"
00105 "-------------------------------------------------------------------------------\n"
00106 "  Input files:\n"
00107 "\n"
00108 "   DO                    KMOS                                                  \n"
00109 "   category              Type   Explanation                    Required #Frames\n"
00110 "   --------              -----  -----------                    -------- -------\n"
00111 "   MAKE_IMG_DATA         F3I    data frame                         Y       1   \n"
00112 "   OH_LIST               F1S    OH line spectrum                   N      0,1  \n"
00113 "\n"
00114 "  Output files:\n"
00115 "\n"
00116 "   DO                    KMOS\n"
00117 "   category              Type   Explanation\n"
00118 "   --------              -----  -----------\n"
00119 "   MAKE_IMAGE            F2I    Collapsed data cubes\n"
00120 "-------------------------------------------------------------------------------\n"
00121 "\n";
00122 
00140 int cpl_plugin_get_info(cpl_pluginlist *list)
00141 {
00142     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00143     cpl_plugin *plugin = &recipe->interface;
00144 
00145     cpl_plugin_init(plugin,
00146                         CPL_PLUGIN_API,
00147                         KMOS_BINARY_VERSION,
00148                         CPL_PLUGIN_TYPE_RECIPE,
00149                         "kmo_make_image",
00150                         "Collapse a cube to create a spatial image",
00151                         kmo_make_image_description,
00152                         "Alex Agudo Berbel",
00153                         "agudo@mpe.mpg.de",
00154                         kmos_get_license(),
00155                         kmo_make_image_create,
00156                         kmo_make_image_exec,
00157                         kmo_make_image_destroy);
00158 
00159     cpl_pluginlist_append(list, plugin);
00160 
00161     return 0;
00162 }
00163 
00171 static int kmo_make_image_create(cpl_plugin *plugin)
00172 {
00173     cpl_recipe *recipe;
00174     cpl_parameter *p;
00175 
00176     /* Check that the plugin is part of a valid recipe */
00177     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00178         recipe = (cpl_recipe *)plugin;
00179     else
00180         return -1;
00181 
00182     /* Create the parameters list in the cpl_recipe object */
00183     recipe->parameters = cpl_parameterlist_new();
00184 
00185     /* Fill the parameters list */
00186     /* --range */
00187     p = cpl_parameter_new_value("kmos.kmo_make_image.range",
00188                                 CPL_TYPE_STRING,
00189                                 "The spectral ranges to combine. e.g."
00190                                 "\"x1_start,x1_end;x2_start,x2_end\" (microns)",
00191                                 "kmos.kmo_make_image",
00192                                 "");
00193     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range");
00194     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00195     cpl_parameterlist_append(recipe->parameters, p);
00196 
00197     /* --threshold (if < 0, no thresholding at all) */
00198     p = cpl_parameter_new_value("kmos.kmo_make_image.threshold",
00199                                 CPL_TYPE_DOUBLE,
00200                                 "The OH threshold level (%)",
00201                                 "kmos.kmo_make_image",
00202                                 0.1);
00203     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "threshold");
00204     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00205     cpl_parameterlist_append(recipe->parameters, p);
00206 
00207     return kmo_combine_pars_create(recipe->parameters,
00208                                    "kmos.kmo_make_image",
00209                                    DEF_REJ_METHOD,
00210                                    FALSE);
00211 }
00212 
00218 static int kmo_make_image_exec(cpl_plugin *plugin)
00219 {
00220     cpl_recipe  *recipe;
00221 
00222     /* Get the recipe out of the plugin */
00223     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00224         recipe = (cpl_recipe *)plugin;
00225     else return -1 ;
00226 
00227     return kmo_make_image(recipe->parameters, recipe->frames);
00228 }
00229 
00235 static int kmo_make_image_destroy(cpl_plugin *plugin)
00236 {
00237     cpl_recipe *recipe;
00238 
00239     /* Get the recipe out of the plugin */
00240     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00241         recipe = (cpl_recipe *)plugin;
00242     else return -1 ;
00243 
00244     cpl_parameterlist_delete(recipe->parameters);
00245     return 0 ;
00246 }
00247 
00262 static int kmo_make_image(cpl_parameterlist *parlist, cpl_frameset *frameset)
00263 {
00264     const char       *cmethod             = NULL;
00265 
00266     double           threshold           = 0.0,
00267                      spec_crval          = 0.0,
00268                      spec_cdelt          = 0.0,
00269                      ifu_crval           = 0.0,
00270                      ifu_cdelt           = 0.0,
00271                      cpos_rej            = 0.0,
00272                      cneg_rej            = 0.0;
00273 
00274     cpl_imagelist    *data_in            = NULL,
00275                      *noise_in           = NULL;
00276 
00277     cpl_image        *data_out           = NULL,
00278                      *noise_out          = NULL;
00279 
00280     const char       *ranges_txt         = NULL;
00281 
00282     cpl_vector       *ranges             = NULL,
00283                      *identified_slices  = NULL,
00284                      *spec_data_in       = NULL,
00285                      *spec_lambda_in     = NULL;
00286 
00287     int              ret_val             = 0,
00288                      nr_devices          = 0,
00289                      i                   = 0,
00290                      valid_ifu           = FALSE,
00291                      citer               = 0,
00292                      cmax                = 0,
00293                      cmin                = 0,
00294                      ifu_crpix           = 0,
00295                      spec_crpix          = 0,
00296                      devnr               = 0,
00297                      index_data          = 0,
00298                      index_noise         = 0;
00299 
00300     cpl_propertylist *sub_header_data    = NULL,
00301                      *sub_header_noise   = NULL,
00302                      *spec_header         = NULL;
00303 
00304     main_fits_desc   desc1,
00305                      desc2;
00306 
00307     cpl_frame        *op1_frame          = NULL,
00308                      *op2_frame          = NULL;
00309 
00310     char             do_mode1[256],
00311                      do_mode2[256];
00312 
00313     KMO_TRY
00314     {
00315         kmo_init_fits_desc(&desc1);
00316         kmo_init_fits_desc(&desc2);
00317 
00318         /* --- check input --- */
00319         KMO_TRY_ASSURE((parlist != NULL) &&
00320                        (frameset != NULL),
00321                        CPL_ERROR_NULL_INPUT,
00322                        "Not all input data is provided!");
00323 
00324         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_make_image") == 1,
00325                        CPL_ERROR_ILLEGAL_INPUT,
00326                        "Cannot identify RAW and CALIB frames!");
00327 
00328         cpl_msg_info("", "--- Parameter setup for kmo_make_image ----");
00329 
00330         threshold = kmo_dfs_get_parameter_double(parlist,
00331                                           "kmos.kmo_make_image.threshold");
00332         KMO_TRY_CHECK_ERROR_STATE();
00333         KMO_TRY_EXIT_IF_ERROR(
00334             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_make_image.threshold"));
00335 
00336         ranges_txt = kmo_dfs_get_parameter_string(parlist,
00337                                                   "kmos.kmo_make_image.range");
00338         KMO_TRY_CHECK_ERROR_STATE();
00339         KMO_TRY_EXIT_IF_ERROR(
00340             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_make_image.range"));
00341 
00342         ranges = kmo_identify_ranges(ranges_txt);
00343         KMO_TRY_CHECK_ERROR_STATE();
00344 
00345         KMO_TRY_EXIT_IF_ERROR(
00346             kmo_combine_pars_load(parlist,
00347                                   "kmos.kmo_make_image",
00348                                   &cmethod,
00349                                   &cpos_rej,
00350                                   &cneg_rej,
00351                                   &citer,
00352                                   &cmin,
00353                                   &cmax,
00354                                   FALSE));
00355         cpl_msg_info("", "-------------------------------------------");
00356 
00357         KMO_TRY_ASSURE((cpl_frameset_get_size(frameset) == 1) ||
00358                        ((cpl_frameset_get_size(frameset) == 2) &&
00359                        (threshold != 0.0)),
00360                        CPL_ERROR_NULL_INPUT,
00361                        "A cube or a cube and a OH line spectrum "
00362                        "must be provided!");
00363 
00364         if (cpl_frameset_get_size(frameset) == 1) {
00365 
00366             KMO_TRY_ASSURE((cpl_frameset_count_tags(frameset, MAKE_IMG_DATA) == 1) ||
00367                            (cpl_frameset_count_tags(frameset, COMMANDLINE) == 1),
00368                            CPL_ERROR_ILLEGAL_INPUT,
00369                            "The cube must be tagged as MAKE_IMG_DATA!");
00370 
00371             if (cpl_frameset_count_tags(frameset, MAKE_IMG_DATA) == 1) {
00372                 strcpy(do_mode1, MAKE_IMG_DATA);
00373                 strcpy(do_mode2, "");
00374             } else {
00375                 strcpy(do_mode1, "0");
00376                 strcpy(do_mode2, "");
00377             }
00378         } else {
00379             if ((cpl_frameset_count_tags(frameset, MAKE_IMG_DATA) == 1) &&
00380                 (cpl_frameset_count_tags(frameset, OH_LIST) == 1)){
00381                 strcpy(do_mode1, MAKE_IMG_DATA);
00382                 strcpy(do_mode2, OH_LIST);
00383             } else {
00384                 strcpy(do_mode1, "0");
00385                 strcpy(do_mode2, "1");
00386             }
00387             KMO_TRY_EXIT_IF_NULL(
00388                 op2_frame = kmo_dfs_get_frame(frameset, do_mode2));
00389 
00390             desc2 = kmo_identify_fits_header(
00391                     cpl_frame_get_filename(op2_frame));
00392             KMO_TRY_CHECK_ERROR_STATE_MSG("Provided fits file doesn't seem "
00393                                       "to be in KMOS-format! "
00394                                       "(KMOSTYPE must be F1S)!");
00395 
00396             KMO_TRY_ASSURE(desc2.fits_type == f1s_fits,
00397                            CPL_ERROR_ILLEGAL_INPUT,
00398                            "Second input file hasn't correct data type "
00399                            "(KMOSTYPE must be F1S)!");
00400         }
00401         KMO_TRY_EXIT_IF_NULL(
00402             op1_frame = kmo_dfs_get_frame(frameset, do_mode1));
00403 
00404         /* load descriptor of first operand */
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                        "First input file hasn't correct data type "
00413                        "(KMOSTYPE must be F3I)!");
00414 
00415         if (cpl_frameset_get_size(frameset) == 1) {
00416             /* only cube is provided */
00417         } else if (cpl_frameset_get_size(frameset) == 2) {
00418             /* cube and OH line spectrum are provided */
00419             KMO_TRY_EXIT_IF_NULL(
00420                 spec_header = kmo_dfs_load_sub_header(frameset, do_mode2, 1,
00421                                                           FALSE));
00422 
00423             KMO_TRY_ASSURE(cpl_propertylist_get_int(spec_header, NAXIS) == 1,
00424                            CPL_ERROR_ILLEGAL_INPUT,
00425                            "Second input file has to be a vector!");
00426 
00427             /* load header & data of OH-lines*/
00428             spec_crpix = cpl_propertylist_get_int(spec_header, CRPIX1);
00429             KMO_TRY_CHECK_ERROR_STATE();
00430             spec_crval = cpl_propertylist_get_double(spec_header, CRVAL1);
00431             KMO_TRY_CHECK_ERROR_STATE();
00432             spec_cdelt = cpl_propertylist_get_double(spec_header, CDELT1);
00433             KMO_TRY_CHECK_ERROR_STATE();
00434 
00435             kmclipm_vector *tmp_vec = NULL;
00436             KMO_TRY_EXIT_IF_NULL(
00437                 tmp_vec = kmo_dfs_load_vector(frameset, do_mode2,
00438                                                    1, FALSE));
00439             KMO_TRY_EXIT_IF_NULL(
00440                 spec_data_in = kmclipm_vector_create_non_rejected(tmp_vec));
00441             kmclipm_vector_delete(tmp_vec); tmp_vec = NULL;
00442 
00443             /* convert threshold from percentage to absolute value*/
00444             threshold = threshold * cpl_vector_get_max(spec_data_in);
00445 
00446             /* create lambda-vector for OH-lines */
00447             KMO_TRY_EXIT_IF_NULL(
00448                 spec_lambda_in = kmo_create_lambda_vec(
00449                                     cpl_vector_get_size(spec_data_in),
00450                                     spec_crpix,
00451                                     spec_crval,
00452                                     spec_cdelt));
00453 
00454         } else {
00455             KMO_TRY_EXIT_WITH_ERROR(CPL_ERROR_ILLEGAL_INPUT);
00456         }
00457 
00458         // --- load, update & save primary header ---
00459         KMO_TRY_EXIT_IF_ERROR(
00460             kmo_dfs_save_main_header(frameset, MAKE_IMAGE, "", op1_frame,
00461                                      NULL, parlist, cpl_func));
00462 
00463         // --- load data ---
00464         if (desc1.ex_noise == TRUE) {
00465             nr_devices = desc1.nr_ext / 2;
00466         } else {
00467             nr_devices = desc1.nr_ext;
00468         }
00469 
00470         for (i = 1; i <= nr_devices; i++) {
00471             if (desc1.ex_noise == FALSE) {
00472                 devnr = desc1.sub_desc[i - 1].device_nr;
00473             } else {
00474                 devnr = desc1.sub_desc[2 * i - 1].device_nr;
00475             }
00476 
00477             if (desc1.ex_badpix == FALSE) {
00478                 index_data = kmo_identify_index_desc(desc1, devnr, FALSE);
00479             } else {
00480                 index_data = kmo_identify_index_desc(desc1, devnr, 2);
00481             }
00482             KMO_TRY_CHECK_ERROR_STATE();
00483 
00484             if (desc1.ex_noise) {
00485                 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE);
00486             }
00487             KMO_TRY_CHECK_ERROR_STATE();
00488 
00489             KMO_TRY_EXIT_IF_NULL(
00490                 sub_header_data = kmo_dfs_load_sub_header(frameset, do_mode1,
00491                                                           devnr, FALSE));
00492 
00493             // check if IFU is valid
00494             valid_ifu = FALSE;
00495             if (desc1.sub_desc[index_data-1].valid_data == TRUE) {
00496                 valid_ifu = TRUE;
00497             }
00498 
00499             if (desc1.ex_noise) {
00500                 // load noise anyway since we have to save it in the output
00501                 KMO_TRY_EXIT_IF_NULL(
00502                     sub_header_noise = kmo_dfs_load_sub_header(frameset,
00503                                                                do_mode1, devnr,
00504                                                                TRUE));
00505 
00506                 if (cpl_propertylist_has(sub_header_noise, CRPIX3))
00507                     cpl_propertylist_erase(sub_header_noise, CRPIX3);
00508                 if (cpl_propertylist_has(sub_header_noise, CRVAL3))
00509                     cpl_propertylist_erase(sub_header_noise, CRVAL3);
00510                 if (cpl_propertylist_has(sub_header_noise, CDELT3))
00511                     cpl_propertylist_erase(sub_header_noise, CDELT3);
00512                 if (cpl_propertylist_has(sub_header_noise, CTYPE3))
00513                     cpl_propertylist_erase(sub_header_noise, CTYPE3);
00514                 if (cpl_propertylist_has(sub_header_noise, CUNIT3))
00515                     cpl_propertylist_erase(sub_header_noise, CUNIT3);
00516                 if (cpl_propertylist_has(sub_header_noise, CD1_3))
00517                     cpl_propertylist_erase(sub_header_noise, CD1_3);
00518                 if (cpl_propertylist_has(sub_header_noise, CD2_3))
00519                     cpl_propertylist_erase(sub_header_noise, CD2_3);
00520                 if (cpl_propertylist_has(sub_header_noise, CD3_3))
00521                     cpl_propertylist_erase(sub_header_noise, CD3_3);
00522                 if (cpl_propertylist_has(sub_header_noise, CD3_2))
00523                     cpl_propertylist_erase(sub_header_noise, CD3_2);
00524                 if (cpl_propertylist_has(sub_header_noise, CD3_1))
00525                     cpl_propertylist_erase(sub_header_noise, CD3_1);
00526             }
00527 
00528             if (valid_ifu) {
00529                 // load data
00530                 KMO_TRY_EXIT_IF_NULL(
00531                     data_in = kmo_dfs_load_cube(frameset, do_mode1,
00532                                                 devnr, FALSE));
00533 
00534                 // load noise, if existing
00535                 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data) {
00536                     KMO_TRY_EXIT_IF_NULL(
00537                         noise_in = kmo_dfs_load_cube(frameset, do_mode1, devnr,
00538                                                      TRUE));
00539                 }
00540 
00541                 // interpolate oh-lines to fit input data
00542                 if (spec_data_in != NULL) {
00543                     ifu_crpix = cpl_propertylist_get_int(sub_header_data,
00544                                                          CRPIX3);
00545                     KMO_TRY_CHECK_ERROR_STATE_MSG(
00546                         "CRPIX3 keyword in FITS-header is missing!");
00547 
00548                     ifu_crval = cpl_propertylist_get_double(sub_header_data,
00549                                                             CRVAL3);
00550                     KMO_TRY_CHECK_ERROR_STATE_MSG(
00551                         "CRVAL3 keyword in FITS-header is missing!");
00552 
00553 
00554                     ifu_cdelt = cpl_propertylist_get_double(sub_header_data,
00555                                                             CDELT3);
00556                     KMO_TRY_CHECK_ERROR_STATE_MSG(
00557                         "CDELT3 keyword in FITS-header is missing!");
00558 
00559                     KMO_TRY_EXIT_IF_NULL(
00560                         identified_slices = kmo_identify_slices_with_oh(
00561                                                                 spec_data_in,
00562                                                                 spec_lambda_in,
00563                                                                 ranges,
00564                                                                 threshold,
00565                                                                 ifu_crpix,
00566                                                                 ifu_crval,
00567                                                                 ifu_cdelt,
00568                                                                 desc1.naxis3));
00569                 }
00570 
00571                 if (cpl_propertylist_has(sub_header_data, CRPIX3))
00572                     cpl_propertylist_erase(sub_header_data, CRPIX3);
00573                 if (cpl_propertylist_has(sub_header_data, CRVAL3))
00574                     cpl_propertylist_erase(sub_header_data, CRVAL3);
00575                 if (cpl_propertylist_has(sub_header_data, CDELT3))
00576                     cpl_propertylist_erase(sub_header_data, CDELT3);
00577                 if (cpl_propertylist_has(sub_header_data, CTYPE3))
00578                     cpl_propertylist_erase(sub_header_data, CTYPE3);
00579                 if (cpl_propertylist_has(sub_header_data, CUNIT3))
00580                     cpl_propertylist_erase(sub_header_data, CUNIT3);
00581                 if (cpl_propertylist_has(sub_header_data, CD1_3))
00582                     cpl_propertylist_erase(sub_header_data, CD1_3);
00583                 if (cpl_propertylist_has(sub_header_data, CD2_3))
00584                     cpl_propertylist_erase(sub_header_data, CD2_3);
00585                 if (cpl_propertylist_has(sub_header_data, CD3_3))
00586                     cpl_propertylist_erase(sub_header_data, CD3_3);
00587                 if (cpl_propertylist_has(sub_header_data, CD3_2))
00588                     cpl_propertylist_erase(sub_header_data, CD3_2);
00589                 if (cpl_propertylist_has(sub_header_data, CD3_1))
00590                     cpl_propertylist_erase(sub_header_data, CD3_1);
00591 
00592                 // process & save data
00593                 KMO_TRY_EXIT_IF_ERROR(
00594                     kmclipm_make_image(data_in, noise_in,
00595                                        &data_out, &noise_out,
00596                                        identified_slices,
00597                                        cmethod, cpos_rej, cneg_rej, citer,
00598                                        cmax, cmin));
00599 
00600                 KMO_TRY_EXIT_IF_ERROR(
00601                     kmo_dfs_save_image(data_out, MAKE_IMAGE, "",
00602                                        sub_header_data, 0./0.));
00603 
00604                 // process & save noise, if existing
00605                 if (desc1.ex_noise) {
00606                     KMO_TRY_EXIT_IF_ERROR(
00607                         kmo_dfs_save_image(noise_out, MAKE_IMAGE, "",
00608                                            sub_header_noise, 0./0.));
00609                 }
00610 
00611                 // free memory
00612                 cpl_imagelist_delete(data_in); data_in = NULL;
00613                 cpl_imagelist_delete(noise_in); noise_in = NULL;
00614                 cpl_image_delete(data_out); data_out = NULL;
00615                 cpl_image_delete(noise_out); noise_out = NULL;
00616                 cpl_vector_delete(identified_slices); identified_slices = NULL;
00617             } else {
00618                 if (cpl_propertylist_has(sub_header_data, CRPIX3))
00619                     cpl_propertylist_erase(sub_header_data, CRPIX3);
00620                 if (cpl_propertylist_has(sub_header_data, CRVAL3))
00621                     cpl_propertylist_erase(sub_header_data, CRVAL3);
00622                 if (cpl_propertylist_has(sub_header_data, CDELT3))
00623                     cpl_propertylist_erase(sub_header_data, CDELT3);
00624                 if (cpl_propertylist_has(sub_header_data, CTYPE3))
00625                     cpl_propertylist_erase(sub_header_data, CTYPE3);
00626                 if (cpl_propertylist_has(sub_header_data, CUNIT3))
00627                     cpl_propertylist_erase(sub_header_data, CUNIT3);
00628                 if (cpl_propertylist_has(sub_header_data, CD1_3))
00629                     cpl_propertylist_erase(sub_header_data, CD1_3);
00630                 if (cpl_propertylist_has(sub_header_data, CD2_3))
00631                     cpl_propertylist_erase(sub_header_data, CD2_3);
00632                 if (cpl_propertylist_has(sub_header_data, CD3_3))
00633                     cpl_propertylist_erase(sub_header_data, CD3_3);
00634                 if (cpl_propertylist_has(sub_header_data, CD3_2))
00635                     cpl_propertylist_erase(sub_header_data, CD3_2);
00636                 if (cpl_propertylist_has(sub_header_data, CD3_1))
00637                     cpl_propertylist_erase(sub_header_data, CD3_1);
00638 
00639                 // invalid IFU, just save sub_headers
00640                  KMO_TRY_EXIT_IF_ERROR(
00641                      kmo_dfs_save_sub_header(MAKE_IMAGE, "", sub_header_data));
00642 
00643                  if (desc1.ex_noise) {
00644                      KMO_TRY_EXIT_IF_ERROR(
00645                          kmo_dfs_save_sub_header(MAKE_IMAGE, "", sub_header_noise));
00646                  }
00647             }
00648 
00649             // free memory
00650             cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00651             cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00652         }
00653     }
00654     KMO_CATCH
00655     {
00656         KMO_CATCH_MSG();
00657         ret_val = -1;
00658     }
00659 
00660     kmo_free_fits_desc(&desc1);
00661     kmo_free_fits_desc(&desc2);
00662     cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00663     cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00664     cpl_propertylist_delete(spec_header); spec_header = NULL;
00665     cpl_imagelist_delete(data_in); data_in = NULL;
00666     cpl_imagelist_delete(noise_in); noise_in = NULL;
00667     cpl_image_delete(data_out); data_out = NULL;
00668     cpl_image_delete(noise_out); noise_out = NULL;
00669     cpl_vector_delete(spec_data_in); spec_data_in = NULL;
00670     cpl_vector_delete(spec_lambda_in); spec_lambda_in = NULL;
00671     cpl_vector_delete(ranges); ranges = NULL;
00672 
00673     return ret_val;
00674 }
00675