naco_img_detlin.c

00001 /* $Id: naco_img_detlin.c,v 1.41 2009/01/29 08:54:58 llundin Exp $
00002  *
00003  * This file is part of the NACO 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., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2009/01/29 08:54:58 $
00024  * $Revision: 1.41 $
00025  * $Name: naco-4_3_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "naco_recipe.h"
00037 
00038 /*-----------------------------------------------------------------------------
00039                                 Define
00040  -----------------------------------------------------------------------------*/
00041 
00042 #define RECIPE_STRING "naco_img_detlin"
00043 
00044 #define DETLIN_LIMIT        0.75 
00045 #define DETLIN_STABILITY    1/100.0
00046 
00047 #define DETLIN_MAX_GRAD 1.5  /* Maximum gradient */
00048 #define DETLIN_MAX_RESI 10.0 /* Maximum residual */
00049 
00050 /*-----------------------------------------------------------------------------
00051                             Private Functions prototypes
00052  -----------------------------------------------------------------------------*/
00053 
00054 static cpl_error_code naco_img_detlin_load(cpl_imagelist *, cpl_vector *,
00055                                            const cpl_parameterlist *,
00056                                            const irplib_framelist *,
00057                                            const irplib_framelist *);
00058 
00059 static cpl_image * naco_img_detlin_limit(const cpl_imagelist *);
00060 static cpl_image * naco_img_detlin_bpm(const cpl_imagelist *,
00061                                        const cpl_vector *,
00062                                        const cpl_image *);
00063 
00064 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector *);
00065 
00066 static cpl_error_code naco_img_detlin_save(cpl_frameset *,
00067                                            const cpl_parameterlist *,
00068                                            const cpl_propertylist *,
00069                                            const cpl_imagelist *,
00070                                            const cpl_image *,
00071                                            const cpl_image *);
00072 
00073 static cpl_imagelist * naco_imagelist_fit_polynomial(const cpl_imagelist *,
00074                                                      const double *, int);
00075 
00076 NACO_RECIPE_DEFINE(naco_img_detlin,
00077                    NACO_PARAM_FORCE,
00078                    "Detector linearity recipe",
00079                    RECIPE_STRING " -- NACO imaging detector linearity recipe.\n"
00080                    "The Set Of Frames (sof-file) must specify at least three "
00081                    "pairs of files which must be tagged\n"
00082                    "NACO-raw-file.fits " NACO_IMG_DETLIN_LAMP " and\n"
00083                    "NACO-raw-file.fits " NACO_IMG_DETLIN_DARK "\n");
00084 
00085 /*----------------------------------------------------------------------------*/
00089 /*----------------------------------------------------------------------------*/
00090 
00091 /*-----------------------------------------------------------------------------
00092                                 Functions code
00093  -----------------------------------------------------------------------------*/
00094 
00095 /*----------------------------------------------------------------------------*/
00102 /*----------------------------------------------------------------------------*/
00103 static int naco_img_detlin(cpl_frameset            * framelist,
00104                            const cpl_parameterlist * parlist)
00105 {
00106     irplib_framelist * allframes  = NULL;
00107     irplib_framelist * darkframes = NULL;
00108     irplib_framelist * lampframes = NULL;
00109     cpl_propertylist * qclist     = cpl_propertylist_new();
00110     const cpl_propertylist * reflist;
00111     cpl_imagelist    * iset = cpl_imagelist_new();
00112     cpl_image        * lin_limit = NULL;
00113     cpl_vector       * ditval = cpl_vector_new(4); /* 4 is minimum */
00114     cpl_imagelist    * fitres = NULL;
00115     cpl_image        * bpm = NULL;
00116     cpl_image        * residual = NULL;
00117 
00118 
00119     /* Identify the RAW and CALIB frames in the input frameset */
00120     skip_if (naco_dfs_set_groups(framelist));
00121  
00122     allframes = irplib_framelist_cast(framelist);
00123     skip_if(allframes == NULL);
00124 
00125     darkframes = irplib_framelist_extract(allframes, NACO_IMG_DETLIN_DARK);
00126     skip_if (darkframes == NULL);
00127    
00128     lampframes = irplib_framelist_extract(allframes, NACO_IMG_DETLIN_LAMP);
00129     skip_if (lampframes == NULL);
00130 
00131     /* Load the data and check the DIT consistency */
00132     cpl_msg_info(cpl_func, "Load the data");
00133     skip_if( irplib_framelist_load_propertylist(lampframes, 0, 0, "^("
00134                                                 NACO_PFITS_REGEXP_DETLIN_FIRST
00135                                                 ")$", CPL_FALSE));
00136 
00137     skip_if(irplib_framelist_load_propertylist_all(lampframes, 0, "^("
00138                                                    NACO_PFITS_REGEXP_DETLIN
00139                                                    ")$",
00140                                                    CPL_FALSE));
00141 
00142     skip_if(irplib_framelist_load_propertylist_all(darkframes, 0, "^("
00143                                                    NACO_PFITS_REGEXP_DETLIN
00144                                                    ")$", CPL_FALSE));
00145 
00146     skip_if (naco_img_detlin_load(iset, ditval, parlist, lampframes,
00147                                   darkframes));
00148 
00149     reflist = irplib_framelist_get_propertylist_const(lampframes, 0);
00150     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00151                                                   NACO_PFITS_REGEXP_DETLIN_COPY
00152                                                   ")$", 0));
00153 
00154     irplib_framelist_delete(lampframes);
00155     lampframes = NULL;
00156     irplib_framelist_delete(darkframes);
00157     darkframes = NULL;
00158    
00159     /* Compute the linearity limit */
00160     cpl_msg_info(cpl_func, "Compute the linearity limit");
00161     lin_limit = naco_img_detlin_limit(iset);
00162     skip_if (lin_limit == NULL);
00163 
00164     /* Compute the linearity coefficients */
00165     cpl_msg_info(cpl_func, "Compute the linearity coefficients");
00166 #if defined USE_CPL_FIT_IMAGELIST_POLYNOMIAL
00167     residual = cpl_image_new(cpl_image_get_size_x(lin_limit),
00168                              cpl_image_get_size_y(lin_limit),
00169                              CPL_TYPE_FLOAT);
00170     bug_if(0);
00171     cpl_vector_dump(ditval, stderr);
00172     fitres = cpl_fit_imagelist_polynomial(ditval, iset, 1, 4, CPL_FALSE,
00173                                           CPL_TYPE_FLOAT, residual);
00174     skip_if (fitres == NULL);
00175 
00176     bug_if (cpl_imagelist_set(fitres, residual, 4));
00177     residual = NULL;
00178 #else
00179     fitres = naco_imagelist_fit_polynomial(iset, cpl_vector_get_data(ditval), 4);
00180     skip_if (fitres == NULL);
00181 #endif
00182 
00183     /* Compute the bad pixels map */
00184     cpl_msg_info(cpl_func, "Compute the bad pixels map");
00185     skip_if (naco_img_detlin_dit_diff(ditval));
00186     bpm = naco_img_detlin_bpm(iset, ditval, cpl_imagelist_get(fitres, 4));
00187     cpl_imagelist_delete(iset);
00188     iset = NULL;
00189 
00190     skip_if (bpm==NULL);
00191 
00192     /* Save the products */
00193     cpl_msg_info(cpl_func, "Save the products");
00194     skip_if (naco_img_detlin_save(framelist, parlist, qclist, fitres,
00195                                   lin_limit, bpm));
00196 
00197     end_skip;
00198 
00199     irplib_framelist_delete(allframes);
00200     irplib_framelist_delete(lampframes);
00201     irplib_framelist_delete(darkframes);
00202     cpl_image_delete(lin_limit);
00203     cpl_image_delete(residual);
00204     cpl_imagelist_delete(fitres);
00205     cpl_image_delete(bpm);
00206     cpl_imagelist_delete(iset);
00207     cpl_vector_delete(ditval);
00208     cpl_propertylist_delete(qclist);
00209 
00210     return cpl_error_get_code();
00211 }
00212 
00213 /*----------------------------------------------------------------------------*/
00223 /*----------------------------------------------------------------------------*/
00224 static cpl_error_code naco_img_detlin_load(cpl_imagelist * lamplist,
00225                                            cpl_vector * ditval,
00226                                            const cpl_parameterlist * parlist,
00227                                            const irplib_framelist * lamps,
00228                                            const irplib_framelist * darks)
00229 {
00230     cpl_image     * imlamp = NULL;
00231     cpl_image     * imdark = NULL;
00232     double          refmean, refdit;
00233     double          dit_min, dit_max;
00234     const int       nb_lamps = irplib_framelist_get_size(lamps);
00235     int             dit_var = 0;
00236     int             i;
00237     const cpl_boolean force = naco_parameterlist_get_bool(parlist, RECIPE_STRING,
00238                                                           NACO_PARAM_FORCE);
00239 
00240 
00241     bug_if (0);
00242 
00243     bug_if (lamplist == NULL);
00244     bug_if (darks    == NULL);
00245     bug_if (ditval   == NULL);
00246 
00247     skip_if_lt(nb_lamps, 3, "lamp images");
00248 
00249     /* Check that there are as many lamp as darks */
00250     skip_if (irplib_framelist_get_size(darks) != nb_lamps);
00251 
00252     /* Check out that they have consistent integration times */
00253     cpl_msg_info(cpl_func, "Checking DIT consistency");
00254 
00255     skip_if(irplib_framelist_contains(lamps, NACO_PFITS_DOUBLE_DIT,
00256                                       CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00257 
00258     skip_if(irplib_framelist_contains(darks, NACO_PFITS_DOUBLE_DIT,
00259                                       CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00260 
00261     /* Load the data and compute lamp-dark */
00262     cpl_msg_info(cpl_func, "Compute the differences lamp - dark");
00263 
00264     /* Check the lamp stability */
00265     cpl_msg_info(cpl_func, "Check the lamp stability");
00266 
00267     bug_if(cpl_vector_set_size(ditval, nb_lamps));
00268     refmean = refdit = dit_max = dit_min = 0.0; /* Avoid uninit warning */
00269     for (i=0 ; i < nb_lamps ; i++) {
00270         const char * lampname
00271             = cpl_frame_get_filename(irplib_framelist_get_const(lamps, i));
00272         const char * darkname
00273             = cpl_frame_get_filename(irplib_framelist_get_const(darks, i));
00274 
00275         /* DIT from LAMP */
00276         const cpl_propertylist * plist
00277             = irplib_framelist_get_propertylist_const(lamps, i);
00278         const double dit_lamp = (double)naco_pfits_get_dit(plist);
00279         double dit_dark;
00280 
00281 
00282         bug_if (0);
00283 
00284         /* DIT from DARK */
00285         plist = irplib_framelist_get_propertylist_const(darks, i);
00286         dit_dark = naco_pfits_get_dit(plist);
00287         bug_if (0);
00288 
00289         /* Check consistency */
00290         irplib_ensure(fabs(dit_dark-dit_lamp) <= 1e-3,
00291                       CPL_ERROR_INCOMPATIBLE_INPUT,
00292                       "LAMP-DIT=%g and DARK-DIT=%g differ by more than %g",
00293                        dit_lamp, dit_dark, 1e-3);
00294 
00295         irplib_check(imlamp = cpl_image_load(lampname, CPL_TYPE_FLOAT, 0, 0),
00296                      "Could not load FITS-image from %s", lampname);
00297 
00298         cpl_image_delete(imdark);
00299         irplib_check(imdark = cpl_image_load(darkname, CPL_TYPE_FLOAT, 0, 0),
00300                      "Could not load FITS-image from %s", darkname);
00301 
00302         bug_if (cpl_image_subtract(imlamp, imdark));
00303 
00304         /* Set selection */
00305         if (i > 0 && dit_lamp != refdit) {
00306             bug_if(cpl_imagelist_set(lamplist, imlamp, dit_var));
00307             imlamp = NULL;
00308             bug_if(cpl_vector_set(ditval, dit_var, dit_lamp));
00309             dit_var++;
00310             if (dit_lamp > dit_max) dit_max = dit_lamp;
00311             if (dit_lamp < dit_min) dit_min = dit_lamp;
00312         } else {
00313             const double mean = cpl_image_get_mean(imlamp);
00314 
00315             cpl_image_delete(imlamp);
00316             imlamp = NULL;
00317 
00318             bug_if(0);
00319 
00320             if (i == 0) {
00321                 refmean = mean;
00322                 dit_max = dit_min = refdit = dit_lamp;
00323             } else if ((mean - refmean) > refmean * (DETLIN_STABILITY)) {
00324                 irplib_ensure(force, CPL_ERROR_INCOMPATIBLE_INPUT,
00325                               "Relative level difference # %d is too high:"
00326                                " (%g - %g)/%g > %g", i+1, mean, refmean,
00327                                refmean, (DETLIN_STABILITY));
00328 
00329                 cpl_msg_warning(cpl_func, "Relative level difference # %d "
00330                                 "is high: (%g - %g)/%g > %g", i+1, mean,
00331                                 refmean, refmean, (DETLIN_STABILITY));
00332             }
00333         }
00334     }
00335     
00336     /* Check if there are enough DITs for stability check */
00337     skip_if_lt(i - dit_var, 2, "lamp frames for stability check");
00338 
00339     if (dit_min >= dit_max) {
00340         cpl_msg_error(cpl_func, "Too small DIT range: %g - %g = %g", dit_max,
00341                       dit_min, dit_max - dit_min);
00342         cpl_error_set(cpl_func, CPL_ERROR_DATA_NOT_FOUND);
00343         skip_if(1);
00344     }
00345 
00346     bug_if(cpl_vector_set_size(ditval, dit_var));
00347 
00348     end_skip;
00349     
00350     cpl_image_delete(imlamp);
00351     cpl_image_delete(imdark);
00352 
00353     return cpl_error_get_code();
00354 }
00355 
00356 /*----------------------------------------------------------------------------*/
00362 /*----------------------------------------------------------------------------*/
00363 static cpl_image * naco_img_detlin_limit(const cpl_imagelist * iset)
00364 {
00365     cpl_image       *   lin_limit = NULL;
00366     int                 size_x, size_y;
00367     float           *   plin_limit;
00368     const float     *   pim1;
00369     const float     *   pim2;
00370     float               ref_diff, cur_diff;
00371     int                 i, j;
00372 
00373 
00374     if (cpl_error_get_code()) return NULL;
00375 
00376     skip_if_lt(cpl_imagelist_get_size(iset), 3, "images to compute the "
00377                "detector linearity limit");
00378 
00379     /* Get image size */
00380     size_x = cpl_image_get_size_x(cpl_imagelist_get_const(iset, 0));
00381     size_y = cpl_image_get_size_y(cpl_imagelist_get_const(iset, 0));
00382 
00383     /* Create the output image */
00384     lin_limit = cpl_image_new(size_x, size_y, CPL_TYPE_FLOAT);
00385 
00386     skip_if (lin_limit == NULL);
00387 
00388     plin_limit = cpl_image_get_data_float(lin_limit);
00389 
00390     bug_if(0);
00391 
00392     /* Compute the limit for each pixel */
00393     for (i=0 ; i<size_x*size_y ; i++) {
00394         pim1 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 0));
00395         pim2 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 1));
00396         ref_diff = pim2[i] - pim1[i];
00397         for (j=1 ; j<cpl_imagelist_get_size(iset)-1 ; j++) {
00398             pim1 = cpl_image_get_data_float_const(
00399                                             cpl_imagelist_get_const(iset, j));
00400             pim2 = cpl_image_get_data_float_const(
00401                                             cpl_imagelist_get_const(iset, j+1));
00402             cur_diff = pim2[i] - pim1[i];
00403             if (cur_diff < DETLIN_LIMIT*ref_diff) {
00404                 /* The limit is reached */
00405                 plin_limit[i] = pim1[i];
00406                 break;
00407             }
00408             /* The limit is undefined */
00409             if (j+1 == cpl_imagelist_get_size(iset)-1) 
00410                 plin_limit[i] = (float)0.0;
00411         }
00412     }
00413 
00414     end_skip;
00415 
00416     return lin_limit;
00417 }
00418 
00419 /*----------------------------------------------------------------------------*/
00426 /*----------------------------------------------------------------------------*/
00427 static cpl_error_code naco_img_detlin_dit_diff(cpl_vector * self)
00428 {
00429 
00430     double * dits;
00431     int i;
00432 
00433     bug_if(0);
00434     bug_if(self == NULL);
00435 
00436     dits = cpl_vector_get_data(self);
00437 
00438     for (i = cpl_vector_get_size(self)-1; i > 0 ; i--) {
00439         dits[i] -= dits[i-1];
00440 
00441         if (dits[i] == 0.0) break;
00442 
00443     }
00444 
00445     if (i > 0) {
00446         cpl_msg_error(cpl_func, "Consecutive (%d and %d) DITS are equal: "
00447                       "%g", i-1, i, dits[i-1]);
00448 
00449         cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
00450         skip_if(1);
00451     }
00452 
00453     end_skip;
00454 
00455     return cpl_error_get_code();
00456 
00457 }
00458 
00459 
00460 /*----------------------------------------------------------------------------*/
00468 /*----------------------------------------------------------------------------*/
00469 static cpl_image * naco_img_detlin_bpm(const cpl_imagelist * iset,
00470                                        const cpl_vector    * ditdiff,
00471                                        const cpl_image     * err_im)
00472 {
00473     cpl_image    * imdiff = NULL;
00474     cpl_image    * bpm = NULL;
00475     int          * pbpm;
00476     const double * perr_im;
00477     const float  * pim1;
00478     const float  * pim2;
00479     float        * pimdiff;
00480     const double * ditval = cpl_vector_get_data_const(ditdiff);
00481     float          dit_ref, curr_val;
00482     int            size_x, size_y;
00483     int            ii, i, j, k;
00484 
00485 
00486     bug_if(0);
00487     skip_if_lt(cpl_imagelist_get_size(iset), 3, "images to compute the "
00488                "bad pixel map");
00489 
00490     /* Get size */
00491     size_x = cpl_image_get_size_x(cpl_imagelist_get_const(iset, 0));
00492     size_y = cpl_image_get_size_y(cpl_imagelist_get_const(iset, 0));
00493     bug_if(0);
00494 
00495     /* Create the output image */
00496     /*  - with all pixels zero-valued - i.e. they are assumed to be good */
00497     bpm = cpl_image_new(size_x, size_y, CPL_TYPE_INT);
00498     bug_if(0);
00499     pbpm = cpl_image_get_data_int(bpm);
00500 
00501     imdiff = cpl_image_new(size_x, 1, CPL_TYPE_FLOAT);
00502     bug_if(0);
00503     pimdiff = cpl_image_get_data_float(imdiff);
00504 
00505     /* Compute the bad pixel value for each pixel */
00506     dit_ref = (float)ditval[1];
00507     perr_im = cpl_image_get_data_double_const(err_im);
00508     
00509     for (ii = 0, j=0 ; j < size_y ; j++) {
00510         pim1 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 1));
00511         pim2 = cpl_image_get_data_float_const(cpl_imagelist_get_const(iset, 0));
00512 
00513         for (i=0 ; i < size_x ; i++, ii++) {
00514             const float fdiff = pim1[ii] - pim2[ii];
00515 
00516             pimdiff[i] = fdiff;
00517 
00518             /* Second test */
00519             if (fdiff * dit_ref < 0.0) pbpm[ii] |= 2;
00520 
00521             /* Third test */
00522             if (perr_im[ii] > DETLIN_MAX_RESI) pbpm[ii] |= 4;
00523         }
00524 
00525         for (k=1 ; k < cpl_imagelist_get_size(iset)-1 ; k++) {
00526             const float dit_diff = ditval[k+1] * DETLIN_MAX_GRAD;
00527 
00528             pim2 = pim1;
00529             pim1 = cpl_image_get_data_float_const(
00530                                             cpl_imagelist_get_const(iset, k+1));
00531 
00532             ii -= size_x;
00533             for (i=0 ; i < size_x ; i++, ii++) {
00534                 if ((pbpm[ii] & 1) == 0) {
00535 
00536                     const float fdiff = pimdiff[i];
00537 
00538                     curr_val = pim1[ii] - pim2[ii];
00539                     if (dit_diff * dit_ref < 0.0
00540                         ? (curr_val *  dit_ref < fdiff *  dit_diff)
00541                         : (curr_val *  dit_ref > fdiff *  dit_diff)) {
00542                         pbpm[ii] |= 1;
00543                     }
00544                 }
00545             }
00546         }
00547     }
00548 
00549     end_skip;
00550 
00551     cpl_image_delete(imdiff);
00552 
00553     return bpm;
00554 }
00555 
00556 /*----------------------------------------------------------------------------*/
00567 /*----------------------------------------------------------------------------*/
00568 static cpl_error_code naco_img_detlin_save(cpl_frameset            * set,
00569                                            const cpl_parameterlist * parlist,
00570                                            const cpl_propertylist  * qclist,
00571                                            const cpl_imagelist     * fitres,
00572                                            const cpl_image         * lin_limit,
00573                                            const cpl_image         * bpm)
00574 {
00575 
00576     bug_if(0);
00577 
00578     /* Write the _A FITS FILE */
00579     skip_if (irplib_dfs_save_image(set, parlist, set,
00580                                cpl_imagelist_get_const(fitres, 0),
00581                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00582                                NACO_IMG_DETLIN_A, qclist, NULL,
00583                                naco_pipe_id,
00584                                RECIPE_STRING "_A" CPL_DFS_FITS));
00585 
00586     /* Write the _B FITS FILE */
00587     skip_if (irplib_dfs_save_image(set, parlist, set,
00588                                cpl_imagelist_get_const(fitres, 1),
00589                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00590                                NACO_IMG_DETLIN_B, qclist, NULL, naco_pipe_id,
00591                                RECIPE_STRING "_B" CPL_DFS_FITS));
00592 
00593     /* Write the _C FITS FILE */
00594     skip_if (irplib_dfs_save_image(set, parlist, set,
00595                                cpl_imagelist_get_const(fitres, 2),
00596                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00597                                NACO_IMG_DETLIN_C, qclist, NULL, naco_pipe_id,
00598                                RECIPE_STRING "_C" CPL_DFS_FITS));
00599 
00600     /* Write the _D FITS FILE */
00601     skip_if (irplib_dfs_save_image(set, parlist, set,
00602                                cpl_imagelist_get_const(fitres, 3),
00603                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00604                                NACO_IMG_DETLIN_D, qclist, NULL, naco_pipe_id,
00605                                RECIPE_STRING "_D" CPL_DFS_FITS));
00606 
00607     /* Write the _Q FITS FILE */
00608     skip_if (irplib_dfs_save_image(set, parlist, set,
00609                                cpl_imagelist_get_const(fitres, 4),
00610                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00611                                NACO_IMG_DETLIN_Q, qclist, NULL, naco_pipe_id,
00612                                RECIPE_STRING "_Q" CPL_DFS_FITS));
00613 
00614     /* Write the _limit FITS FILE */
00615     skip_if (irplib_dfs_save_image(set, parlist, set, lin_limit, CPL_BPP_IEEE_FLOAT,
00616                                RECIPE_STRING, NACO_IMG_DETLIN_LIM, qclist, NULL,
00617                                naco_pipe_id,
00618                                RECIPE_STRING "_limit" CPL_DFS_FITS));
00619 
00620     /* Write the _bpm FITS FILE */
00621     skip_if (irplib_dfs_save_image(set, parlist, set, bpm, CPL_BPP_8_UNSIGNED,
00622                                RECIPE_STRING, NACO_IMG_DETLIN_BPM, qclist, NULL,
00623                                naco_pipe_id,
00624                                RECIPE_STRING "_bpm" CPL_DFS_FITS));
00625 
00626     end_skip;
00627 
00628     return cpl_error_get_code();
00629 }
00630 
00631 
00632 
00633 /*----------------------------------------------------------------------------*/
00662 /*----------------------------------------------------------------------------*/
00663 static cpl_imagelist * naco_imagelist_fit_polynomial(
00664         const cpl_imagelist *   ilist,
00665         const double        *   dit,
00666         int                     deg)
00667 {
00668     cpl_imagelist   * fitres;
00669     const cpl_image * image;
00670     int               ni, nx, ny;
00671 
00672     /* Check entries */
00673     cpl_ensure(ilist != NULL, CPL_ERROR_NULL_INPUT, NULL);
00674     cpl_ensure(dit   != NULL, CPL_ERROR_NULL_INPUT, NULL);
00675     cpl_ensure(deg > 0,       CPL_ERROR_ILLEGAL_INPUT, NULL);
00676 
00677     ni = cpl_imagelist_get_size(ilist);
00678     cpl_ensure(ni >= deg,     CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
00679 
00680     image = cpl_imagelist_get_const(ilist, 0);
00681 
00682     cpl_ensure(cpl_image_get_type(image) == CPL_TYPE_FLOAT,
00683                CPL_ERROR_TYPE_MISMATCH, NULL);
00684 
00685     nx = cpl_image_get_size_x(image);
00686     ny = cpl_image_get_size_y(image);
00687 
00688     do {
00689 
00690         double       f, f_prod;
00691         double     * pimad;
00692         const float* pi;
00693         cpl_matrix * mv;
00694         cpl_matrix * mb;
00695         cpl_matrix * mx;
00696         double     * pv;
00697         const int    npix = nx * ny;
00698         int          nsing = 0;
00699         int          i, j, k;
00700         cpl_errorstate prestate = cpl_errorstate_get();
00701 
00702 
00703         /* Allocate deg+1 images to store the results */
00704         fitres = cpl_imagelist_new();
00705         for (i=0; i < deg+1; i++) {
00706             cpl_imagelist_set(fitres, cpl_image_new(nx, ny, CPL_TYPE_DOUBLE),
00707                               i);
00708         }
00709 
00710         /* Create matrices */
00711         pv = cpl_malloc(ni * deg * sizeof(double));
00712         mv = cpl_matrix_wrap(ni, deg, pv);
00713 
00714         /* Fill RHS matrix
00715            - mb is _not_ modified */
00716         mb = cpl_matrix_wrap(ni, 1, (double*)dit);
00717 
00718         /* Loop on pixels */
00719         for (i=0; i < npix; i++) {
00720             /* Fill Vandermonde matrix */
00721             for (j=0; j < ni; j++) {
00722                 pi = cpl_image_get_data_const(cpl_imagelist_get_const(ilist,j));
00723                 f_prod = f = (double)pi[i];
00724                 pv[deg * j] = f;
00725                 for (k=1; k < deg; k++) {
00726                     f_prod *= f;
00727                     pv[deg * j + k] = f_prod;
00728                 }
00729             }
00730 
00731             /* Solve least-squares */
00732             /* FIXME: See cpl_polynomial_fit_1d_create() for how to
00733                reduce the solve time */
00734             mx = cpl_matrix_solve_normal(mv, mb);
00735 
00736             if (mx == NULL) {
00737                 cpl_errorstate_set(prestate);
00738                 for (k=0; k < deg+1; k++) {
00739                     pimad = 
00740                         cpl_image_get_data_double(cpl_imagelist_get(fitres,k));
00741                     pimad[i] = 0.0;
00742                 }
00743                 nsing++;
00744             } else {
00745                 double err, sq_err;
00746                 const double * px = cpl_matrix_get_data(mx);
00747 
00748                 /* Store results */
00749                 for (k=0; k < deg; k++) {
00750                     pimad = cpl_image_get_data_double(
00751                             cpl_imagelist_get(fitres, k));
00752                     pimad[i] = px[k];
00753                 }
00754 
00755                 /* Goodness of fit */
00756                 sq_err=0.0;
00757                 for (j=0; j < ni; j++) {
00758                     /* Error between model and reality */
00759                     err = dit[j];
00760                     /* Computed by model */
00761                     for (k=0; k < deg; k++)
00762                         err -= px[k] * pv[deg * j + k];
00763                     sq_err += err * err;
00764                 }
00765                 sq_err /= (double)ni;
00766                 pimad=cpl_image_get_data_double(cpl_imagelist_get(fitres, deg));
00767                 pimad[i] = sq_err;
00768                 cpl_matrix_delete(mx);
00769             }
00770         }
00771 
00772         cpl_matrix_delete(mv);
00773         (void)cpl_matrix_unwrap(mb);
00774 
00775         if (nsing == npix) {
00776             cpl_imagelist_delete(fitres);
00777             cpl_ensure(0, CPL_ERROR_SINGULAR_MATRIX, NULL);
00778         }
00779 
00780 
00781     } while (0);
00782 
00783 
00784     return fitres;
00785 }

Generated on Mon Feb 6 14:42:07 2012 for NACO Pipeline Reference Manual by  doxygen 1.5.8