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