KMOS Pipeline Reference Manual  1.3.0
kmo_make_image.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 
00030 #include <cpl.h>
00031 
00032 #include "kmo_debug.h"
00033 #include "kmo_utils.h"
00034 #include "kmo_dfs.h"
00035 #include "kmo_error.h"
00036 #include "kmo_priv_make_image.h"
00037 #include "kmo_priv_functions.h"
00038 #include "kmo_constants.h"
00039 
00040 /*-----------------------------------------------------------------------------
00041  *                          Functions prototypes
00042  *----------------------------------------------------------------------------*/
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 /*-----------------------------------------------------------------------------
00050  *                          Static variables
00051  *----------------------------------------------------------------------------*/
00052 
00053 static char kmo_make_image_description[] =
00054 "This recipe collapses a cube along the spectral axis using rejection. By \n"
00055 "default all spectral slices are averaged.\n"
00056 "Errors are propagated for the same spectral ranges as for the input data if\n"
00057 "a noise map is provided.\n"
00058 "\n"
00059 "BASIC PARAMETERS:\n"
00060 "-----------------\n"
00061 "--range\n"
00062 "The spectral range can be delimited to one or several sub-ranges like \n"
00063 "\"1.8,1.9\" or \"1.8,1.9; 2.0,2.11\"\n"
00064 "\n"
00065 "--cmethod\n"
00066 "Following methods of frame combination are available:\n"
00067 "   * 'ksigma' (Default)\n"
00068 "       An iterative sigma clipping. For each position all pixels in the\n"
00069 "       spectrum are examined. If they deviate significantly, they will be\n"
00070 "       rejected according to the conditions:\n"
00071 "           val > mean + stdev * cpos_rej\n"
00072 "       and\n"
00073 "           val < mean - stdev * cneg_rej\n"
00074 "       where --cpos_rej, --cneg_rej and --citer are the wished parameters\n"
00075 "       In the first iteration median and percentile level are used.\n"
00076 "   * 'median'\n"
00077 "       At each pixel position the median is calculated.\n"
00078 "   * 'average'\n"
00079 "       At each pixel position the average is calculated.\n"
00080 "   * 'sum'\n"
00081 "       At each pixel position the sum is calculated.\n"
00082 "   * 'min_max'\n"
00083 "       The specified number of min and max 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\n"
00091 "spectrum are omitted in the input frame. This parameter can be combined with\n"
00092 "the --range parameter. Negative threshold values are ignored.\n"
00093 "Own spectra can be converted into the required F1S KMOS FITS format for the\n"
00094 "OH 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 "--cmax\n"
00101 "--cmin\n"
00102 "   see --cmethod='min_max'\n"
00103 "\n"
00104 "---------------------------------------------------------------------------\n"
00105 "  Input files:\n"
00106 "   DO CATG           Type   Explanation                    Required #Frames\n"
00107 "   -------           -----  -----------                    -------- -------\n"
00108 "   <none or any>     F3I    data frame                         Y       1   \n"
00109 "   <none or any>     F1S    OH line spectrum                   N      0,1  \n"
00110 "\n"
00111 "  Output files:\n"
00112 "   DO CATG           Type   Explanation\n"
00113 "   -------           -----  -----------\n"
00114 "   MAKE_IMAGE        F2I    Collapsed data cubes\n"
00115 "---------------------------------------------------------------------------\n"
00116 "\n";
00117 
00118 /*----------------------------------------------------------------------------*/
00122 /*----------------------------------------------------------------------------*/
00123 
00126 /*----------------------------------------------------------------------------*/
00135 /*----------------------------------------------------------------------------*/
00136 int cpl_plugin_get_info(cpl_pluginlist *list)
00137 {
00138     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00139     cpl_plugin *plugin = &recipe->interface;
00140 
00141     cpl_plugin_init(plugin,
00142             CPL_PLUGIN_API,
00143             KMOS_BINARY_VERSION,
00144             CPL_PLUGIN_TYPE_RECIPE,
00145             "kmo_make_image",
00146             "Collapse a cube to create a spatial image",
00147             kmo_make_image_description,
00148             "Alex Agudo Berbel",
00149             "usd-help@eso.org",
00150             kmos_get_license(),
00151             kmo_make_image_create,
00152             kmo_make_image_exec,
00153             kmo_make_image_destroy);
00154 
00155     cpl_pluginlist_append(list, plugin);
00156 
00157     return 0;
00158 }
00159 
00160 /*----------------------------------------------------------------------------*/
00168 /*----------------------------------------------------------------------------*/
00169 static int kmo_make_image_create(cpl_plugin *plugin)
00170 {
00171     cpl_recipe *recipe;
00172     cpl_parameter *p;
00173 
00174     /* Check that the plugin is part of a valid recipe */
00175     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00176         recipe = (cpl_recipe *)plugin;
00177     else
00178         return -1;
00179 
00180     /* Create the parameters list in the cpl_recipe object */
00181     recipe->parameters = cpl_parameterlist_new();
00182 
00183     /* Fill the parameters list */
00184     /* --range */
00185     p = cpl_parameter_new_value("kmos.kmo_make_image.range", CPL_TYPE_STRING,
00186             "The spectral ranges to combine. e.g."
00187             "\"x1_start,x1_end;x2_start,x2_end\" (microns)",
00188             "kmos.kmo_make_image", "");
00189     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range");
00190     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00191     cpl_parameterlist_append(recipe->parameters, p);
00192 
00193     /* --threshold (if < 0, no thresholding at all) */
00194     p = cpl_parameter_new_value("kmos.kmo_make_image.threshold",
00195             CPL_TYPE_DOUBLE, "The OH threshold level (%)",
00196             "kmos.kmo_make_image", 0.1);
00197     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "threshold");
00198     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00199     cpl_parameterlist_append(recipe->parameters, p);
00200 
00201     return kmo_combine_pars_create(recipe->parameters, "kmos.kmo_make_image", 
00202             DEF_REJ_METHOD, FALSE);
00203 }
00204 
00205 /*----------------------------------------------------------------------------*/
00211 /*----------------------------------------------------------------------------*/
00212 static int kmo_make_image_exec(cpl_plugin *plugin)
00213 {
00214     cpl_recipe  *recipe;
00215 
00216     /* Get the recipe out of the plugin */
00217     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00218         recipe = (cpl_recipe *)plugin;
00219     else return -1 ;
00220 
00221     return kmo_make_image(recipe->parameters, recipe->frames);
00222 }
00223 
00224 /*----------------------------------------------------------------------------*/
00230 /*----------------------------------------------------------------------------*/
00231 static int kmo_make_image_destroy(cpl_plugin *plugin)
00232 {
00233     cpl_recipe *recipe;
00234 
00235     /* Get the recipe out of the plugin */
00236     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00237         recipe = (cpl_recipe *)plugin;
00238     else return -1 ;
00239 
00240     cpl_parameterlist_delete(recipe->parameters);
00241     return 0 ;
00242 }
00243 
00244 /*----------------------------------------------------------------------------*/
00258 /*----------------------------------------------------------------------------*/
00259 static int kmo_make_image(cpl_parameterlist *parlist, cpl_frameset *frameset)
00260 {
00261     const char       *cmethod             = NULL;
00262 
00263     double           threshold           = 0.0,
00264                      spec_crpix          = 0.0,
00265                      spec_crval          = 0.0,
00266                      spec_cdelt          = 0.0,
00267                      ifu_crpix           = 0.0,
00268                      ifu_crval           = 0.0,
00269                      ifu_cdelt           = 0.0,
00270                      cpos_rej            = 0.0,
00271                      cneg_rej            = 0.0;
00272 
00273     cpl_imagelist    *data_in            = NULL,
00274                      *noise_in           = NULL;
00275 
00276     cpl_image        *data_out           = NULL,
00277                      *noise_out          = NULL;
00278 
00279     const char       *ranges_txt         = NULL;
00280 
00281     cpl_vector       *ranges             = NULL,
00282                      *identified_slices  = NULL,
00283                      *spec_data_in       = NULL,
00284                      *spec_lambda_in     = NULL;
00285 
00286     int              ret_val             = 0,
00287                      nr_devices          = 0,
00288                      i                   = 0,
00289                      valid_ifu           = FALSE,
00290                      citer               = 0,
00291                      cmax                = 0,
00292                      cmin                = 0,
00293                      devnr               = 0,
00294                      index_data          = 0,
00295                      index_noise         = 0;
00296 
00297     cpl_propertylist *sub_header_data    = NULL,
00298                      *sub_header_noise   = NULL,
00299                      *spec_header         = NULL;
00300 
00301     main_fits_desc   desc1,
00302                      desc2;
00303 
00304     cpl_frame        *op1_frame          = NULL,
00305                      *op2_frame          = NULL;
00306 
00307     KMO_TRY
00308     {
00309         kmo_init_fits_desc(&desc1);
00310         kmo_init_fits_desc(&desc2);
00311 
00312         /* --- check input --- */
00313         KMO_TRY_ASSURE((parlist != NULL) && (frameset != NULL),
00314                 CPL_ERROR_NULL_INPUT, "Not all input data is provided");
00315 
00316         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_make_image") == 1,
00317                 CPL_ERROR_ILLEGAL_INPUT,"Cannot identify RAW and CALIB frames");
00318 
00319         cpl_msg_info("", "--- Parameter setup for kmo_make_image ----");
00320         threshold = kmo_dfs_get_parameter_double(parlist,
00321                 "kmos.kmo_make_image.threshold");
00322         KMO_TRY_CHECK_ERROR_STATE();
00323         KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist, 
00324                     "kmos.kmo_make_image.threshold"));
00325 
00326         ranges_txt = kmo_dfs_get_parameter_string(parlist,
00327                 "kmos.kmo_make_image.range");
00328         KMO_TRY_CHECK_ERROR_STATE();
00329         KMO_TRY_EXIT_IF_ERROR(kmo_dfs_print_parameter_help(parlist, 
00330                     "kmos.kmo_make_image.range"));
00331         ranges = kmo_identify_ranges(ranges_txt);
00332         KMO_TRY_CHECK_ERROR_STATE();
00333 
00334         KMO_TRY_EXIT_IF_ERROR(kmo_combine_pars_load(parlist,
00335                     "kmos.kmo_make_image", &cmethod, &cpos_rej, &cneg_rej,
00336                     &citer, &cmin, &cmax, FALSE));
00337         cpl_msg_info("", "-------------------------------------------");
00338 
00339         KMO_TRY_ASSURE((cpl_frameset_get_size(frameset) == 1) ||
00340                 ((cpl_frameset_get_size(frameset) == 2) && (threshold != 0.0)),
00341                 CPL_ERROR_NULL_INPUT,
00342                 "A cube or a cube and a OH line spectrum must be provided");
00343 
00344         /* Get First Frame and its Descriptor */
00345         op1_frame=cpl_frameset_get_position(frameset, 0) ;
00346         desc1 = kmo_identify_fits_header(cpl_frame_get_filename(op1_frame));
00347         KMO_TRY_CHECK_ERROR_STATE_MSG("Wrong File Format");
00348         KMO_TRY_ASSURE(desc1.fits_type == f3i_fits, CPL_ERROR_ILLEGAL_INPUT,
00349                 "First file has wrong data type (expect F3I)");
00350 
00351         /* Get Second Frame and its decriptor */
00352         if (cpl_frameset_get_size(frameset) > 1) {
00353             op2_frame=cpl_frameset_get_position(frameset, 1) ;
00354             desc2 = kmo_identify_fits_header(cpl_frame_get_filename(op2_frame));
00355             KMO_TRY_CHECK_ERROR_STATE_MSG("Wrong File Format");
00356             KMO_TRY_ASSURE(desc2.fits_type == f1s_fits, CPL_ERROR_ILLEGAL_INPUT,
00357                     "Second file has wrong data type (expect F1S)");
00358             
00359             /* Load OH-lines header */
00360             spec_header = kmos_dfs_load_sub_header(op2_frame, 1, FALSE);
00361             KMO_TRY_EXIT_IF_NULL(spec_header) ;
00362             KMO_TRY_ASSURE(cpl_propertylist_get_int(spec_header, NAXIS) == 1,
00363                     CPL_ERROR_ILLEGAL_INPUT, 
00364                     "Second input file must be a vector");
00365             spec_crpix = cpl_propertylist_get_double(spec_header, CRPIX1);
00366             KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot get CRPIX1");
00367             spec_crval = cpl_propertylist_get_double(spec_header, CRVAL1);
00368             KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot get CRVAL1");
00369             spec_cdelt = cpl_propertylist_get_double(spec_header, CDELT1);
00370             KMO_TRY_CHECK_ERROR_STATE_MSG("Cannot get CDELT1");
00371 
00372             /* Load OH lines data */
00373             kmclipm_vector * tmp_vec ;
00374             tmp_vec = kmos_dfs_load_vector(op2_frame, 1, FALSE) ;
00375             spec_data_in = kmclipm_vector_create_non_rejected(tmp_vec);
00376             kmclipm_vector_delete(tmp_vec);
00377             KMO_TRY_EXIT_IF_NULL(spec_data_in) ;
00378 
00379             /* Convert threshold from percentage to absolute value */
00380             threshold = threshold * cpl_vector_get_max(spec_data_in);
00381 
00382             // create lambda-vector for OH-lines
00383             KMO_TRY_EXIT_IF_NULL(
00384                 spec_lambda_in = kmo_create_lambda_vec(
00385                     cpl_vector_get_size(spec_data_in), 
00386                     (int)spec_crpix, spec_crval, spec_cdelt));
00387         }
00388 
00389         /* --- load, update & save primary header --- */
00390         KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_main_header(frameset, MAKE_IMAGE, 
00391                     "", op1_frame, NULL, parlist, cpl_func));
00392 
00393         /* --- load data --- */
00394         if (desc1.ex_noise == TRUE) {
00395             nr_devices = desc1.nr_ext / 2;
00396         } else {
00397             nr_devices = desc1.nr_ext;
00398         }
00399 
00400         for (i = 1; i <= nr_devices; i++) {
00401 
00402             /* Get the Device Nb */
00403             if (desc1.ex_noise == FALSE) {
00404                 devnr = desc1.sub_desc[i - 1].device_nr;
00405             } else {
00406                 devnr = desc1.sub_desc[2 * i - 1].device_nr;
00407             }
00408 
00409             /* Get the Data index */
00410             if (desc1.ex_badpix == FALSE) {
00411                 index_data = kmo_identify_index_desc(desc1, devnr, FALSE);
00412             } else {
00413                 index_data = kmo_identify_index_desc(desc1, devnr, 2);
00414             }
00415             KMO_TRY_CHECK_ERROR_STATE();
00416 
00417             /* Get the Noise index */
00418             if (desc1.ex_noise) {
00419                 index_noise = kmo_identify_index_desc(desc1, devnr, TRUE);
00420             }
00421             KMO_TRY_CHECK_ERROR_STATE();
00422 
00423             /* Load the Extension Header */
00424             sub_header_data = kmos_dfs_load_sub_header(op1_frame, devnr, FALSE);
00425             KMO_TRY_EXIT_IF_NULL(sub_header_data) ;
00426 
00427             /* Check if IFU is valid */
00428             valid_ifu = FALSE;
00429             if (desc1.sub_desc[index_data-1].valid_data == TRUE) {
00430                 valid_ifu = TRUE;
00431             }
00432 
00433             /* Load noise anyway since we have to save it in the output */
00434             if (desc1.ex_noise) {
00435                 sub_header_noise = kmos_dfs_load_sub_header(op1_frame, devnr, 
00436                         TRUE);
00437                 KMO_TRY_EXIT_IF_NULL(sub_header_noise) ;
00438                 if (cpl_propertylist_has(sub_header_noise, CRPIX3))
00439                     cpl_propertylist_erase(sub_header_noise, CRPIX3);
00440                 if (cpl_propertylist_has(sub_header_noise, CRVAL3))
00441                     cpl_propertylist_erase(sub_header_noise, CRVAL3);
00442                 if (cpl_propertylist_has(sub_header_noise, CDELT3))
00443                     cpl_propertylist_erase(sub_header_noise, CDELT3);
00444                 if (cpl_propertylist_has(sub_header_noise, CTYPE3))
00445                     cpl_propertylist_erase(sub_header_noise, CTYPE3);
00446                 if (cpl_propertylist_has(sub_header_noise, CUNIT3))
00447                     cpl_propertylist_erase(sub_header_noise, CUNIT3);
00448                 if (cpl_propertylist_has(sub_header_noise, CD1_3))
00449                     cpl_propertylist_erase(sub_header_noise, CD1_3);
00450                 if (cpl_propertylist_has(sub_header_noise, CD2_3))
00451                     cpl_propertylist_erase(sub_header_noise, CD2_3);
00452                 if (cpl_propertylist_has(sub_header_noise, CD3_3))
00453                     cpl_propertylist_erase(sub_header_noise, CD3_3);
00454                 if (cpl_propertylist_has(sub_header_noise, CD3_2))
00455                     cpl_propertylist_erase(sub_header_noise, CD3_2);
00456                 if (cpl_propertylist_has(sub_header_noise, CD3_1))
00457                     cpl_propertylist_erase(sub_header_noise, CD3_1);
00458             }
00459 
00460             if (valid_ifu) {
00461                 /* Load data */
00462                 data_in = kmos_dfs_load_cube(op1_frame, devnr, FALSE) ;
00463                 KMO_TRY_EXIT_IF_NULL(data_in) ;
00464 
00465                 /* Load noise, if existing */
00466                 if (desc1.ex_noise && desc1.sub_desc[index_noise-1].valid_data){
00467                     noise_in = kmos_dfs_load_cube(op1_frame, devnr, TRUE) ;
00468                     KMO_TRY_EXIT_IF_NULL(noise_in) ;
00469                 }
00470 
00471                 /* Interpolate oh-lines to fit input data */
00472                 ifu_crpix = cpl_propertylist_get_double(sub_header_data,CRPIX3);
00473                 KMO_TRY_CHECK_ERROR_STATE_MSG("CRPIX3 is missing");
00474                 ifu_crval = cpl_propertylist_get_double(sub_header_data,CRVAL3);
00475                 KMO_TRY_CHECK_ERROR_STATE_MSG("CRVAL3 is missing");
00476                 ifu_cdelt = cpl_propertylist_get_double(sub_header_data,CDELT3);
00477                 KMO_TRY_CHECK_ERROR_STATE_MSG("CDELT3 is missing");
00478 
00479                 if (spec_data_in == NULL) {
00480                     identified_slices = kmo_identify_slices(ranges, ifu_crpix, 
00481                             ifu_crval, ifu_cdelt, desc1.naxis3);
00482                 } else {
00483                     identified_slices = kmo_identify_slices_with_oh(
00484                             spec_data_in, spec_lambda_in, ranges, threshold,
00485                             ifu_crpix, ifu_crval, ifu_cdelt, desc1.naxis3);
00486                 }
00487                 KMO_TRY_EXIT_IF_NULL(identified_slices) ;
00488 
00489                 if (cpl_propertylist_has(sub_header_data, CRPIX3))
00490                     cpl_propertylist_erase(sub_header_data, CRPIX3);
00491                 if (cpl_propertylist_has(sub_header_data, CRVAL3))
00492                     cpl_propertylist_erase(sub_header_data, CRVAL3);
00493                 if (cpl_propertylist_has(sub_header_data, CDELT3))
00494                     cpl_propertylist_erase(sub_header_data, CDELT3);
00495                 if (cpl_propertylist_has(sub_header_data, CTYPE3))
00496                     cpl_propertylist_erase(sub_header_data, CTYPE3);
00497                 if (cpl_propertylist_has(sub_header_data, CUNIT3))
00498                     cpl_propertylist_erase(sub_header_data, CUNIT3);
00499                 if (cpl_propertylist_has(sub_header_data, CD1_3))
00500                     cpl_propertylist_erase(sub_header_data, CD1_3);
00501                 if (cpl_propertylist_has(sub_header_data, CD2_3))
00502                     cpl_propertylist_erase(sub_header_data, CD2_3);
00503                 if (cpl_propertylist_has(sub_header_data, CD3_3))
00504                     cpl_propertylist_erase(sub_header_data, CD3_3);
00505                 if (cpl_propertylist_has(sub_header_data, CD3_2))
00506                     cpl_propertylist_erase(sub_header_data, CD3_2);
00507                 if (cpl_propertylist_has(sub_header_data, CD3_1))
00508                     cpl_propertylist_erase(sub_header_data, CD3_1);
00509 
00510                 /* Process & save data */
00511                 KMO_TRY_EXIT_IF_ERROR(kmclipm_make_image(data_in, noise_in,
00512                             &data_out, &noise_out, identified_slices, cmethod,
00513                             cpos_rej, cneg_rej, citer, cmax, cmin));
00514 
00515                 KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(data_out, MAKE_IMAGE,
00516                             "", sub_header_data, 0./0.));
00517 
00518                 /* Process & save noise, if existing */
00519                 if (desc1.ex_noise) {
00520                     KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_image(noise_out, 
00521                                 MAKE_IMAGE, "", sub_header_noise, 0./0.));
00522                 }
00523 
00524                 /* Free memory */
00525                 cpl_imagelist_delete(data_in); data_in = NULL;
00526                 cpl_imagelist_delete(noise_in); noise_in = NULL;
00527                 cpl_image_delete(data_out); data_out = NULL;
00528                 cpl_image_delete(noise_out); noise_out = NULL;
00529                 cpl_vector_delete(identified_slices); identified_slices = NULL;
00530             } else {
00531                 if (cpl_propertylist_has(sub_header_data, CRPIX3))
00532                     cpl_propertylist_erase(sub_header_data, CRPIX3);
00533                 if (cpl_propertylist_has(sub_header_data, CRVAL3))
00534                     cpl_propertylist_erase(sub_header_data, CRVAL3);
00535                 if (cpl_propertylist_has(sub_header_data, CDELT3))
00536                     cpl_propertylist_erase(sub_header_data, CDELT3);
00537                 if (cpl_propertylist_has(sub_header_data, CTYPE3))
00538                     cpl_propertylist_erase(sub_header_data, CTYPE3);
00539                 if (cpl_propertylist_has(sub_header_data, CUNIT3))
00540                     cpl_propertylist_erase(sub_header_data, CUNIT3);
00541                 if (cpl_propertylist_has(sub_header_data, CD1_3))
00542                     cpl_propertylist_erase(sub_header_data, CD1_3);
00543                 if (cpl_propertylist_has(sub_header_data, CD2_3))
00544                     cpl_propertylist_erase(sub_header_data, CD2_3);
00545                 if (cpl_propertylist_has(sub_header_data, CD3_3))
00546                     cpl_propertylist_erase(sub_header_data, CD3_3);
00547                 if (cpl_propertylist_has(sub_header_data, CD3_2))
00548                     cpl_propertylist_erase(sub_header_data, CD3_2);
00549                 if (cpl_propertylist_has(sub_header_data, CD3_1))
00550                     cpl_propertylist_erase(sub_header_data, CD3_1);
00551 
00552                 // invalid IFU, just save sub_headers
00553                  KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_sub_header(MAKE_IMAGE, "", 
00554                              sub_header_data));
00555 
00556                  if (desc1.ex_noise) {
00557                      KMO_TRY_EXIT_IF_ERROR(kmo_dfs_save_sub_header(MAKE_IMAGE, 
00558                                  "", sub_header_noise));
00559                  }
00560             }
00561 
00562             // free memory
00563             cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00564             cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00565         }
00566     }
00567     KMO_CATCH
00568     {
00569         KMO_CATCH_MSG();
00570         ret_val = -1;
00571     }
00572 
00573     kmo_free_fits_desc(&desc1);
00574     kmo_free_fits_desc(&desc2);
00575     cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00576     cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00577     cpl_propertylist_delete(spec_header); spec_header = NULL;
00578     cpl_imagelist_delete(data_in); data_in = NULL;
00579     cpl_imagelist_delete(noise_in); noise_in = NULL;
00580     cpl_image_delete(data_out); data_out = NULL;
00581     cpl_image_delete(noise_out); noise_out = NULL;
00582     cpl_vector_delete(spec_data_in); spec_data_in = NULL;
00583     cpl_vector_delete(spec_lambda_in); spec_lambda_in = NULL;
00584     cpl_vector_delete(ranges); ranges = NULL;
00585 
00586     return ret_val;
00587 }
00588