KMOS Pipeline Reference Manual  1.0.7
kmo_fit_profile.c
00001 /* $Id: kmo_fit_profile.c,v 1.8 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.8 $
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_priv_fit_profile.h"
00043 #include "kmo_priv_functions.h"
00044 #include "kmo_dfs.h"
00045 #include "kmo_error.h"
00046 #include "kmo_constants.h"
00047 #include "kmo_debug.h"
00048 
00049 /*-----------------------------------------------------------------------------
00050  *                          Functions prototypes
00051  *----------------------------------------------------------------------------*/
00052 
00053 static int kmo_fit_profile_create(cpl_plugin *);
00054 static int kmo_fit_profile_exec(cpl_plugin *);
00055 static int kmo_fit_profile_destroy(cpl_plugin *);
00056 static int kmo_fit_profile(cpl_parameterlist *, cpl_frameset *);
00057 
00058 /*-----------------------------------------------------------------------------
00059  *                          Static variables
00060  *----------------------------------------------------------------------------*/
00061 
00062 static char kmo_fit_profile_description[] =
00063 "This recipe creates either spectral or spatial profiles of sources using dif-\n"
00064 "ferent functions to fit. Spectral profiles can be created for F1I frames (if\n"
00065 "WCS is defined in the input frame, the output parameters are in respect to the\n"
00066 "defined WCS).\n"
00067 "Spatial profiles can be created for F2I frames (any WCS information is ignored\n"
00068 "here).\n"
00069 "If the frames contain no noise information, constant noise is assumed for the\n"
00070 "fitting procedure.\n"
00071 "\n"
00072 "BASIC PARAMETERS:\n"
00073 "-----------------\n"
00074 "--method\n"
00075 "F1I frames can be fitted using either 'gauss', 'moffat' or 'lorentz' function.\n"
00076 "F2I frames can be fitted using either 'gauss' or 'moffat' function.\n"
00077 "\n"
00078 "ADVANCED PARAMETERS\n"
00079 "-------------------\n"
00080 "--range\n"
00081 "For F1I frames the spectral range can be defined. With available WCS informa-\n"
00082 "tion the range can be provided in units (e.g. “1.2;1.5”), otherwise in pixels\n"
00083 "(e.g. “112;224).\n"
00084 "For F2I frames the spatial range can be defined as follow: “x1,x2;y1,y2”\n"
00085 "\n"
00086 "-------------------------------------------------------------------------------\n"
00087 "  Input files:\n"
00088 "\n"
00089 "   DO                    KMOS                                                  \n"
00090 "   category              Type   Explanation                    Required #Frames\n"
00091 "   --------              -----  -----------                    -------- -------\n"
00092 "   <none or any>         F1I    Vector with or                     Y       1   \n"
00093 "                                without noise frame                            \n"
00094 "   or                                                                          \n"
00095 "   <none or any>         F2I    Image with or                      Y       1   \n"
00096 "                                without noise frame                            \n"
00097 "\n"
00098 "  Output files:\n"
00099 "\n"
00100 "   DO                    KMOS\n"
00101 "   category              Type   Explanation\n"
00102 "   --------              -----  -----------\n"
00103 "   FIT_PROFILE           F1I    Fitted profile (without noise frame)\n"
00104 "                         or     (3 Extensions)                      \n"
00105 "                         F2I                                        \n"
00106 "-------------------------------------------------------------------------------\n"
00107 "\n";
00108 
00109 /*-----------------------------------------------------------------------------
00110  *                              Functions code
00111  *----------------------------------------------------------------------------*/
00112 
00129 int cpl_plugin_get_info(cpl_pluginlist *list)
00130 {
00131     cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
00132     cpl_plugin *plugin = &recipe->interface;
00133 
00134     cpl_plugin_init(plugin,
00135                         CPL_PLUGIN_API,
00136                         KMOS_BINARY_VERSION,
00137                         CPL_PLUGIN_TYPE_RECIPE,
00138                         "kmo_fit_profile",
00139                         "Fit spectral line profiles as well as spatial profiles"
00140                         " with a simple function - for example to measure "
00141                         "resolution or find the centre of a source",
00142                         kmo_fit_profile_description,
00143                         "Alex Agudo Berbel",
00144                         "agudo@mpe.mpg.de",
00145                         kmos_get_license(),
00146                         kmo_fit_profile_create,
00147                         kmo_fit_profile_exec,
00148                         kmo_fit_profile_destroy);
00149 
00150     cpl_pluginlist_append(list, plugin);
00151 
00152     return 0;
00153 }
00154 
00162 static int kmo_fit_profile_create(cpl_plugin *plugin)
00163 {
00164     cpl_recipe *recipe;
00165     cpl_parameter *p;
00166 
00167     /* Check that the plugin is part of a valid recipe */
00168     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00169         recipe = (cpl_recipe *)plugin;
00170     else
00171         return -1;
00172 
00173     /* Create the parameters list in the cpl_recipe object */
00174     recipe->parameters = cpl_parameterlist_new();
00175 
00176     /* Fill the parameters list */
00177     /* --method */
00178     p = cpl_parameter_new_value("kmos.kmo_fit_profile.method",
00179                                 CPL_TYPE_STRING,
00180                                 "Either fit \"gauss\", \"moffat\" or "
00181                                 "\"lorentz\" for 1D data."
00182                                 "Either fit \"gauss\" or \"moffat\" for "
00183                                 "2D data. ",
00184                                 "kmos.kmo_fit_profile",
00185                                 "gauss");
00186     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "method");
00187     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00188     cpl_parameterlist_append(recipe->parameters, p);
00189 
00190     /* --range */
00191     p = cpl_parameter_new_value("kmos.kmo_fit_profile.range",
00192                                 CPL_TYPE_STRING,
00193                                 "The spectral or spatial range to combine. "
00194                                 "Default is the whole range. "
00195                                 "e.g. F1I: \"0.5,2.1\" (microns), "
00196                                 "e.g. F2I: \"1,7;3,10\" (pixels: x1,x2;y1,y2), "
00197                                 "pixels are counted from 1.",
00198                                 "kmos.kmo_fit_profile",
00199                                 "");
00200     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "range");
00201     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00202     cpl_parameterlist_append(recipe->parameters, p);
00203 
00204     return 0;
00205 }
00206 
00212 static int kmo_fit_profile_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_fit_profile(recipe->parameters, recipe->frames);
00222 }
00223 
00229 static int kmo_fit_profile_destroy(cpl_plugin *plugin)
00230 {
00231     cpl_recipe *recipe;
00232 
00233     /* Get the recipe out of the plugin */
00234     if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
00235         recipe = (cpl_recipe *)plugin;
00236     else return -1 ;
00237 
00238     cpl_parameterlist_delete(recipe->parameters);
00239     return 0 ;
00240 }
00241 
00256 static int kmo_fit_profile(cpl_parameterlist *parlist, cpl_frameset *frameset)
00257 {
00258     cpl_image       *data_img_in            = NULL,
00259                     *data_img_in2           = NULL,
00260                     *data_img_out           = NULL,
00261                     *noise_img_in           = NULL,
00262                     *noise_img_in2          = NULL;
00263 
00264     cpl_vector      *data_vec_in            = NULL,
00265                     *data_vec_out           = NULL,
00266                     *noise_vec_in           = NULL,
00267                     *ranges                 = NULL,
00268                     *ranges2                = NULL,
00269                     *fit_par                = NULL,
00270                     *lambda_vec             = NULL,
00271                     *lambda_vec2            = NULL,
00272                     *data_vec2              = NULL,
00273                     *noise_vec2             = NULL;
00274 
00275     cpl_frame        *frame                 = NULL;
00276 
00277     int              ret_val                = 0,
00278                      nr_devices             = 0,
00279                      i                      = 0,
00280                      j                      = 0,
00281                      x1                     = 0,
00282                      x2                     = 0,
00283                      y1                     = 0,
00284                      y2                     = 0,
00285                      valid_ifu              = FALSE,
00286                      devnr                  = 0,
00287                      index_data             = 0,
00288                      index_noise            = 0;
00289 
00290     double           crpix1                 = 0.0,
00291                      crval1                 = 0.0,
00292                      cdelt1                 = 0.0,
00293                      *pranges               = NULL;
00294 
00295     const char       *ranges_txt            = NULL,
00296                      *method                = NULL;
00297 
00298     cpl_propertylist *sub_header_data       = NULL,
00299                      *sub_header_noise      = NULL,
00300                      *pl                    = NULL;
00301 
00302     main_fits_desc   desc;
00303 
00304     KMO_TRY
00305     {
00306         kmo_init_fits_desc(&desc);
00307 
00308         /* --- check input --- */
00309         KMO_TRY_ASSURE((parlist != NULL) &&
00310                        (frameset != NULL),
00311                        CPL_ERROR_NULL_INPUT,
00312                        "Not all input data is provided!");
00313 
00314         KMO_TRY_ASSURE(cpl_frameset_get_size(frameset) == 1,
00315                        CPL_ERROR_NULL_INPUT,
00316                        "A fits-file must be provided!");
00317 
00318         KMO_TRY_EXIT_IF_NULL(
00319             frame = kmo_dfs_get_frame(frameset, "0"));
00320 
00321         /* load descriptor */
00322         desc = kmo_identify_fits_header(
00323                     cpl_frame_get_filename(frame));
00324         KMO_TRY_CHECK_ERROR_STATE();
00325 
00326         KMO_TRY_ASSURE((desc.fits_type == f2i_fits) ||
00327                        (desc.fits_type == f1i_fits),
00328                        CPL_ERROR_ILLEGAL_INPUT,
00329                        "DATA isn't in the correct format (either F2I or F1I)!");
00330 
00331         KMO_TRY_ASSURE(kmo_dfs_set_groups(frameset, "kmo_fit_profile") == 1,
00332                        CPL_ERROR_ILLEGAL_INPUT,
00333                        "Cannot identify RAW and CALIB frames!");
00334 
00335         /* --- get parameters --- */
00336         cpl_msg_info(cpl_func, "--- Parameter setup for kmo_fit_profile ---");
00337 
00338         KMO_TRY_EXIT_IF_NULL(
00339             method = kmo_dfs_get_parameter_string(parlist,
00340                                            "kmos.kmo_fit_profile.method"));
00341         KMO_TRY_EXIT_IF_ERROR(
00342             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fit_profile.method"));
00343 
00344         ranges_txt = kmo_dfs_get_parameter_string(parlist,
00345                                                   "kmos.kmo_fit_profile.range");
00346         KMO_TRY_CHECK_ERROR_STATE();
00347         KMO_TRY_EXIT_IF_ERROR(
00348             kmo_dfs_print_parameter_help(parlist, "kmos.kmo_fit_profile.range"));
00349 
00350         cpl_msg_info("", "-------------------------------------------");
00351 
00352         if (strcmp(ranges_txt, "") != 0) {
00353 
00354             ranges = kmo_identify_ranges(ranges_txt);
00355             KMO_TRY_CHECK_ERROR_STATE();
00356 
00357             KMO_TRY_EXIT_IF_NULL(
00358                 pranges = cpl_vector_get_data(ranges));
00359 
00360             KMO_TRY_ASSURE((pranges[0] < pranges[1]),
00361                            CPL_ERROR_ILLEGAL_INPUT,
00362                            "x1 must be smaller than x2!");
00363 
00364             KMO_TRY_ASSURE((((desc.fits_type == f2i_fits) &&
00365                              (cpl_vector_get_size(ranges) == 4) ) || (
00366                              (desc.fits_type == f1i_fits) &&
00367                              (cpl_vector_get_size(ranges) == 2) )),
00368                      CPL_ERROR_ILLEGAL_INPUT,
00369                      "'range' must contain 2 values for F1I and "
00370                      "4 values for F2I!");
00371 
00372             if (desc.fits_type == f2i_fits) {
00373                 x1 = pranges[0];
00374                 x2 = pranges[1];
00375                 y1 = pranges[2];
00376                 y2 = pranges[3];
00377 
00378                 KMO_TRY_ASSURE((x1 > 0) &&
00379                                (y1 > 0) &&
00380                                (x2 < desc.naxis1) &&
00381                                (y2 < desc.naxis2),
00382                      CPL_ERROR_ILLEGAL_INPUT,
00383                      "Provided range is larger than images in F2I!");
00384 
00385                 KMO_TRY_ASSURE(y1 < y2,
00386                      CPL_ERROR_ILLEGAL_INPUT,
00387                      "y1 must be smaller than y2!");
00388 
00389             } else {
00390                 // for F1I-files this will be done individually for each
00391                 // extension.
00392             }
00393         } else {
00394             if (desc.fits_type == f2i_fits) {
00395                 x1 = 1;
00396                 x2 = desc.naxis1;
00397                 y1 = 1;
00398                 y2 = desc.naxis2;
00399             } else {
00400                 ranges = cpl_vector_new(2);
00401                 cpl_vector_set(ranges, 0, 1);
00402                 cpl_vector_set(ranges, 1, desc.naxis1);
00403             }
00404         }
00405 
00406         /* --- load & save primary header --- */
00407         KMO_TRY_EXIT_IF_ERROR(
00408             kmo_dfs_save_main_header(frameset, FIT_PROFILE, "", frame,
00409                                      NULL, parlist, cpl_func));
00410 
00411         /* --- load data --- */
00412         if (desc.ex_noise == TRUE) {
00413             nr_devices = desc.nr_ext / 2;
00414         } else {
00415             nr_devices = desc.nr_ext;
00416         }
00417 
00418         for (i = 1; i <= nr_devices; i++) {
00419             if (desc.ex_noise == FALSE) {
00420                 devnr = desc.sub_desc[i - 1].device_nr;
00421             } else {
00422                 devnr = desc.sub_desc[2 * i - 1].device_nr;
00423             }
00424 
00425             if (desc.ex_badpix == FALSE) {
00426                 index_data = kmo_identify_index_desc(desc, devnr, FALSE);
00427             } else {
00428                 index_data = kmo_identify_index_desc(desc, devnr, 2);
00429             }
00430             KMO_TRY_CHECK_ERROR_STATE();
00431 
00432             if (desc.ex_noise) {
00433                 index_noise = kmo_identify_index_desc(desc, devnr, TRUE);
00434             }
00435             KMO_TRY_CHECK_ERROR_STATE();
00436 
00437             KMO_TRY_EXIT_IF_NULL(
00438                 sub_header_data = kmo_dfs_load_sub_header(frameset, "0", devnr,
00439                                                           FALSE));
00440 
00441             // check if IFU is valid
00442             valid_ifu = FALSE;
00443             if (desc.sub_desc[index_data-1].valid_data == TRUE) {
00444                 valid_ifu = TRUE;
00445             }
00446 
00447             if (desc.ex_noise) {
00448                 // load noise anyway since we have to save it in the output
00449                 KMO_TRY_EXIT_IF_NULL(
00450                     sub_header_noise = kmo_dfs_load_sub_header(frameset, "0",
00451                                                                devnr, TRUE));
00452             }
00453 
00454             if (valid_ifu) {
00455                 if (desc.fits_type == f2i_fits) {
00456                     //
00457                     // process images
00458                     //
00459 
00460                     // load data
00461                     KMO_TRY_EXIT_IF_NULL(
00462                         data_img_in = kmo_dfs_load_image(frameset, "0",
00463                                                          devnr, FALSE, FALSE, NULL));
00464 
00465                     KMO_TRY_EXIT_IF_NULL(
00466                         data_img_in2 = cpl_image_extract(data_img_in,
00467                                                          x1, y1, x2, y2));
00468 
00469                     // load noise, if existing
00470                     if (desc.ex_noise && desc.sub_desc[index_noise-1].valid_data) {
00471                         KMO_TRY_EXIT_IF_NULL(
00472                             noise_img_in = kmo_dfs_load_image(frameset, "0",
00473                                                               devnr, TRUE, FALSE, NULL));
00474 
00475                         KMO_TRY_EXIT_IF_NULL(
00476                             noise_img_in2 = cpl_image_extract(noise_img_in,
00477                                                               x1, y1, x2, y2));
00478                     }
00479 
00480                     // process data
00481                     KMO_TRY_EXIT_IF_NULL(
00482                         fit_par = kmo_fit_profile_2D(data_img_in2,
00483                                                      noise_img_in2,
00484                                                      method,
00485                                                      &data_img_out,
00486                                                      &pl));
00487                     cpl_vector_delete(fit_par); fit_par = NULL;
00488 
00489                     // update subheader with fit parameters
00490                     KMO_TRY_EXIT_IF_ERROR(
00491                         cpl_propertylist_append(sub_header_data, pl));
00492 
00493                     /* save data  (noise is omitted for the fitted data)*/
00494                     KMO_TRY_EXIT_IF_ERROR(
00495                         kmo_dfs_save_image(data_img_out, FIT_PROFILE, "",
00496                                            sub_header_data, 0./0.));
00497 
00498                     /* free memory */
00499                     cpl_image_delete(data_img_in); data_img_in = NULL;
00500                     cpl_image_delete(data_img_in2); data_img_in2 = NULL;
00501                     cpl_image_delete(data_img_out); data_img_out = NULL;
00502                     cpl_image_delete(noise_img_in); noise_img_in = NULL;
00503                     cpl_image_delete(noise_img_in2); noise_img_in2 = NULL;
00504                 } else {
00505                     //
00506                     // process vectors
00507                     //
00508 
00509                     // load data
00510 kmclipm_vector *ddd = NULL;
00511                     KMO_TRY_EXIT_IF_NULL(
00512                         ddd = kmo_dfs_load_vector(frameset, "0",
00513                                                   devnr, FALSE));
00514 data_vec_in = kmclipm_vector_create_non_rejected(ddd);
00515 kmclipm_vector_delete(ddd); ddd = NULL;
00516 
00517                     // extract CRVAL, CRPIX and CDELT to convert the ranges-
00518                     // vector from spectral- to pixel-space
00519                     if (cpl_propertylist_has(sub_header_data, CRPIX1) &&
00520                         cpl_propertylist_has(sub_header_data, CRVAL1) &&
00521                         cpl_propertylist_has(sub_header_data, CDELT1))
00522                     {
00523                         crpix1 = cpl_propertylist_get_double(sub_header_data,
00524                                                                 CRPIX1);
00525                         crval1 = cpl_propertylist_get_double(sub_header_data,
00526                                                                 CRVAL1);
00527                         cdelt1 = cpl_propertylist_get_double(sub_header_data,
00528                                                                 CDELT1);
00529 
00530                         if (strcmp(ranges_txt, "") == 0) {
00531                             cpl_vector_set(ranges, 0,
00532                                 crpix1*crval1 +
00533                                     cdelt1*(cpl_vector_get(ranges,0)-1));
00534                             cpl_vector_set(ranges, 1,
00535                                 crpix1*crval1 +
00536                                     cdelt1*(cpl_vector_get(ranges,1)-1));
00537                         }
00538                     } else {
00539                         // set crpix1 to 2 because the output position should
00540                         // be zero-based
00541                         // (like in the cpl_vector definition)
00542 //                        crpix1 = 2;
00543                         crpix1 = 1;
00544                         crval1 = 1;
00545                         cdelt1 = 1;
00546                     }
00547 
00548                     // ranges2 will have the same size as the input spectra
00549                     // and will contain zeros for positions outside the provided
00550                     // spectral range and ones for values inside
00551                     KMO_TRY_EXIT_IF_NULL(
00552                         ranges2 = kmo_identify_slices(ranges,
00553                                                   crpix1,
00554                                                   crval1,
00555                                                   cdelt1,
00556                                                   desc.naxis1));
00557                     KMO_TRY_EXIT_IF_NULL(
00558                         pranges = cpl_vector_get_data(ranges2));
00559 
00560                     x1 = -1; x2 = -1;
00561                     for (j = 0; j < cpl_vector_get_size(ranges2); j++) {
00562                         if ((pranges[j] == 1) && (x1 == -1)) {
00563                             x1 = j;
00564                         }
00565                         if ((pranges[j] == 1) && (x1 != -1)) {
00566                             x2 = j;
00567                         }
00568                     }
00569                     cpl_vector_delete(ranges2); ranges2 = NULL;
00570 
00571                     // create lambda-vector for IFU
00572                     KMO_TRY_EXIT_IF_NULL(
00573                         lambda_vec = kmo_create_lambda_vec(desc.naxis1,
00574                                                            crpix1,
00575                                                            crval1,
00576                                                            cdelt1));
00577 
00578                     KMO_TRY_EXIT_IF_NULL(
00579                         lambda_vec2 = cpl_vector_extract(lambda_vec, x1, x2, 1));
00580 
00581                     KMO_TRY_EXIT_IF_NULL(
00582                         data_vec2 = cpl_vector_extract(data_vec_in, x1, x2, 1));
00583 
00584                     // load noise, if existing and
00585                     // extract same range as with data
00586                     if (desc.ex_noise  && desc.sub_desc[index_noise-1].valid_data) {
00587                         KMO_TRY_EXIT_IF_NULL(
00588                             ddd = kmo_dfs_load_vector(frameset, "0",
00589                                                       devnr, TRUE));
00590 noise_vec_in = kmclipm_vector_create_non_rejected(ddd);
00591 kmclipm_vector_delete(ddd); ddd =NULL;
00592 
00593                         KMO_TRY_EXIT_IF_NULL(
00594                             noise_vec2 = cpl_vector_extract(noise_vec_in,
00595                                                                x1, x2, 1));
00596                     }
00597 
00598                     // process data
00599                     KMO_TRY_EXIT_IF_NULL(
00600                         fit_par = kmo_fit_profile_1D(lambda_vec2,
00601                                                      data_vec2,
00602                                                      noise_vec2,
00603                                                      method,
00604                                                      &data_vec_out,
00605                                                      &pl));
00606 
00607                     cpl_vector_delete(fit_par); fit_par = NULL;
00608 
00609                     // update CRPIX if WCS information is available
00610                     if (cpl_propertylist_has(sub_header_data, CRPIX1) &&
00611                         cpl_propertylist_has(sub_header_data, CRVAL1) &&
00612                         cpl_propertylist_has(sub_header_data, CDELT1))
00613                     {
00614                         KMO_TRY_EXIT_IF_ERROR(
00615                             kmclipm_update_property_double(sub_header_data,
00616                                                            CRPIX1,
00617                                                            crpix1-x1,
00618                                                "[pix] Reference pixel in x"));
00619 
00620                         if (desc.ex_noise) {
00621                             KMO_TRY_EXIT_IF_ERROR(
00622                                 kmclipm_update_property_double(sub_header_noise,
00623                                                                CRPIX1,
00624                                                                crpix1-x1,
00625                                                "[pix] Reference pixel in x"));
00626                         }
00627                     }
00628 
00629                     // append fit parameters and errors
00630                     KMO_TRY_EXIT_IF_ERROR(
00631                         cpl_propertylist_append(sub_header_data, pl));
00632 
00633                     // save data  (noise is omitted for the fitted data)
00634 ddd = kmclipm_vector_create(cpl_vector_duplicate(data_vec_out));
00635                     KMO_TRY_EXIT_IF_ERROR(
00636                         kmo_dfs_save_vector(ddd, FIT_PROFILE, "",
00637                                            sub_header_data, 0./0.));
00638 kmclipm_vector_delete(ddd); ddd = NULL;
00639 
00640                     // free memory
00641                     cpl_vector_delete(data_vec_in); data_vec_in = NULL;
00642                     cpl_vector_delete(data_vec_out); data_vec_out = NULL;
00643                     cpl_vector_delete(noise_vec_in); noise_vec_in = NULL;
00644                     cpl_vector_delete(noise_vec2); noise_vec2 = NULL;
00645                     cpl_vector_delete(lambda_vec); lambda_vec = NULL;
00646                     cpl_vector_delete(lambda_vec2); lambda_vec2 = NULL;
00647                     cpl_vector_delete(data_vec2); data_vec2 = NULL;
00648                 }
00649 
00650                 cpl_propertylist_delete(pl); pl = NULL;
00651             } else {
00652                 // invalid IFU, just save sub_headers */
00653                 KMO_TRY_EXIT_IF_ERROR(
00654                     kmo_dfs_save_sub_header(FIT_PROFILE, "", sub_header_data));
00655 
00656                 if (desc.ex_noise) {
00657                     KMO_TRY_EXIT_IF_ERROR(
00658                         kmo_dfs_save_sub_header(FIT_PROFILE, "", sub_header_noise));
00659                 }
00660             }
00661 
00662             // free memory
00663             cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00664             cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00665         }
00666     }
00667     KMO_CATCH
00668     {
00669         KMO_CATCH_MSG();
00670         ret_val = -1;
00671     }
00672 
00673     kmo_free_fits_desc(&desc);
00674     cpl_image_delete(data_img_in); data_img_in = NULL;
00675     cpl_image_delete(data_img_in2); data_img_in2 = NULL;
00676     cpl_image_delete(data_img_out); data_img_out = NULL;
00677     cpl_image_delete(noise_img_in); noise_img_in = NULL;
00678     cpl_image_delete(noise_img_in2); noise_img_in2 = NULL;
00679     cpl_vector_delete(data_vec_in); data_vec_in = NULL;
00680     cpl_vector_delete(data_vec2); data_vec2 = NULL;
00681     cpl_vector_delete(data_vec_out); data_vec_out = NULL;
00682     cpl_vector_delete(noise_vec_in); noise_vec_in = NULL;
00683     cpl_vector_delete(noise_vec2); noise_vec2 = NULL;
00684     cpl_vector_delete(lambda_vec); lambda_vec = NULL;
00685     cpl_vector_delete(lambda_vec2); lambda_vec2 = NULL;
00686     cpl_vector_delete(fit_par); fit_par = NULL;
00687     cpl_vector_delete(ranges); ranges = NULL;
00688     cpl_vector_delete(ranges2); ranges2 = NULL;
00689     cpl_propertylist_delete(sub_header_data); sub_header_data = NULL;
00690     cpl_propertylist_delete(sub_header_noise); sub_header_noise = NULL;
00691 
00692     return ret_val;
00693 }
00694