GIRAFFE Pipeline Reference Manual

irplib_detmon.c

00001 /* $Id: irplib_detmon.c,v 1.3.2.1 2008/06/10 14:09:33 rpalsa Exp $
00002  *
00003  * This file is part of the irplib package
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: rpalsa $
00023  * $Date: 2008/06/10 14:09:33 $
00024  * $Revision: 1.3.2.1 $
00025  * $Name: giraffe-2_5_2 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*---------------------------------------------------------------------------
00033                                   Includes
00034  ---------------------------------------------------------------------------*/
00035 
00036 #ifdef HAVE_FFTW
00037 #include <complex.h>
00038 #include <sfftw.h>
00039 #endif
00040 
00041 #include <math.h>
00042 #include <string.h>
00043 #include <assert.h>
00044 #include <float.h>
00045 
00046 #include <cpl.h>
00047 
00048 #include "irplib_detmon.h"
00049 
00050 #include "irplib_hist.h"
00051 #include "irplib_utils.h"
00052 
00053 
00054 /* Computes the square of an euclidean distance bet. 2 points */
00055 #define pdist(x1,y1,x2,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
00056 
00057 #define cpl_drand() ((double)rand()/(double)RAND_MAX)
00058 
00059 /*--------------------------------------------------------------------------*/
00060 
00061 /*
00062  * @defgroup irplib_detmon        Detector monitoring functions
00063  */
00064 
00065 /*--------------------------------------------------------------------------*/
00066 
00067 /*---------------------------------------------------------------------------
00068                                   Defines
00069  ---------------------------------------------------------------------------*/
00070 
00071 
00072 #define HIST_FACT 2.354820045
00073 
00074 enum pixeltypes
00075 {
00076     HOT = 0,
00077     DEAD = 1,
00078     NOISY = 2
00079 };
00080 
00081 enum stackingtypes
00082 {
00083     MINMAX = 0,
00084     MEAN = 1,
00085     MEDIAN = 2,
00086     KSIGMA = 3
00087 };
00088 
00089 enum readouts
00090 {
00091     HORIZONTAL = 1,
00092     VERTICAL = 2
00093 };
00094 
00095 
00096 static struct
00097 {
00098     /* Inputs */
00099     const char             *method;
00100     const char             *pmethod;
00101     ronbias_method          method_bitmask;
00102     int                     prescan_llx;
00103     int                     prescan_lly;
00104     int                     prescan_urx;
00105     int                     prescan_ury;
00106     int                     overscan_llx;
00107     int                     overscan_lly;
00108     int                     overscan_urx;
00109     int                     overscan_ury;
00110     int                     preoverscan_degree;
00111     int                     random_nsamples;
00112     int                     random_sizex;
00113     int                     random_sizey;
00114     int                     criteria;
00115     int                     ref_llx;
00116     int                     ref_lly;
00117     int                     ref_urx;
00118     int                     ref_ury;
00119     const char             *stacking_method;
00120     int                     stacking_ks_low;
00121     int                     stacking_ks_high;
00122     int                     stacking_ks_iter;
00123     int                     master_shift_x;
00124     int                     master_shift_y;
00125     int                     ron_llx;
00126     int                     ron_lly;
00127     int                     ron_urx;
00128     int                     ron_ury;
00129     int                     exts;
00130     int                     nb_extensions;
00131 } detmon_ronbias_config;
00132 
00133 static struct
00134 {
00135     int         mode;
00136     cpl_boolean direction;
00137     double      speed;
00138     int         llx;
00139     int         lly;
00140     int         urx;
00141     int         ury;
00142     int         kappa;
00143     int         exts;
00144     int         nb_extensions;
00145 } detmon_pernoise_config;
00146 
00147 static struct
00148 {
00149     const char * ron_method;
00150     const char * dsnu_method;
00151     int         exts;
00152     int         nb_extensions;
00153     cpl_boolean opt_nir;
00154 } detmon_dark_config;
00155 
00156 #define NIR TRUE
00157 #define OPT FALSE
00158 
00159 /*---------------------------------------------------------------------------
00160                                   Private function prototypes
00161  ---------------------------------------------------------------------------*/
00162 
00163 
00164 
00165 /* Functions for RON/Bias recipe, irplib_detmon_ronbias() */
00166 
00167 static cpl_error_code
00168 irplib_detmon_ronbias_retrieve_parlist(const char *,
00169                                        const char *,
00170                                        const cpl_parameterlist *);
00171 
00172 static cpl_error_code
00173 irplib_detmon_ronbias_random(const cpl_imagelist *,
00174                  const cpl_image *, cpl_propertylist *);
00175 
00176 static cpl_error_code
00177 irplib_detmon_ronbias_histo(const cpl_imagelist *,
00178                 const cpl_image *, cpl_propertylist *);
00179 
00180 static cpl_error_code
00181 irplib_detmon_ronbias_preoverscan(const cpl_imagelist *, /*const cpl_image *,*/
00182                                    cpl_propertylist *, cpl_image **);
00183 
00184 static cpl_error_code
00185 irplib_detmon_ronbias_region(const cpl_imagelist *,
00186                  const cpl_image *, cpl_propertylist *);
00187 
00188 static cpl_image *
00189 irplib_detmon_ronbias_master(const cpl_imagelist *,
00190                  cpl_mask **, cpl_mask **, cpl_mask **,
00191                              cpl_propertylist *);
00192 
00193 static cpl_error_code
00194 irplib_detmon_ronbias_save(const cpl_parameterlist *,
00195                            cpl_frameset *,
00196                            const char *,
00197                            const char *,
00198                            const char *,
00199                            const char *,
00200                            const char *,
00201                            const char *,
00202                            const char *,
00203                            const char *,
00204                            const char *,
00205                            const char *,
00206                            const char *,
00207                            const cpl_image *,
00208                            const cpl_image *,
00209                const cpl_mask *,
00210                const cpl_mask *,
00211                const cpl_mask *,
00212                            cpl_propertylist *,
00213                            const int, 
00214                            const int, 
00215                            cpl_frameset *,
00216                            int);
00217 
00218 int
00219 irplib_detmon_ronbias_dfs_set_groups(cpl_frameset *, const char *);
00220 
00221 static cpl_image *
00222 irplib_detmon_build_synthetic(cpl_image *,
00223                               cpl_image *);
00224 
00225 static cpl_error_code
00226 irplib_detmon_ronbias_histo_reduce(const cpl_image * c_raw,
00227                    double * bias,
00228                    double * fwhm,
00229                    double * max);
00230 
00231 static cpl_error_code
00232 irplib_detmon_ronbias_dutycycl(const cpl_frameset *, cpl_propertylist *);
00233 
00234 cpl_error_code
00235 irplib_detmon_rm_bpixs(cpl_image **,
00236                        const double,
00237                        int         ,
00238                        int         );
00239 
00240 /* The following 2 functions are duplicated from cpl_det */
00241 
00242 static cpl_error_code
00243 irplib_flux_get_bias_window(const cpl_image *,
00244                             const int       *,
00245                             int              ,
00246                             int              ,
00247                             double          *,
00248                             double          *);
00249 
00250 static cpl_bivector    *
00251 irplib_bivector_gen_rect_poisson(const int *r,
00252                                  const int np,
00253                                  const int homog);
00254 
00255 /* End of duplicated code */ 
00256 
00257 
00258 cpl_error_code
00259 irplib_detmon_ronbias_check_defaults(const cpl_frameset *, const int whichext);
00260 
00261 
00262 /* Functions for Periodic Noise Characterisation, irplib_detmon_pernoise() */
00263 
00264 int
00265 irplib_detmon_pernoise_dfs_set_groups(cpl_frameset *,
00266                                       const char *);
00267 
00268 static cpl_error_code
00269 irplib_detmon_pernoise_retrieve_parlist(const char *,
00270                                        const char *,
00271                                        const cpl_parameterlist *);
00272 
00273 static cpl_error_code
00274 irplib_detmon_pernoise_qc(cpl_propertylist *,
00275                           cpl_table        *,
00276                           int);
00277 
00278 static cpl_error_code
00279 irplib_detmon_pernoise_save(const cpl_parameterlist *,
00280                             cpl_frameset *,
00281                             const char *,
00282                             const char *,
00283                             const char *,
00284                             const char *,
00285                             cpl_table **,
00286                             cpl_propertylist **,
00287                             const int,
00288                             const int,
00289                             const cpl_frameset *);
00290 
00291 cpl_error_code
00292 irplib_detmon_pernoise_rm_bg(cpl_image *,
00293                              int,
00294                              int);
00295 
00296 int
00297 irplib_detmon_dark_dfs_set_groups(cpl_frameset *,
00298                                   const char *);
00299 
00300 cpl_error_code
00301 irplib_detmon_dark_dsnu(cpl_frameset *,
00302                         cpl_imagelist *,
00303                         cpl_table *,
00304                         cpl_image *,
00305                         int pos);
00306 
00307 
00308 static cpl_error_code
00309 irplib_detmon_dark_save(const cpl_parameterlist *,
00310                         cpl_frameset *,
00311                         const char *,
00312                         const char *,
00313                         const char *,
00314                         const char *,
00315                         const char *,
00316                         const char *,
00317                         cpl_imagelist **,
00318                         cpl_table **,
00319                         cpl_imagelist **,
00320                         cpl_propertylist **,
00321                         const int,
00322                         const int,
00323                         const cpl_frameset *);
00324 
00325 
00326 
00327 static cpl_error_code
00328 irplib_detmon_retrieve_dark_params(const char *,
00329                                    const char *,
00330                                    const cpl_parameterlist *);
00331 
00332 cpl_error_code
00333 irplib_detmon_dark_qc(cpl_propertylist *,
00334                       cpl_image *);
00335 
00336 
00337 
00338 /*         RONBIAS FILLING PARLIST        */
00339 
00340 cpl_error_code
00341 irplib_detmon_ronbias_fill_parlist_default(cpl_parameterlist * parlist,
00342                    const char *recipe_name,
00343                    const char *pipeline_name)
00344 {
00345     const cpl_error_code error =
00346     irplib_detmon_ronbias_fill_parlist(parlist, recipe_name, pipeline_name,
00347                        "ALL", /* --method */
00348                        "NORM",/* --pmethod */
00349                        1,     /* --preoverscan_degree */
00350                        -1,    /* --random_nsamples */
00351                        -1,    /* --random_sizex */
00352                        -1,    /* --random_sizey */
00353                        0,     /* --criteria     */
00354                        -1,    /* --ref_llx     */
00355                        -1,    /* --ref_lly */
00356                        -1,    /* --ref_urx */
00357                        -1,    /* --ref_ury */
00358                        "MEAN",/* --stacking_method */
00359                        3,     /* --stacking_ks_low */
00360                        10000, /* --stacking_ks_high */
00361                        25,    /* --stacking_ks_iter */ 
00362                        0,     /* --master_shift_x */
00363                        0,     /* --master_shift_y */
00364                        -1,    /* --ron_llx */
00365                        -1,    /* --ron_lly */
00366                        -1,    /* --ron_urx */
00367                        -1,    /* --ron_ury */
00368                        0);    /* --exts */
00369     cpl_ensure_code(!error, error);
00370 
00371     return cpl_error_get_code();
00372 }
00373 
00374 cpl_error_code
00375 irplib_detmon_ronbias_fill_parlist(cpl_parameterlist * parlist,
00376                    const char *recipe_name,
00377                    const char *pipeline_name,
00378                    const char * method,
00379                    const char * pmethod,
00380                    const int preoverscan_degree,
00381                    const int random_nsamples,
00382                    const int random_sizex,
00383                    const int random_sizey,
00384                    const int criteria,
00385                    const int ref_llx,
00386                    const int ref_lly,
00387                    const int ref_urx,
00388                    const int ref_ury,
00389                    const char * stacking_method,
00390                    const int stacking_ks_low,
00391                    const int stacking_ks_high,
00392                    const int stacking_ks_iter,
00393                    const int master_shift_x,
00394                    const int master_shift_y,
00395                    const int ron_llx,
00396                    const int ron_lly,
00397                    const int ron_urx,
00398                    const int ron_ury,
00399                    const int exts)
00400 {
00401     const cpl_error_code error = 
00402     irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 22,
00403                    "method",
00404                    "Method to be used when computing bias. Methods appliable: <RANDOM | HISTO | PREOVERSCAN | REGION | ALL>. By default ALL methods are applied. More than a method can be chosen; in that case selected methods must be separated by a single space and put together between inverted commas (ex. --method=\"HISTO REGION\").\n RANDOM: Bias is computed as the mean value on a given number (--random.nsamples) of boxes (dimensions --random.sizex and --random.sizey) randomly taken  accross the detector.\n HISTO: An histogram of the pixels of the image is built.\n PREOVERSCAN: Mean, median and RMS values computed and designated areas. \n REGION: Mean, median and RMS values on reference region.",
00405                    "CPL_TYPE_STRING", method,
00406 
00407                    "pmethod",
00408                    "Pre-method for RANDOM, HISTO and REGION."
00409                    "Difference raw frames or not",
00410                    "CPL_TYPE_STRING", pmethod,
00411 
00412                    "preoverscan.degree",
00413                    "Degree used for pre-overscan method",
00414                    "CPL_TYPE_INT", preoverscan_degree,
00415 
00416                    "random.nsamples",
00417                    "Number of samples",
00418                    "CPL_TYPE_INT", random_nsamples,
00419 
00420                    "random.sizex",
00421                    "X size of the boxes",
00422                    "CPL_TYPE_INT", random_sizex,
00423 
00424                    "random.sizey",
00425                    "Y size of the boxes",
00426                    "CPL_TYPE_INT", random_sizey,
00427 
00428                    "criteria",
00429                    "Criteria",
00430                    "CPL_TYPE_INT", criteria,
00431 
00432                    "ref.llx",
00433                    "x coordinate of the lower-left point "
00434                    "of the reference region of the frame",
00435                    "CPL_TYPE_INT", ref_llx,
00436 
00437                    "ref.lly",
00438                    "y coordinate of the lower-left point "
00439                    "of the reference region of the frame",
00440                    "CPL_TYPE_INT", ref_lly,
00441 
00442                    "ref.urx",
00443                    "x coordinate of the upper-right point "
00444                    "of the reference region of the frame",
00445                    "CPL_TYPE_INT", ref_urx,
00446 
00447                    "ref.ury",
00448                    "y coordinate of the upper-right point "
00449                    "of the reference region of the frame",
00450                    "CPL_TYPE_INT", ref_ury,
00451 
00452                    "stacking.method",
00453                    "Method to be used when stacking the master. Posible values < MINMAX | MEAN | MEDIAN | KSIGMA >",
00454                    "CPL_TYPE_STRING", stacking_method,
00455 
00456                    "stacking.ks.low",
00457                    "Low threshold for kappa-sigma clipping",
00458                    "CPL_TYPE_INT", stacking_ks_low,
00459 
00460                    "stacking.ks.high",
00461                    "High threshold for kappa-sigma clipping",
00462                    "CPL_TYPE_INT", stacking_ks_high,
00463 
00464                    "stacking.ks.iter",
00465                    "Nb of iterations for kappa-sigma clipping",
00466                    "CPL_TYPE_INT", stacking_ks_iter,
00467 
00468                    "master.shift.x",
00469                    "Master shift X",
00470                    "CPL_TYPE_INT", master_shift_x,
00471 
00472                    "master.shift.y",
00473                    "Master shift Y",
00474                    "CPL_TYPE_INT", master_shift_y,
00475 
00476                    "ron.llx",
00477                    "x coordinate of the lower-left point "
00478                    "of the RON frame",
00479                    "CPL_TYPE_INT", ron_llx,
00480 
00481                    "ron.lly",
00482                    "y coordinate of the lower-left point "
00483                    "of the RON frame",
00484                    "CPL_TYPE_INT", ron_lly,
00485 
00486                    "ron.urx",
00487                    "x coordinate of the upper-right point "
00488                    "of the RON frame",
00489                    "CPL_TYPE_INT", ron_urx,
00490 
00491                    "ron.ury",
00492                    "y coordinate of the upper-right point "
00493                    "of the RON frame", "CPL_TYPE_INT", ron_ury,
00494 
00495                                    "exts",
00496                                    "Activate the multi-exts option",
00497                                    "CPL_TYPE_INT", exts);
00498 
00499 
00500     cpl_ensure_code(!error, error);
00501 
00502     return cpl_error_get_code();
00503 }
00504 
00505 cpl_error_code
00506 irplib_detmon_fill_parlist(cpl_parameterlist * parlist,
00507                            const char *recipe_name, const char *pipeline_name,
00508                            int npars, ...)
00509 {
00510 
00511     va_list                 ap;
00512 
00513     char                   *group_name;
00514 
00515     int                     pars_counter = 0;
00516 
00517     group_name = cpl_sprintf("%s.%s", pipeline_name, recipe_name);
00518     assert(group_name != NULL);
00519 
00520 #define insert_par(PARNAME, PARDESC, PARVALUE, PARTYPE)                      \
00521     do {                                                                     \
00522     char * par_name = cpl_sprintf("%s.%s", group_name, PARNAME);          \
00523     cpl_parameter * p;                                                       \
00524     assert(par_name != NULL);                                                \
00525     p = cpl_parameter_new_value(par_name, PARTYPE,                           \
00526                                 PARDESC, group_name, PARVALUE);              \
00527     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, PARNAME);             \
00528     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);                        \
00529     cpl_parameterlist_append(parlist, p);                                    \
00530     cpl_free(par_name);                                                      \
00531     } while(0);
00532 
00533 
00534     va_start(ap, npars);
00535 
00536     while(pars_counter < npars) {
00537         char                   *name = va_arg(ap, char *);
00538         char                   *desc = va_arg(ap, char *);
00539         char                   *type = va_arg(ap, char *);
00540 
00541         if(!strcmp(type, "CPL_TYPE_INT")) {
00542             int                     v1 = va_arg(ap, int);
00543 
00544             insert_par(name, desc, v1, CPL_TYPE_INT);
00545         } else if(!strcmp(type, "CPL_TYPE_BOOL")) {
00546             char                   *v2 = va_arg(ap, char *);
00547 
00548             if(!strcmp(v2, "CPL_FALSE"))
00549                 insert_par(name, desc, CPL_FALSE, CPL_TYPE_BOOL);
00550             if(!strcmp(v2, "CPL_TRUE"))
00551                 insert_par(name, desc, CPL_TRUE, CPL_TYPE_BOOL);
00552         } else if(!strcmp(type, "CPL_TYPE_STRING")) {
00553             char                   *v2 = va_arg(ap, char *);
00554 
00555             insert_par(name, desc, v2, CPL_TYPE_STRING);
00556         } else if(!strcmp(type, "CPL_TYPE_DOUBLE")) {
00557             double v3 = va_arg(ap, double);
00558             insert_par(name, desc, v3, CPL_TYPE_DOUBLE);
00559         }
00560 
00561         pars_counter++;
00562     }
00563 
00564     va_end(ap);
00565 
00566     cpl_free(group_name);
00567 
00568 #undef insert_par
00569     return 0;
00570 }
00571 
00572 /*---------------------------------------------------------------------------*/
00573 
00574 /*
00575  * @brief  Retrieve input parameters
00576  * @param  pipeline_name        Input image
00577  * @param  recipe_name          Input image
00578  * @param  parlist              Shift to apply on the x-axis
00579  * @return CPL_ERROR_NONE on success.
00580  */
00581 
00582 /*---------------------------------------------------------------------------*/
00583 int
00584 irplib_detmon_retrieve_par(const char *parn,
00585                            const char *pipeline_name,
00586                            const char *recipe_name,
00587                            const cpl_parameterlist * parlist)
00588 {
00589     char                   *par_name;
00590     cpl_parameter          *par;
00591     int                     value;
00592 
00593     par_name = cpl_sprintf("%s.%s.%s", pipeline_name, recipe_name, parn);
00594     assert(par_name != NULL);
00595     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
00596     value = cpl_parameter_get_int(par);
00597     cpl_free(par_name);
00598 
00599     return value;
00600 }
00601 
00602 
00603 /*--------------------------------------------------------------------------*/
00604 
00605 /*
00606  * @brief    Comparison function to identify different settings
00607  * @param    frame1  First frame 
00608  * @param    frame2  Second frame 
00609  * @return   0 if different, 1 if equal, -1 in error case
00610  */
00611 
00612 /*--------------------------------------------------------------------------*/
00613 
00614 int
00615 irplib_detmon_compare_dits(const cpl_frame * frame1, const cpl_frame * frame2)
00616 {
00617     int                     comparison;
00618     cpl_propertylist       *plist1;
00619     cpl_propertylist       *plist2;
00620     double                  dval1, dval2;
00621 
00622     /* Test entries */
00623     if(frame1 == NULL || frame2 == NULL)
00624         return -1;
00625 
00626     /* Get property lists */
00627     if((plist1 = cpl_propertylist_load(cpl_frame_get_filename(frame1),
00628                                        0)) == NULL) {
00629         cpl_msg_error(cpl_func, "getting header from reference frame");
00630         return -1;
00631     }
00632     if((plist2 = cpl_propertylist_load(cpl_frame_get_filename(frame2),
00633                                        0)) == NULL) {
00634         cpl_msg_error(cpl_func, "getting header from reference frame");
00635         cpl_propertylist_delete(plist1);
00636         return -1;
00637     }
00638 
00639     /* Test status */
00640     if(cpl_error_get_code()) {
00641         cpl_propertylist_delete(plist1);
00642         cpl_propertylist_delete(plist2);
00643         return -1;
00644     }
00645 
00646     /* Compare exposure time */
00647     comparison = 1;
00648     dval1 = irplib_pfits_get_exptime(plist1);
00649     dval2 = irplib_pfits_get_exptime(plist2);
00650     if(cpl_error_get_code()) {
00651         cpl_msg_error(cpl_func, "cannot get exposure time");
00652         cpl_propertylist_delete(plist1);
00653         cpl_propertylist_delete(plist2);
00654         return -1;
00655     }
00656     if(fabs(dval1 - dval2) > 1e-3)
00657         comparison = 0;
00658 
00659     /* Free and return */
00660     cpl_propertylist_delete(plist1);
00661     cpl_propertylist_delete(plist2);
00662     return comparison;
00663 }
00664 
00665 
00666 double
00667 irplib_pfits_get_exptime(const cpl_propertylist * plist)
00668 {
00669     double                  exptime;
00670 
00671     exptime = cpl_propertylist_get_double(plist, "EXPTIME");
00672 
00673     return exptime;
00674 }
00675 
00676 /*---------------------------------------------------------------------------*/
00677 
00678 /*
00679  * @brief  Retrieve input parameters
00680  * @param  pipeline_name        Input image
00681  * @param  recipe_name          Input image
00682  * @param  parlist              Shift to apply on the x-axis
00683  * @return CPL_ERROR_NONE on success.
00684  */
00685 
00686 /*---------------------------------------------------------------------------*/
00687 static                  cpl_error_code
00688 irplib_detmon_ronbias_retrieve_parlist(const char *pipeline_name,
00689                                       const char *recipe_name,
00690                                       const cpl_parameterlist * parlist)
00691 {
00692     char                   *par_name;
00693     cpl_parameter          *par;
00694 
00695     char                    m1[20] = "";
00696     char                    m2[20] = "";
00697     char                    m3[20] = "";
00698 
00699     /* --method */
00700     par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
00701     assert(par_name != NULL);
00702     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
00703     detmon_ronbias_config.method = cpl_parameter_get_string(par);
00704     cpl_free(par_name);
00705 
00706     detmon_ronbias_config.method_bitmask = 0;
00707 
00708     sscanf(detmon_ronbias_config.method, "%s %s %s", m1, m2, m3);
00709 
00710     if(!strcmp(m1, "RANDOM") || !strcmp(m2, "RANDOM")
00711        || !strcmp(m3, "RANDOM"))
00712         detmon_ronbias_config.method_bitmask += RANDOM;
00713 
00714     if(!strcmp(m1, "HISTO") || !strcmp(m2, "HISTO") || !strcmp(m3, "HISTO"))
00715         detmon_ronbias_config.method_bitmask += HISTO;
00716 
00717     if(!strcmp(m1, "PREOVERSCAN") || !strcmp(m2, "PREOVERSCAN")
00718        || !strcmp(m3, "PREOVERSCAN"))
00719         detmon_ronbias_config.method_bitmask += PREOVERSCAN;
00720 
00721     if(!strcmp(m1, "REGION") || !strcmp(m2, "REGION")
00722        || !strcmp(m3, "REGION"))
00723         detmon_ronbias_config.method_bitmask += REGION;
00724 
00725     if(!strcmp(m1, "ALL"))
00726         detmon_ronbias_config.method_bitmask =
00727             RANDOM | HISTO | PREOVERSCAN | REGION;
00728 
00729     /* --pmethod */
00730     par_name = cpl_sprintf("%s.%s.pmethod", pipeline_name, recipe_name);
00731     assert(par_name != NULL);
00732     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
00733     detmon_ronbias_config.pmethod = cpl_parameter_get_string(par);
00734     cpl_free(par_name);
00735 
00736     /* --preoverscan.degree */
00737     detmon_ronbias_config.preoverscan_degree =
00738         irplib_detmon_retrieve_par("preoverscan.degree", pipeline_name,
00739                                    recipe_name, parlist);
00740 
00741     /* --nsamples */
00742     detmon_ronbias_config.random_nsamples =
00743         irplib_detmon_retrieve_par("random.nsamples", pipeline_name,
00744                                    recipe_name, parlist);
00745 
00746     /* --sizex */
00747     detmon_ronbias_config.random_sizex =
00748         irplib_detmon_retrieve_par("random.sizex", pipeline_name,
00749                                    recipe_name, parlist);
00750 
00751     /* --sizey */
00752     detmon_ronbias_config.random_sizey =
00753         irplib_detmon_retrieve_par("random.sizey", pipeline_name,
00754                                    recipe_name, parlist);
00755 
00756     /* --criteria */
00757     detmon_ronbias_config.criteria =
00758         irplib_detmon_retrieve_par("criteria", pipeline_name, recipe_name,
00759                                    parlist);
00760 
00761     /* --ref.llx */
00762     detmon_ronbias_config.ref_llx =
00763         irplib_detmon_retrieve_par("ref.llx", pipeline_name, recipe_name,
00764                                    parlist);
00765     /* --ref.lly */
00766     detmon_ronbias_config.ref_lly =
00767         irplib_detmon_retrieve_par("ref.lly", pipeline_name, recipe_name,
00768                                    parlist);
00769     /* --ref.urx */
00770     detmon_ronbias_config.ref_urx =
00771         irplib_detmon_retrieve_par("ref.urx", pipeline_name, recipe_name,
00772                                    parlist);
00773     /* --ref.ury */
00774     detmon_ronbias_config.ref_ury =
00775         irplib_detmon_retrieve_par("ref.ury", pipeline_name, recipe_name,
00776                                    parlist);
00777 
00778     /* --stacking.method */
00779     par_name =
00780         cpl_sprintf("%s.%s.stacking.method", pipeline_name, recipe_name);
00781     assert(par_name != NULL);
00782     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
00783     detmon_ronbias_config.stacking_method = cpl_parameter_get_string(par);
00784     cpl_free(par_name);
00785 
00786     /* --stacking.ks.low */
00787     detmon_ronbias_config.stacking_ks_low =
00788         irplib_detmon_retrieve_par("stacking.ks.low", pipeline_name,
00789                                    recipe_name, parlist);
00790     /* --stacking.ks.high */
00791     detmon_ronbias_config.stacking_ks_high =
00792         irplib_detmon_retrieve_par("stacking.ks.high", pipeline_name,
00793                                    recipe_name, parlist);
00794     /* --stacking.ks.iter */
00795     detmon_ronbias_config.stacking_ks_iter =
00796         irplib_detmon_retrieve_par("stacking.ks.iter", pipeline_name,
00797                                    recipe_name, parlist);
00798     /* --master.shift.x */
00799     detmon_ronbias_config.master_shift_x =
00800         irplib_detmon_retrieve_par("master.shift.x", pipeline_name,
00801                                    recipe_name, parlist);
00802     /* --master.shift.y */
00803     detmon_ronbias_config.master_shift_y =
00804         irplib_detmon_retrieve_par("master.shift.y", pipeline_name,
00805                                    recipe_name, parlist);
00806     /* --ron.llx */
00807     detmon_ronbias_config.ron_llx =
00808         irplib_detmon_retrieve_par("ron.llx", pipeline_name, recipe_name,
00809                                    parlist);
00810     /* --ron.lly */
00811     detmon_ronbias_config.ron_lly =
00812         irplib_detmon_retrieve_par("ron.lly", pipeline_name, recipe_name,
00813                                    parlist);
00814     /* --ron.urx */
00815     detmon_ronbias_config.ron_urx =
00816         irplib_detmon_retrieve_par("ron.urx", pipeline_name, recipe_name,
00817                                    parlist);
00818     /* --ron.ury */
00819     detmon_ronbias_config.ron_ury =
00820         irplib_detmon_retrieve_par("ron.ury", pipeline_name, recipe_name,
00821                                    parlist);
00822     /* --exts */
00823     detmon_ronbias_config.exts =
00824         irplib_detmon_retrieve_par("exts", pipeline_name, recipe_name,
00825                                    parlist);
00826 
00827     if(cpl_error_get_code()) {
00828         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
00829         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
00830     }
00831 
00832 
00833     return CPL_ERROR_NONE;
00834 }
00835 
00836 /*---------------------------------------------------------------------------*/
00837 
00838 /*
00839  * @brief  Retrieve input parameters
00840  * @param  pipeline_name        Input image
00841  * @param  recipe_name          Input image
00842  * @param  parlist              Shift to apply on the x-axis
00843  * @return CPL_ERROR_NONE on success.
00844  */
00845 
00846 /*---------------------------------------------------------------------------*/
00847 cpl_error_code
00848 irplib_detmon_ronbias_check_defaults(const cpl_frameset * set,
00849                                      const int whichext)
00850 {
00851     const cpl_frame  * fr        = cpl_frameset_get_first_const(set);
00852 
00853     cpl_propertylist * plist     = 
00854     cpl_propertylist_load(cpl_frame_get_filename(fr), whichext);
00855 
00856     const int naxis1 = cpl_propertylist_get_int(plist, "NAXIS1");
00857     const int naxis2 = cpl_propertylist_get_int(plist, "NAXIS2");
00858 
00859     cpl_error_code          error;
00860 
00861     if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
00862     const int nx = cpl_propertylist_get_int(plist, "ESO DET OUT1 NX");
00863     const int ny = cpl_propertylist_get_int(plist, "ESO DET OUT1 NY");
00864 
00865     int prscsize;
00866     int ovscsize;
00867 
00868     if (naxis1 != nx) {
00869         prscsize = 
00870         cpl_propertylist_get_int(plist, "ESO DET OUT1 PRSCX");
00871         ovscsize =
00872         cpl_propertylist_get_int(plist, "ESO DET OUT1 OVSCX");
00873         cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
00874 
00875         detmon_ronbias_config.prescan_llx  = 1;
00876         detmon_ronbias_config.prescan_lly  = 1;
00877         detmon_ronbias_config.prescan_urx  = prscsize;
00878         detmon_ronbias_config.prescan_ury  = naxis2;
00879         detmon_ronbias_config.overscan_llx = naxis1 - ovscsize;
00880         detmon_ronbias_config.overscan_lly = 1;
00881         detmon_ronbias_config.overscan_urx = naxis1;
00882         detmon_ronbias_config.overscan_ury = naxis2;
00883     } else if (naxis2 != ny) {
00884         prscsize =
00885         cpl_propertylist_get_int(plist, "ESO DET OUT1 PRSCY");
00886         ovscsize =
00887         cpl_propertylist_get_int(plist, "ESO DET OUT1 OVSCY");
00888         cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
00889 
00890         detmon_ronbias_config.prescan_llx  = 1;
00891         detmon_ronbias_config.prescan_lly  = 1;
00892         detmon_ronbias_config.prescan_urx  = naxis1;
00893         detmon_ronbias_config.prescan_ury  = prscsize;
00894         detmon_ronbias_config.overscan_llx = 1;
00895         detmon_ronbias_config.overscan_lly = naxis2 - ovscsize;
00896         detmon_ronbias_config.overscan_urx = naxis1;
00897         detmon_ronbias_config.overscan_ury = naxis2;
00898     } else {
00899         cpl_msg_error(cpl_func,
00900               "No PREOVERSCAN areas found");
00901         cpl_ensure_code(0, CPL_ERROR_NULL_INPUT);
00902     }
00903     cpl_propertylist_delete(plist);
00904     }
00905 
00906     if(detmon_ronbias_config.ref_llx == -1)
00907         detmon_ronbias_config.ref_llx = naxis1 / 8;
00908     if(detmon_ronbias_config.ref_lly == -1)
00909         detmon_ronbias_config.ref_lly = naxis2 / 8;
00910     if(detmon_ronbias_config.ref_urx == -1)
00911         detmon_ronbias_config.ref_urx = naxis1 * 7 / 8;
00912     if(detmon_ronbias_config.ref_ury == -1)
00913         detmon_ronbias_config.ref_ury = naxis2 * 7 / 8;
00914 
00915     if(detmon_ronbias_config.ron_llx == -1)
00916         detmon_ronbias_config.ron_llx = 1;
00917     if(detmon_ronbias_config.ron_lly == -1)
00918         detmon_ronbias_config.ron_lly = 1;
00919     if(detmon_ronbias_config.ron_urx == -1)
00920         detmon_ronbias_config.ron_urx = naxis1;
00921     if(detmon_ronbias_config.ron_ury == -1)
00922         detmon_ronbias_config.ron_ury = naxis2;
00923 
00924     error = cpl_error_get_code();
00925     cpl_ensure_code(!error, error);
00926 
00927     return CPL_ERROR_NONE;
00928 }
00929 
00944 cpl_error_code
00945 irplib_get_clean_mean_window(const cpl_image * img,
00946                              const int llx,
00947                              const int lly,
00948                              const int urx,
00949                  const int ury,
00950                              const double kappa,
00951                              const int nclip,
00952                  const double tolerance,
00953                              double * clean_mean,
00954                  double * clean_stdev)
00955 {
00956     double  threshold;
00957     double  lo_cut, hi_cut;
00958     double  lo_cut_p, hi_cut_p;
00959 
00960     const float * pi      = cpl_image_get_data_const(img);
00961 
00962     int     npixs   = (ury - lly + 1) * (urx - llx + 1);
00963 
00964     cpl_mask   * mask      = cpl_mask_new(cpl_image_get_size_x(img),
00965                       cpl_image_get_size_y(img));
00966     cpl_binary * badpixels = cpl_mask_get_data(mask);
00967 
00968     int i, j, h;
00969     int pos;
00970 
00971     cpl_stats * stats =
00972     cpl_stats_new_from_image_window(img,
00973                     CPL_STATS_MEAN | CPL_STATS_STDEV,
00974                     llx, lly, urx, ury);
00975 
00976     double  mean  = cpl_stats_get_mean(stats);
00977     double  stdev = cpl_stats_get_stdev(stats);
00978 
00979     double  var_sum;
00980     cpl_stats_delete(stats);
00981 
00982     var_sum = stdev * stdev * (npixs - 1);
00983 
00984     threshold = kappa * stdev;
00985     lo_cut = mean - threshold;
00986     hi_cut = mean + threshold;
00987 
00988     lo_cut_p = lo_cut;
00989     hi_cut_p = hi_cut;
00990 
00991     for (h = 0; h < nclip; h++) {
00992 
00993     for (j = lly - 1 ; j < ury ; j++) {
00994         pos = (llx - 1) + j * cpl_image_get_size_x(img);
00995         for (i = llx - 1 ; i < urx ; i++) {
00996         if (badpixels[pos] == CPL_BINARY_0 &&
00997             (pi[pos] > hi_cut || pi[pos] < lo_cut)) {
00998 
00999             const double delta = (double)pi[pos] - mean;
01000             badpixels[pos] = CPL_BINARY_1;
01001 
01002             var_sum  -= npixs * delta * delta / (npixs - 1.0);
01003             mean     += delta / (npixs - 1.0);
01004             npixs--;
01005 
01006             stdev = sqrt(var_sum / (double)(npixs - 1));
01007 
01008             lo_cut_p = lo_cut;
01009             hi_cut_p = hi_cut;
01010 
01011             threshold = kappa * stdev;
01012             lo_cut = mean - threshold;
01013             hi_cut = mean + threshold;
01014 
01015             if (lo_cut < lo_cut_p) lo_cut_p = lo_cut;
01016             if (hi_cut > hi_cut_p) hi_cut_p = hi_cut;
01017 
01018         }
01019         pos++;
01020         }
01021     }
01022 
01023     if(fabs(lo_cut - lo_cut_p) < tolerance &&
01024        fabs(hi_cut - hi_cut_p) < tolerance)
01025         break;
01026     }
01027 
01028     *clean_mean  = mean;
01029     *clean_stdev = stdev;
01030 
01031     cpl_mask_delete(mask);
01032 
01033     return cpl_error_get_code();
01034 }
01035 
01036 /*---------------------------------------------------------------------------*/
01037 
01038 /*
01039  * @brief  Retrieve input parameters
01040  * @param  pipeline_name        Input image
01041  * @param  recipe_name          Input image
01042  * @param  parlist              Shift to apply on the x-axis
01043  * @return CPL_ERROR_NONE on success.
01044  */
01045 
01046 /*---------------------------------------------------------------------------*/
01047 cpl_error_code
01048 irplib_detmon_ronbias(cpl_frameset * frameset,
01049                       const cpl_parameterlist * parlist,
01050                       const char *tag,
01051                       const char *recipe_name,
01052                       const char *pipeline_name,
01053                       const char *pafregexp,
01054                       const char *procatg_master,
01055                       const char *procatg_xstr,
01056                       const char *procatg_ystr,
01057                       const char *procatg_synth,
01058                       const char *procatg_bpmhot,
01059                       const char *procatg_bpmcold,
01060                       const char *procatg_bpmdev,
01061                       const char *package,
01062                       int (*compare) (const cpl_frame *, const cpl_frame *))
01063 {
01064 
01065     int                     nsets;
01066     int                     i;
01067 
01068     int                    * selection  = NULL;
01069     cpl_frameset           * cur_fset   = NULL;
01070     cpl_propertylist       * qclist     = NULL;
01071     cpl_image              * synthetic  = NULL;
01072     cpl_image              * masterbias = NULL;
01073     cpl_imagelist          * rawbiases  = NULL;
01074     cpl_mask               * bpmhot     = NULL;
01075     cpl_mask               * bpmcold    = NULL;
01076     cpl_mask               * bpmdev     = NULL;
01077 
01078     if(irplib_detmon_ronbias_dfs_set_groups(frameset, tag)) {
01079         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
01080     }
01081 
01082     /*
01083      * First of all test the entries.
01084      * See if the selected method(s) is/are appliable.
01085      * See if necessary parameters for those selected have been provided.
01086      */
01087 
01088 /*    clreturn_if(irplib_detmon_ronbias_test_entries());
01089 */
01090     /*
01091      * This function reads all inputs parameters from parlist
01092      * and stores them in a global variable detmon_ronbias_config.
01093      * Similar to irplib_detmon_lg_retrieve_parlist(). See irplib_detmon.c
01094      */
01095     irplib_detmon_ronbias_retrieve_parlist(pipeline_name,
01096                                           recipe_name, parlist);
01097 
01098 
01099     /* Labelise all input frames */
01100     if(compare == NULL)
01101         nsets = 1;
01102     else {
01103         cpl_msg_info(cpl_func, "Identify the different settings");
01104         selection = cpl_frameset_labelise(frameset, compare, &nsets);
01105         if(selection == NULL)
01106             cpl_msg_error(cpl_func, "Cannot labelise input frames");
01107     }
01108 
01109     /* Extract settings and reduce each of them */
01110     for(i = 0; i < nsets; i++) {
01111     int  j;
01112     int first_ext = 0;
01113     int last_ext  = 1;
01114 
01115        detmon_ronbias_config.nb_extensions = 1;
01116 
01117     /* Reduce data set nb i */
01118     cpl_msg_info(cpl_func, "Reduce data set nb %d out of %d",
01119              i + 1, nsets);
01120 
01121     cur_fset = nsets == 1 ?
01122         cpl_frameset_duplicate(frameset) : 
01123         cpl_frameset_extract(frameset, selection, i);   
01124     skip_if(cur_fset == NULL);
01125 
01126        if(detmon_ronbias_config.exts > 0) {
01127        first_ext = detmon_ronbias_config.exts;
01128        last_ext  = first_ext + 1;
01129        } else if(detmon_ronbias_config.exts < 0) {
01130           const cpl_frame        *cur_frame =
01131              cpl_frameset_get_first_const(cur_fset);
01132           /* Get the nb of extensions */
01133           detmon_ronbias_config.nb_extensions =
01134              cpl_frame_get_nextensions(cur_frame);
01135       first_ext = 1;
01136       last_ext = detmon_ronbias_config.nb_extensions + 1; 
01137        }
01138 
01139        if (last_ext - first_ext > 1) {
01140        skip_if(irplib_detmon_ronbias_save(parlist, frameset,
01141                           recipe_name,
01142                           pipeline_name, pafregexp,
01143                           procatg_master, procatg_xstr,
01144                           procatg_ystr, procatg_synth,
01145                           procatg_bpmhot,
01146                           procatg_bpmcold, procatg_bpmdev,
01147                           package, NULL, NULL, NULL,
01148                           NULL, NULL, NULL,
01149                           0, 0, cur_fset, 0));
01150        }
01151 
01152        for(j = first_ext; j < last_ext; j++) {
01153        int whichext;
01154 
01155        qclist = cpl_propertylist_new();
01156 
01157        rawbiases
01158            = cpl_imagelist_load_frameset(cur_fset,
01159                          CPL_TYPE_FLOAT, 1, j);
01160        skip_if(rawbiases == NULL);
01161        
01162        skip_if(irplib_detmon_ronbias_check_defaults(cur_fset, j));
01163        
01164        skip_if(irplib_detmon_ronbias_dutycycl(cur_fset, qclist));
01165        
01166        masterbias = irplib_detmon_ronbias_master(rawbiases,
01167                              &bpmhot, &bpmcold,
01168                              &bpmdev, qclist);
01169        skip_if(masterbias == NULL);
01170        
01171        /*
01172         * Following, a function corresponding each of the
01173         * possible methods is to be found.
01174         */
01175 
01176           if(detmon_ronbias_config.method_bitmask & RANDOM) {
01177 //        if(!strcmp(detmon_ronbias_config.method, "ALL")) {
01178           skip_if(irplib_detmon_ronbias_random(rawbiases, masterbias,
01179                            qclist));
01180           }
01181 
01182           if(detmon_ronbias_config.method_bitmask & HISTO) {
01183           skip_if(irplib_detmon_ronbias_histo(rawbiases, masterbias,
01184                           qclist));
01185           }
01186 
01187           if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
01188           skip_if(irplib_detmon_ronbias_preoverscan(rawbiases,
01189                             /*masterbias,*/
01190                             qclist, &synthetic));
01191           }
01192 
01193           if(detmon_ronbias_config.method_bitmask & REGION) {
01194           skip_if(irplib_detmon_ronbias_region(rawbiases, masterbias,
01195                            qclist));
01196           }
01197 
01198           /*
01199            * This function takes the QC list where all the results of the
01200            * methods applied are stored, and compares them.
01201            * No action defined yet if comparison reveals important differences.
01202            */
01203           //    irplib_detmon_ronbias_check(qclist);
01204 
01205       /* Definition of the extension of the output where to save
01206          the products. If input are multiextension but only
01207          computation on a single extension is required, it is 0 */
01208       whichext = first_ext > 1 ? 0 : j;
01209 
01210           skip_if(irplib_detmon_ronbias_save(parlist, frameset,
01211                          recipe_name,
01212                          pipeline_name, pafregexp,
01213                          procatg_master, procatg_xstr,
01214                          procatg_ystr, procatg_synth,
01215                          procatg_bpmhot,
01216                          procatg_bpmcold, procatg_bpmdev,
01217                          package, masterbias, synthetic,
01218                          bpmhot, bpmcold, bpmdev,
01219                          qclist, 0, 0, cur_fset,
01220                          whichext));
01221 
01222           cpl_image_delete(synthetic);
01223           cpl_image_delete(masterbias);
01224           cpl_mask_delete(bpmhot);
01225           cpl_mask_delete(bpmcold);
01226           cpl_mask_delete(bpmdev);
01227           cpl_imagelist_delete(rawbiases);
01228       cpl_propertylist_delete(qclist);
01229 
01230       qclist     = NULL;
01231       rawbiases  = NULL;
01232       masterbias = NULL;
01233       bpmhot     = NULL;
01234       bpmcold    = NULL;
01235       bpmdev     = NULL;
01236       synthetic  = NULL;
01237        } /* for each extension */
01238 
01239        cpl_frameset_delete(cur_fset);
01240        cur_fset = NULL;
01241 
01242     } /* for each setting */
01243 
01244     end_skip;
01245 
01246     cpl_free(selection);
01247 
01248     cpl_frameset_delete(cur_fset);
01249 
01250     cpl_image_delete(synthetic);
01251     cpl_image_delete(masterbias);
01252     cpl_mask_delete(bpmhot);
01253     cpl_mask_delete(bpmcold);
01254     cpl_mask_delete(bpmdev);
01255     cpl_imagelist_delete(rawbiases);
01256     cpl_propertylist_delete(qclist);
01257 
01258     return cpl_error_get_code();
01259 }
01260 
01261 /*---------------------------------------------------------------------------*/
01262 
01263 /*
01264  * @brief  Retrieve input parameters
01265  * @param  pipeline_name        Input image
01266  * @param  recipe_name          Input image
01267  * @param  parlist              Shift to apply on the x-axis
01268  * @return CPL_ERROR_NONE on success.
01269  */
01270 
01271 /*---------------------------------------------------------------------------*/
01272 static cpl_error_code
01273 irplib_detmon_ronbias_random(const cpl_imagelist * rawbiases,
01274                  const cpl_image     * masterbias,
01275                              cpl_propertylist    * qclist)
01276 {
01277     int                     nraws = cpl_imagelist_get_size(rawbiases);
01278     int                     i;
01279     double                  bias = DBL_MAX;  /* Avoid (false) uninit warning */
01280     double                  bias_error;
01281 
01282     double                  ron_error;
01283     double                 *ron =
01284         (double *) cpl_malloc(sizeof(double) * nraws);
01285 
01286     cpl_vector             *v;
01287     double stdev;
01288     cpl_error_code error;
01289 
01290     /* As we are applying to diff frames instead of raw frames,
01291        there is one less to compute on */
01292     if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) {
01293     nraws--;
01294     /* As we are applying to diff frames instead of raw frames,
01295        there is one less to compute on */
01296     for(i = 0; i < nraws; i++) {
01297         const cpl_image        *c1_raw =
01298         cpl_imagelist_get_const(rawbiases, i);
01299         const cpl_image        *c2_raw =
01300         cpl_imagelist_get_const(rawbiases, i + 1);
01301         /*FIXME: See if const modifier is necessary */
01302         const cpl_image        *c_raw = cpl_image_subtract_create(c1_raw,
01303                                       c2_raw);
01304         cpl_flux_get_noise_window(c_raw, NULL,
01305                       detmon_ronbias_config.random_sizex / 2,
01306                       detmon_ronbias_config.random_nsamples,
01307                       ron + i, &ron_error);
01308         cpl_image_delete((cpl_image*)c_raw);
01309 
01310     }
01311     } else {
01312     for(i = 0; i < nraws; i++) {
01313         const cpl_image        *c_raw = cpl_imagelist_get_const(rawbiases, i);
01314 
01315         cpl_flux_get_noise_window(c_raw, NULL,
01316                       detmon_ronbias_config.random_sizex / 2,
01317                       detmon_ronbias_config.random_nsamples,
01318                       ron + i, &ron_error);
01319     }
01320     }
01321 
01322     /*FIXME: Calls to noise_window could be out from if() and
01323       coded only once */
01324 
01325     irplib_flux_get_bias_window(masterbias, NULL,
01326                 detmon_ronbias_config.random_sizex / 2,
01327                 detmon_ronbias_config.random_nsamples,
01328                 &bias, &bias_error);
01329 
01330     v = cpl_vector_wrap(nraws, ron);
01331     stdev = cpl_vector_get_median_const(v);
01332     cpl_vector_unwrap(v);
01333 
01334     cpl_free(ron);
01335 
01336     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS RANDOM VAL", bias);
01337     cpl_ensure_code(!error, error);
01338     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS RANDOM RON", stdev);    //ron_error); //stdev);
01339     cpl_ensure_code(!error, error);
01340     return cpl_error_get_code();
01341 }
01342 
01343 static cpl_error_code
01344 irplib_detmon_ronbias_histo(const cpl_imagelist * rawbiases,
01345                 const cpl_image * masterbias,
01346                             cpl_propertylist * qclist)
01347 {
01348     int                     nraws = cpl_imagelist_get_size(rawbiases);
01349     int                     i;
01350 
01351     double mbias = DBL_MAX;
01352     double mfwhm = DBL_MAX;
01353     double mmax = DBL_MAX;
01354 
01355     cpl_vector * fwhms;
01356     cpl_vector * maxs;
01357 
01358     double mean_fwhm = DBL_MAX;
01359 
01360     if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) nraws--;
01361 
01362     fwhms = cpl_vector_new(nraws);
01363     maxs = cpl_vector_new(nraws);
01364 
01365     for(i = 0; i < nraws; i++) {
01366     /*FIXME: See if it is necessary to have const */
01367     const cpl_image * c_raw;
01368     double bias = DBL_MAX;
01369     double fwhm = DBL_MAX;
01370     double max = DBL_MAX;
01371 
01372     if(strcmp(detmon_ronbias_config.pmethod, "DIF")) {
01373            c_raw = cpl_imagelist_get_const(rawbiases, i);
01374     } else {
01375         const cpl_image        *c1_raw = cpl_imagelist_get_const(rawbiases, i);
01376         const cpl_image        * c2_raw = cpl_imagelist_get_const(rawbiases, i+1);
01377         c_raw = cpl_image_subtract_create(c1_raw, c2_raw);
01378     }
01379 
01380     skip_if(irplib_detmon_ronbias_histo_reduce(c_raw, &bias, &fwhm, &max));
01381 
01382     skip_if(bias == DBL_MAX || fwhm == DBL_MAX || max == DBL_MAX);
01383 
01384     if(!strcmp(detmon_ronbias_config.pmethod, "DIF"))
01385         cpl_image_delete((cpl_image *)c_raw);
01386 
01387         skip_if(cpl_vector_set(maxs, i, max));
01388         skip_if(cpl_vector_set(fwhms, i, fwhm));
01389 
01390         //cpl_msg_error(cpl_func, "%d", irplib_hist_get_size(hist));
01391 //      char *       name = cpl_sprintf("hist_pr%d.fits", i);
01392     //      cpl_table * table = irplib_hist_cast_table(hist);
01393     //cpl_table_save(table, NULL, NULL, name, CPL_IO_DEFAULT);
01394 //      cpl_table_delete(table);
01395     }
01396 
01397     skip_if(cpl_vector_divide_scalar(fwhms, HIST_FACT));
01398 
01399     irplib_detmon_ronbias_histo_reduce(masterbias, &mbias, &mfwhm, &mmax);
01400 
01401     skip_if(mbias == DBL_MAX || mfwhm == DBL_MAX || mmax == DBL_MAX);
01402 
01403     skip_if(cpl_propertylist_append_double(qclist, "ESO QC BIAS HISTO VAL",
01404                                            mbias));
01405     mean_fwhm = cpl_vector_get_mean(fwhms);
01406 
01407     skip_if(mean_fwhm == DBL_MAX);
01408     skip_if(cpl_error_get_code());
01409 
01410     skip_if(cpl_propertylist_append_double(qclist, "ESO QC BIAS HISTO RON",
01411                        mean_fwhm));
01412     //  skip_if(cpl_propertylist_append_double(qclist,
01413 //                     "ESO QC BIAS HISTO RMS STDEV",
01414                        //              cpl_vector_get_stdev(fwhms)));
01415 //    skip_if(cpl_propertylist_append_double(qclist, "ESO QC BIAS HISTO MAX",
01416     //                                         cpl_vector_get_mean(maxs)));
01417 //    skip_if(cpl_propertylist_append_double(qclist,
01418     //                 "ESO QC BIAS HISTO MAX STDEV",
01419     //                 cpl_vector_get_stdev(maxs)));
01420 
01421     end_skip;
01422 
01423     cpl_vector_delete(fwhms);
01424     cpl_vector_delete(maxs);
01425 
01426     return cpl_error_get_code();
01427 }
01428 
01429 static cpl_error_code
01430 irplib_detmon_ronbias_histo_reduce(const cpl_image * c_raw,
01431                    double * bias,
01432                    double * fwhm,
01433                    double * max)
01434 {
01435 //    int                     j, k;
01436     unsigned long           uj;
01437 //    int                     rej;
01438     irplib_hist            *hist;
01439     unsigned long           maxwhere = 0;
01440     unsigned long           maxf;
01441 
01442     double mean, stdev;
01443     cpl_image * dupi;
01444     unsigned long           x1a = 1;
01445     unsigned long           x2a = 1;
01446 
01447     double                  x1 = 0;
01448     double                  x2 = 0;
01449 
01450     double                  maxwhere_interp;
01451     double                  max_interp;
01452     double a, b, c;
01453     cpl_matrix * coeffs =cpl_matrix_new(3, 3);
01454     cpl_matrix * rhs    =cpl_matrix_new(3, 1);
01455     int p, q;
01456     cpl_matrix * result = NULL;
01457     cpl_error_code error;
01458 
01459     mean = cpl_image_get_mean(c_raw);
01460     stdev = cpl_image_get_stdev(c_raw);
01461     dupi = cpl_image_duplicate(c_raw);
01462 
01463 //        char                   *name;
01464 
01465     /* The following 2 nested-for(s) are used to remove
01466        contribution of bad pixels. Still to be decided if it
01467        is needed or not */
01468 /*    for(j = 1; j <= cpl_image_get_size_x(c_raw); j++) {
01469     for(k = 1; k <= cpl_image_get_size_y(c_raw); k++) {
01470         if(fabs(cpl_image_get(c_raw, j, k, &rej) - mean) > stdev * 3)
01471         cpl_image_set(dupi, j, k, mean);
01472     }
01473     }
01474 */
01475     // hist = irplib_hist_new_from_image(c_raw);
01476     hist = irplib_hist_new();
01477     error = irplib_hist_fill(hist, dupi);
01478     cpl_ensure_code(!error, error);
01479 
01480     cpl_image_delete(dupi);
01481 
01482     maxf = irplib_hist_get_max(hist, &maxwhere);
01483 
01484     for( p = 0; p< 3; p++){
01485     unsigned long bi = irplib_hist_get_value(hist, maxwhere-1+p);
01486     cpl_matrix_set(rhs, p, 0, bi);
01487     for( q= 0; q< 3; q++) {
01488         cpl_matrix_set(coeffs, p,q,pow((maxwhere-1+p),q));
01489     }
01490     }
01491 
01492     result = cpl_matrix_solve(coeffs, rhs);
01493 
01494     a = cpl_matrix_get(result, 2, 0);
01495     b = cpl_matrix_get(result, 1, 0);
01496     c = cpl_matrix_get(result, 0, 0);
01497 
01498     maxwhere_interp = -0.5 * b / (2 * a);
01499     max_interp = -1 * b * b / (4 * a) + c;
01500 
01501     cpl_matrix_delete(coeffs);
01502     cpl_matrix_delete(rhs);
01503     cpl_matrix_delete(result);
01504 
01505     /* Look for the points of half-maximum */
01506     for(uj = 0; uj < maxwhere; uj++) {
01507     if(irplib_hist_get_value(hist, uj)     <= max_interp / 2 &&
01508        irplib_hist_get_value(hist, uj + 1) >  max_interp / 2) {
01509         x1a = uj;
01510     }
01511     }
01512     for(uj = maxwhere; uj < irplib_hist_get_nbins(hist)-1; uj++) {
01513     if(irplib_hist_get_value(hist, uj)     >= max_interp / 2 &&
01514        irplib_hist_get_value(hist, uj + 1) <  max_interp / 2) {
01515         x2a = uj;
01516     }
01517     }
01518 
01519 //    if(points != 2) {
01520 //       cpl_msg_error(cpl_func, "points %d Couldn't compute FWHM", points);
01521 //  irplib_hist_delete(hist);
01522 //  return CPL_ERROR_DATA_NOT_FOUND;
01523 //    }
01524 
01525     x1 = (max_interp / 2 - irplib_hist_get_value(hist, x1a)) /
01526     (irplib_hist_get_value(hist, x1a + 1) -
01527      irplib_hist_get_value(hist, x1a)) + x1a;
01528     x2 = (max_interp / 2 - irplib_hist_get_value(hist, x2a)) /
01529     (irplib_hist_get_value(hist, x2a + 1) -
01530      irplib_hist_get_value(hist, x2a)) + x2a;
01531 
01532     *fwhm = (x2 - x1) * irplib_hist_get_bin_size(hist);
01533 
01534     *max = max_interp;
01535 
01536     *bias =  maxwhere_interp * irplib_hist_get_bin_size(hist) +
01537                            irplib_hist_get_start(hist);
01538 
01539     irplib_hist_delete(hist);
01540 
01541     return cpl_error_get_code();
01542 }
01543 /*---------------------------------------------------------------------------*/
01544 
01545 /*
01546  * @brief  Retrieve input parameters
01547  * @param  pipeline_name        Input image
01548  * @param  recipe_name          Input image
01549  * @param  parlist              Shift to apply on the x-axis
01550  * @return CPL_ERROR_NONE on success.
01551  */
01552 
01553 /*---------------------------------------------------------------------------*/
01554 static cpl_error_code
01555 irplib_detmon_ronbias_preoverscan(const cpl_imagelist * rawbiases,
01556 //                const cpl_image * masterbias,
01557                                   cpl_propertylist * qclist,
01558                                   cpl_image ** synthetic)
01559 {
01560     int                     i;
01561     int                     nx, ny;
01562     int                     nraws;
01563 
01564     cpl_vector             *meanspre;
01565     cpl_vector             *medspre;
01566     cpl_vector             *rmsspre;
01567     cpl_vector             *meansover;
01568     cpl_vector             *medsover;
01569     cpl_vector             *rmssover;
01570 
01571     cpl_error_code          error;
01572 
01573     nraws = cpl_imagelist_get_size(rawbiases);
01574     cpl_ensure_code(nraws != -1, CPL_ERROR_ILLEGAL_INPUT);
01575 
01576     meanspre = cpl_vector_new(nraws);
01577     medspre = cpl_vector_new(nraws);
01578     rmsspre = cpl_vector_new(nraws);
01579     meansover = cpl_vector_new(nraws);
01580     medsover = cpl_vector_new(nraws);
01581     rmssover = cpl_vector_new(nraws);
01582 
01583     nx = cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
01584     ny = cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
01585     cpl_ensure_code(nx != -1 && ny != -1, CPL_ERROR_ILLEGAL_INPUT);
01586 
01587     if(nx < detmon_ronbias_config.prescan_urx ||
01588        nx < detmon_ronbias_config.overscan_urx ||
01589        ny < detmon_ronbias_config.prescan_ury ||
01590        ny < detmon_ronbias_config.overscan_ury) {
01591         cpl_msg_warning(cpl_func, "PREOVERSCAN method not applied. Given "
01592                         "limits of prescan and overscan area "
01593                         "exceed image size. Please check and rerun.");
01594         return CPL_ERROR_NONE;
01595     }
01596 
01597     for(i = 0; i < nraws; i++) {
01598         double                  mean = 0;
01599         double                  stdev = 0;
01600 
01601         cpl_image              *prescan = NULL;
01602         cpl_image              *overscan = NULL;
01603 
01604         const cpl_image        *c_raw = cpl_imagelist_get_const(rawbiases, i);
01605 
01606         cpl_ensure_code(c_raw != NULL, CPL_ERROR_ILLEGAL_INPUT);
01607 
01608         prescan =
01609             cpl_image_extract(c_raw,
01610                               detmon_ronbias_config.prescan_llx,
01611                               detmon_ronbias_config.prescan_lly,
01612                               detmon_ronbias_config.prescan_urx,
01613                               detmon_ronbias_config.prescan_ury);
01614         cpl_ensure_code(prescan != NULL, CPL_ERROR_ILLEGAL_INPUT);
01615         overscan =
01616             cpl_image_extract(c_raw,
01617                               detmon_ronbias_config.overscan_llx,
01618                               detmon_ronbias_config.overscan_lly,
01619                               detmon_ronbias_config.overscan_urx,
01620                               detmon_ronbias_config.overscan_ury);
01621         cpl_ensure_code(overscan != NULL, CPL_ERROR_ILLEGAL_INPUT);
01622 
01623         if(i == 0) {
01624             *synthetic = irplib_detmon_build_synthetic(prescan, overscan);
01625             cpl_msg_info(cpl_func, "Creating SYNTHETIC frame");
01626             if(*synthetic == NULL) {
01627                 cpl_msg_error(cpl_func, "Error creating SYNTHETIC frame");
01628                 return CPL_ERROR_UNSPECIFIED;
01629             }
01630         }
01631 
01632         error = irplib_get_clean_mean_window(c_raw,
01633                                              detmon_ronbias_config.
01634                                              prescan_llx,
01635                                              detmon_ronbias_config.
01636                                              prescan_lly,
01637                                              detmon_ronbias_config.
01638                                              prescan_urx,
01639                                              detmon_ronbias_config.
01640                                              prescan_ury,
01641                                              (double) detmon_ronbias_config.
01642                                              stacking_ks_low,
01643                                              detmon_ronbias_config.
01644                                              stacking_ks_iter, 1e-5,
01645                          &mean, &stdev);
01646         cpl_ensure_code(!error, error);
01647 
01648         cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
01649 
01650         error = cpl_vector_set(medspre, i, cpl_image_get_median(prescan));
01651         cpl_ensure_code(!error, error);
01652         //        cpl_vector_set(meanspre, i, cpl_image_get_mean(prescan));
01653         //        cpl_vector_set(rmsspre,  i, cpl_image_get_stdev(prescan));
01654         error = cpl_vector_set(meanspre, i, mean);
01655         cpl_ensure_code(!error, error);
01656         error = cpl_vector_set(rmsspre, i, stdev);
01657         cpl_ensure_code(!error, error);
01658         error = irplib_get_clean_mean_window(c_raw,
01659                                              detmon_ronbias_config.
01660                                              overscan_llx,
01661                                              detmon_ronbias_config.
01662                                              overscan_lly,
01663                                              detmon_ronbias_config.
01664                                              overscan_urx,
01665                                              detmon_ronbias_config.
01666                                              overscan_ury,
01667                                              (double) detmon_ronbias_config.
01668                                              stacking_ks_low,
01669                                              detmon_ronbias_config.
01670                                              stacking_ks_iter, 1e-5,
01671                          &mean, &stdev);
01672         cpl_ensure_code(!error, error);
01673 
01674         cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
01675 
01676         error = cpl_vector_set(medsover, i, cpl_image_get_median(overscan));
01677         cpl_ensure_code(!error, error);
01678 
01679         //        cpl_vector_set(meansover, i, cpl_image_get_mean(overscan));
01680         //        cpl_vector_set(rmssover,  i, cpl_image_get_stdev(overscan));
01681         error = cpl_vector_set(meansover, i, mean);
01682         cpl_ensure_code(!error, error);
01683         error = cpl_vector_set(rmssover, i, stdev);
01684         cpl_ensure_code(!error, error);
01685 
01686         cpl_image_delete(prescan);
01687         cpl_image_delete(overscan);
01688     }
01689 
01690     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS PRESCAN MEAN",
01691                                            cpl_vector_get_mean(meanspre));
01692     cpl_ensure_code(!error, error);
01693     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS PRESCAN MED",
01694                                            cpl_vector_get_mean(medspre));
01695     cpl_ensure_code(!error, error);
01696     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS PRESCAN RON",
01697                                            cpl_vector_get_mean(rmsspre));
01698     cpl_ensure_code(!error, error);
01699 
01700     error =
01701         cpl_propertylist_append_double(qclist, "ESO QC BIAS OVERSCAN MEAN",
01702                                        cpl_vector_get_mean(meansover));
01703     cpl_ensure_code(!error, error);
01704     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS OVERSCAN MED",
01705                                            cpl_vector_get_mean(medsover));
01706     cpl_ensure_code(!error, error);
01707     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS OVERSCAN RON",
01708                                            cpl_vector_get_mean(rmssover));
01709     cpl_ensure_code(!error, error);
01710 
01711     /* The following seems not to be necessary.
01712        Pending of revision to be removed */
01713     /*
01714     error =
01715         cpl_propertylist_append_double(qclist,
01716                                        "ESO QC BIAS PRESCAN MEAN STDEV",
01717                                        cpl_vector_get_stdev(meanspre));
01718     cpl_ensure_code(!error, error);
01719     error =
01720         cpl_propertylist_append_double(qclist,
01721                                        "ESO QC BIAS PRESCAN MED STDEV",
01722                                        cpl_vector_get_stdev(medspre));
01723     cpl_ensure_code(!error, error);
01724     error =
01725         cpl_propertylist_append_double(qclist,
01726                                        "ESO QC BIAS PRESCAN RMS STDEV",
01727                                        cpl_vector_get_stdev(rmsspre));
01728     cpl_ensure_code(!error, error);
01729 
01730     error =
01731         cpl_propertylist_append_double(qclist,
01732                                        "ESO QC BIAS OVERSCAN MEAN STDEV",
01733                                        cpl_vector_get_stdev(meansover));
01734     cpl_ensure_code(!error, error);
01735     error =
01736         cpl_propertylist_append_double(qclist,
01737                                        "ESO QC BIAS OVERSCAN MED STDEV",
01738                                        cpl_vector_get_stdev(medsover));
01739     cpl_ensure_code(!error, error);
01740     error =
01741         cpl_propertylist_append_double(qclist,
01742                                        "ESO QC BIAS OVERSCAN RMS STDEV",
01743                                        cpl_vector_get_stdev(rmssover));
01744     cpl_ensure_code(!error, error);
01745     */
01746 
01747     cpl_vector_delete(meanspre);
01748     cpl_vector_delete(medspre);
01749     cpl_vector_delete(rmsspre);
01750     cpl_vector_delete(meansover);
01751     cpl_vector_delete(medsover);
01752     cpl_vector_delete(rmssover);
01753 
01754     return CPL_ERROR_NONE;
01755 }
01756 
01757 /*---------------------------------------------------------------------------*/
01758 
01759 /*
01760  * @brief  Retrieve input parameters
01761  * @param  pipeline_name        Input image
01762  * @param  recipe_name          Input image
01763  * @param  parlist              Shift to apply on the x-axis
01764  * @return CPL_ERROR_NONE on success.
01765  */
01766 
01767 /*---------------------------------------------------------------------------*/
01768 static cpl_error_code
01769 irplib_detmon_ronbias_region(const cpl_imagelist * rawbiases,
01770                  const cpl_image * masterbias,
01771                              cpl_propertylist * qclist)
01772 {
01773 
01774     int                     nraws = cpl_imagelist_get_size(rawbiases);
01775     int                     i;
01776 
01777     int                     nx =
01778         cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
01779     int                     ny =
01780         cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
01781 
01782     cpl_vector *rmssreg;
01783     cpl_error_code          error;
01784 
01785     const cpl_image * c_raw;
01786     double median, mbias, mstdev;
01787 
01788     if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) nraws--;
01789 
01790     rmssreg = cpl_vector_new(nraws);
01791 
01792     if(nx < detmon_ronbias_config.ref_urx ||
01793        ny < detmon_ronbias_config.ref_ury) {
01794         cpl_msg_warning(cpl_func, "REGION method not applied. Given "
01795                         "limits of prescan and overscan area "
01796                         "exceed image size. Please check and rerun.");
01797         return CPL_ERROR_NONE;
01798     }
01799 
01800     for(i = 0; i < nraws; i++) {
01801         double                  mean = 0;
01802         double                  stdev = 0;
01803     if(strcmp(detmon_ronbias_config.pmethod, "DIF")) {
01804         c_raw = cpl_imagelist_get_const(rawbiases, i);
01805     } else {
01806         const cpl_image        *c1_raw = cpl_imagelist_get_const(rawbiases, i);
01807         const cpl_image        * c2_raw = cpl_imagelist_get_const(rawbiases, i+1);
01808         c_raw = cpl_image_subtract_create(c1_raw, c2_raw);
01809     }
01810         error = irplib_get_clean_mean_window(c_raw,
01811                                              detmon_ronbias_config.ref_llx,
01812                                              detmon_ronbias_config.ref_lly,
01813                                              detmon_ronbias_config.ref_urx,
01814                                              detmon_ronbias_config.ref_ury,
01815                                              (double) detmon_ronbias_config.
01816                                              stacking_ks_low,
01817                                              detmon_ronbias_config.
01818                                              stacking_ks_iter, 1e-5,
01819                          &mean, &stdev);
01820         cpl_ensure_code(!error, error);
01821         /*        cpl_vector_set(rmssreg, i, cpl_image_get_stdev_window(c_raw,
01822            detmon_ronbias_config.ref_llx,
01823            detmon_ronbias_config.ref_lly,
01824            detmon_ronbias_config.ref_urx,    
01825            detmon_ronbias_config.ref_ury));
01826          */
01827         error = cpl_vector_set(rmssreg, i, stdev);
01828         cpl_ensure_code(!error, error);
01829     if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) cpl_image_delete((cpl_image *)c_raw);
01830     }
01831 
01832     median =  cpl_image_get_median_window(masterbias,
01833                       detmon_ronbias_config.ref_llx,
01834                       detmon_ronbias_config.ref_lly,
01835                       detmon_ronbias_config.ref_urx,
01836                       detmon_ronbias_config.ref_ury);
01837     error = irplib_get_clean_mean_window(masterbias,
01838                      detmon_ronbias_config.ref_llx,
01839                      detmon_ronbias_config.ref_lly,
01840                      detmon_ronbias_config.ref_urx,
01841                      detmon_ronbias_config.ref_ury,
01842                      (double) detmon_ronbias_config.
01843                      stacking_ks_low,
01844                      detmon_ronbias_config.
01845                      stacking_ks_iter, 1e-5,
01846                      &mbias, &mstdev);
01847 
01848     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION MED",
01849                                            median);
01850     cpl_ensure_code(!error, error);
01851 
01852     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION VAL",
01853                                            mbias);
01854     cpl_ensure_code(!error, error);
01855     error = cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION RON",
01856                                            cpl_vector_get_mean(rmssreg));
01857     cpl_ensure_code(!error, error);
01858     /*
01859     error =
01860         cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION RMS STDEV",
01861                                        cpl_vector_get_stdev(rmssreg));
01862     cpl_ensure_code(!error, error);
01863     */
01864     cpl_vector_delete(rmssreg);
01865 
01866     return cpl_error_get_code();
01867 }
01868 
01869 /*---------------------------------------------------------------------------*/
01870 
01871 /*
01872  * @brief  Retrieve input parameters
01873  * @param  pipeline_name        Input image
01874  * @param  recipe_name          Input image
01875  * @param  parlist              Shift to apply on the x-axis
01876  * @return CPL_ERROR_NONE on success.
01877  */
01878 
01879 /*---------------------------------------------------------------------------*/
01880 static cpl_image *
01881 irplib_detmon_ronbias_master(const cpl_imagelist * rawbiases,
01882                  cpl_mask ** bpmhot, cpl_mask ** bpmcold,
01883                  cpl_mask ** bpmdev, cpl_propertylist * qclist)
01884 {
01885     double                  mean = 0;
01886     double                  stdev = 0;
01887     cpl_image              *masterbias = NULL;
01888     double dark_med, stdev_med,lower, upper;
01889     int hotpix_nb, coldpix_nb, devpix_nb;                   
01890     cpl_image * stdev_im = NULL;
01891 
01892     if(!strcmp(detmon_ronbias_config.stacking_method, "MEAN"))
01893         masterbias = cpl_imagelist_collapse_create(rawbiases);
01894     if(!strcmp(detmon_ronbias_config.stacking_method, "MINMAX"))
01895         masterbias =
01896             cpl_imagelist_collapse_minmax_create(rawbiases, 0, 10000);
01897     if(!strcmp(detmon_ronbias_config.stacking_method, "KSIGMA"))
01898         masterbias = cpl_imagelist_collapse_sigclip_create(rawbiases, 3);
01899     if(!strcmp(detmon_ronbias_config.stacking_method, "MEDIAN"))
01900         masterbias = cpl_imagelist_collapse_median_create(rawbiases);
01901 
01902     skip_if(masterbias == NULL);
01903 
01904     skip_if(irplib_get_clean_mean_window(masterbias, 1, 1,
01905                                          cpl_image_get_size_x(masterbias),
01906                                          cpl_image_get_size_y(masterbias),
01907                                          (double) detmon_ronbias_config.
01908                                          stacking_ks_low,
01909                                          detmon_ronbias_config.
01910                                          stacking_ks_iter, 1e-5,
01911                      &mean, &stdev));
01912 
01913     skip_if(cpl_propertylist_append_double(qclist, "ESO QC MASTER MEAN",
01914                        mean));
01915     skip_if(cpl_propertylist_append_double(qclist, "ESO QC MASTER RMS",
01916                        stdev));
01917 
01918     /* Compute median-rms of the central part of the dark  */
01919     dark_med = cpl_image_get_median(masterbias);
01920 
01921     lower = dark_med - stdev * detmon_ronbias_config.stacking_ks_low;
01922     upper = dark_med + stdev * detmon_ronbias_config.stacking_ks_high;
01923 
01924     /* Create the hot pixel map */
01925     cpl_mask_delete(*bpmhot);
01926     irplib_check(*bpmhot = cpl_mask_threshold_image_create(masterbias,
01927                                upper, DBL_MAX),
01928                  "Cannot compute the hot pixel map");
01929     hotpix_nb = cpl_mask_count(*bpmhot);
01930     skip_if (0);
01931 
01932     /* Create the cold pixel map */
01933     cpl_mask_delete(*bpmcold);
01934     irplib_check(*bpmcold = cpl_mask_threshold_image_create(masterbias,
01935                                 -FLT_MAX, lower),
01936                  "Cannot compute the cold pixel map");
01937     coldpix_nb = cpl_mask_count(*bpmcold);
01938     skip_if (0);
01939 
01940     /* Create the deviant pixel map */
01941     stdev_im  = irplib_imagelist_collapse_stdev_create(rawbiases);
01942     stdev_med = cpl_image_get_median(stdev_im);
01943 
01944     skip_if(irplib_get_clean_mean_window(stdev_im, 1, 1,
01945                                          cpl_image_get_size_x(stdev_im),
01946                                          cpl_image_get_size_y(stdev_im),
01947                                          (double) detmon_ronbias_config.
01948                                          stacking_ks_low,
01949                                          detmon_ronbias_config.
01950                                          stacking_ks_iter, 1e-5,
01951                      &mean, &stdev));
01952 
01953     lower = stdev_med - stdev * detmon_ronbias_config.stacking_ks_low;
01954     upper = stdev_med + stdev * detmon_ronbias_config.stacking_ks_high;
01955 
01956     cpl_mask_delete(*bpmdev);
01957     irplib_check(*bpmdev = cpl_mask_threshold_image_create(stdev_im,
01958                                lower, upper),
01959                  "Cannot compute the cold pixel map");
01960     cpl_mask_not(*bpmdev);
01961     devpix_nb = cpl_mask_count(*bpmdev);
01962     skip_if (0);
01963 
01964     skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBCOLPIX", coldpix_nb));
01965     skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBHOTPIX", hotpix_nb));
01966     skip_if(cpl_propertylist_append_int(qclist, "ESO QC NBDEVPIX", devpix_nb));
01967 
01968     end_skip;
01969 
01970     cpl_image_delete(stdev_im);
01971 
01972     if (cpl_error_get_code()) {
01973     cpl_image_delete(masterbias);
01974     masterbias = NULL;
01975     }
01976 
01977     return masterbias;
01978 }
01979 
01980 /*---------------------------------------------------------------------------*/
01981 
01982 /*
01983  * @brief  Retrieve input parameters
01984  * @param  pipeline_name        Input image
01985  * @param  recipe_name          Input image
01986  * @param  parlist              Shift to apply on the x-axis
01987  * @return CPL_ERROR_NONE on success.
01988  */
01989 
01990 /*---------------------------------------------------------------------------*/
01991 static                  cpl_error_code
01992 irplib_detmon_ronbias_save(const cpl_parameterlist * parlist,
01993                            cpl_frameset * frameset,
01994                            const char *recipe_name,
01995                            const char *pipeline_name,
01996                const char *pafregexp,
01997                            const char *procatg_master,
01998                            const char *procatg_xstr,
01999                            const char *procatg_ystr,
02000                            const char *procatg_synth,
02001                            const char *procatg_bpmhot,
02002                            const char *procatg_bpmcold,
02003                            const char *procatg_bpmdev,
02004                            const char *package,
02005                            const cpl_image * masterbias,
02006                            const cpl_image * synthetic,
02007                            const cpl_mask * bpmhot,
02008                            const cpl_mask * bpmcold,
02009                            const cpl_mask * bpmdev,
02010                            cpl_propertylist * qclist,
02011                            const int flag_sets,
02012                            const int which_set, 
02013                            cpl_frameset * usedframes,
02014                            int whichext)
02015 {
02016 
02017     cpl_frame              *ref_frame;
02018     cpl_propertylist       *plist = NULL;
02019     char                   *name_o = NULL; /* Avoid (false) uninit warning */
02020  
02021     //    cpl_frame         * product_frame;
02022     cpl_propertylist       * paflist   = NULL;
02023     cpl_propertylist       * mainplist = NULL;
02024     cpl_propertylist       * xplist    = NULL;
02025     cpl_image              * image     = NULL;
02026 
02027     cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
02028     cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
02029     cpl_ensure_code(pafregexp != NULL, CPL_ERROR_NULL_INPUT);
02030     cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
02031     cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
02032     cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
02033     cpl_ensure_code(procatg_master != NULL, CPL_ERROR_NULL_INPUT);
02034     cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
02035 
02036     /* Extract extension headers if multi-extension */
02037     if (detmon_ronbias_config.exts < 0) {
02038         const char * filename =
02039             cpl_frame_get_filename(cpl_frameset_get_first(frameset));
02040 
02041 
02042             xplist = cpl_propertylist_load_regexp(filename, whichext,
02043                                                      "ESO DET", 0);
02044         skip_if(cpl_propertylist_append(xplist, qclist));
02045     }
02046 
02047     cpl_msg_info(cpl_func,"dealing with extention %d",whichext);
02048 
02049     /* This is only used later for PAF */
02050     /* Get FITS header from reference file */
02051     ref_frame = cpl_frameset_get_first(frameset);
02052     skip_if(ref_frame == NULL);
02053 
02054     skip_if((mainplist =
02055     cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02056                   0)) == NULL);
02057 
02058     /**************************/
02059     /*  Write the MASTERBIAS  */
02060     /**************************/
02061 
02062     /* Set the file name for the table */
02063     if(!flag_sets) {
02064        name_o = cpl_sprintf("%s_masterbias.fits", recipe_name);
02065        assert(name_o != NULL);
02066     } else {
02067        name_o =
02068           cpl_sprintf("%s_masterbias_set%02d.fits", recipe_name,
02069                       which_set);
02070        assert(name_o != NULL);
02071     }
02072     /* Save the MASTERBIAS image */
02073     if (whichext == 0)
02074     skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, masterbias,
02075                              CPL_BPP_IEEE_FLOAT, recipe_name, procatg_master,
02076                   qclist, NULL, package, name_o));
02077     else
02078     skip_if(cpl_image_save(masterbias,
02079                    name_o, CPL_BPP_IEEE_FLOAT, xplist,
02080                    CPL_IO_EXTEND));
02081 
02082     /* Free */
02083     cpl_free(name_o);
02084     name_o = NULL;
02085 
02086     /*****************************/
02087     /*  Write the HOT PIXEL MAP  */
02088     /*****************************/
02089 
02090     /* Set the file name for the table */
02091     if(!flag_sets) {
02092        name_o = cpl_sprintf("%s_hotpixmap.fits", recipe_name);
02093        assert(name_o != NULL);
02094     } else {
02095        name_o =
02096           cpl_sprintf("%s_hotpixmap_set%02d.fits", recipe_name,
02097                       which_set);
02098        assert(name_o != NULL);
02099     }
02100     /* Save the HOTBPM image */
02101     skip_if(0);
02102     image = cpl_image_new_from_mask(bpmhot);
02103     cpl_error_reset();
02104 
02105     if (whichext == 0)
02106     skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, image,
02107                              CPL_BPP_IEEE_FLOAT, recipe_name, procatg_bpmhot,
02108                   qclist, NULL, package, name_o));
02109     else
02110     skip_if(cpl_image_save(image,
02111                    name_o, CPL_BPP_IEEE_FLOAT, xplist,
02112                    CPL_IO_EXTEND));
02113 
02114     /* Free */
02115     cpl_free(name_o);
02116     cpl_image_delete(image);
02117     image = NULL;
02118     name_o = NULL;
02119 
02120     /*****************************/
02121     /*  Write the COLD PIXEL MAP  */
02122     /*****************************/
02123 
02124     /* Set the file name for the table */
02125     if(!flag_sets) {
02126        name_o = cpl_sprintf("%s_coldpixmap.fits", recipe_name);
02127        assert(name_o != NULL);
02128     } else {
02129        name_o =
02130           cpl_sprintf("%s_coldpixmap_set%02d.fits", recipe_name,
02131                       which_set);
02132        assert(name_o != NULL);
02133     }
02134     /* Save the COLDBPM image */
02135     skip_if(0);
02136     image = cpl_image_new_from_mask(bpmcold);
02137     cpl_error_reset();
02138 
02139     if (whichext == 0)
02140     skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, image,
02141                              CPL_BPP_IEEE_FLOAT, recipe_name, procatg_bpmcold,
02142                   qclist, NULL, package, name_o));
02143     else
02144     skip_if(cpl_image_save(image,
02145                    name_o, CPL_BPP_IEEE_FLOAT, xplist,
02146                    CPL_IO_EXTEND));
02147 
02148     /* Free */
02149     cpl_free(name_o);
02150     cpl_image_delete(image);
02151     image = NULL;
02152     name_o = NULL;
02153 
02154     /*****************************/
02155     /*  Write the DEV PIXEL MAP  */
02156     /*****************************/
02157 
02158     /* Set the file name for the table */
02159     if(!flag_sets) {
02160        name_o = cpl_sprintf("%s_devpixmap.fits", recipe_name);
02161        assert(name_o != NULL);
02162     } else {
02163        name_o =
02164           cpl_sprintf("%s_devpixmap_set%02d.fits", recipe_name,
02165                       which_set);
02166        assert(name_o != NULL);
02167     }
02168     /* Save the DEVBPM image */
02169     skip_if(0);
02170     image = cpl_image_new_from_mask(bpmdev);
02171     cpl_error_reset();
02172 
02173     if (whichext == 0)
02174     skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, image,
02175                              CPL_BPP_IEEE_FLOAT, recipe_name, procatg_bpmdev,
02176                   qclist, NULL, package, name_o));
02177     else
02178     skip_if(cpl_image_save(image,
02179                    name_o, CPL_BPP_IEEE_FLOAT, xplist,
02180                    CPL_IO_EXTEND));
02181 
02182     /* Free */
02183     cpl_free(name_o);
02184     cpl_image_delete(image);
02185     image = NULL;
02186     name_o = NULL;
02187 
02188     /*******************************/
02189     /*  Write the SYNTHETIC        */
02190     /*******************************/
02191     if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
02192     /* Set the file name for the table */
02193     if(!flag_sets) {
02194         name_o = cpl_sprintf("%s_synthetic.fits", recipe_name);
02195         assert(name_o != NULL);
02196     } else {
02197         name_o =
02198                 cpl_sprintf("%s_synthetic_set%02d.fits", recipe_name,
02199                             which_set);
02200         assert(name_o != NULL);
02201     }
02202 
02203        if (whichext == 0)
02204           /* Save the SYNTHETIC image */
02205        skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, synthetic,
02206                       CPL_BPP_IEEE_DOUBLE, recipe_name,
02207                       procatg_synth,
02208                       qclist, NULL, package, name_o));
02209        else
02210        skip_if(cpl_image_save(synthetic, name_o, CPL_BPP_IEEE_FLOAT,
02211                   xplist, CPL_IO_EXTEND));
02212 
02213        /* Free */
02214        cpl_free(name_o);
02215        name_o = NULL;
02216     }
02217 
02218     /*******************************/
02219     /*  Write the PAF file         */
02220     /*******************************/
02221     if (qclist) {
02222     paflist = cpl_propertylist_new();
02223 
02224     /* Set the file name for the PAF */
02225     if(detmon_ronbias_config.exts >= 0) {
02226         skip_if((plist =
02227              cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02228                        detmon_ronbias_config.exts)) == NULL);
02229 
02230         if(!flag_sets) {
02231         name_o = cpl_sprintf("%s.paf", recipe_name);
02232         assert(name_o != NULL);
02233         } else {
02234         name_o = cpl_sprintf("%s_set%02d.paf",
02235                      recipe_name, which_set);
02236         assert(name_o != NULL);
02237         }
02238     } else {
02239         skip_if((plist =
02240              cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02241                        whichext)) == NULL);
02242 
02243 
02244         if(!flag_sets) {
02245         name_o = cpl_sprintf("%s_ext%02d.paf", 
02246                      recipe_name, whichext);
02247         assert(name_o != NULL);
02248         } else {
02249         name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", 
02250                      recipe_name,
02251                      which_set, whichext);
02252         assert(name_o != NULL);
02253         }
02254     }
02255 
02256     /* Get the keywords for the paf file */
02257     skip_if(cpl_propertylist_copy_property_regexp(paflist, plist,
02258                               pafregexp, 0));
02259     skip_if(cpl_propertylist_copy_property_regexp(paflist, mainplist,
02260                               pafregexp, 0));
02261 
02262     skip_if(cpl_propertylist_append(paflist, qclist));
02263 
02264     /* Save the PAF */
02265     skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, paflist, name_o));
02266 
02267     if(procatg_xstr == NULL)
02268         cpl_msg_info(cpl_func, "X Structure not created");
02269     if(procatg_ystr == NULL)
02270         cpl_msg_info(cpl_func, "Y Structure not created");
02271     }
02272     
02273     end_skip;
02274 
02275     cpl_propertylist_delete(plist);
02276     cpl_propertylist_delete(paflist);
02277     cpl_propertylist_delete(mainplist);
02278     cpl_propertylist_delete(xplist);
02279     cpl_free(name_o);
02280     cpl_image_delete(image);
02281 
02282     return cpl_error_get_code();
02283 }
02284 
02285 /*---------------------------------------------------------------------------*/
02286 
02287 /*
02288  * @brief  Retrieve input parameters
02289  * @param  pipeline_name        Input image
02290  * @param  recipe_name          Input image
02291  * @param  parlist              Shift to apply on the x-axis
02292  * @return CPL_ERROR_NONE on success.
02293  */
02294 
02295 /*---------------------------------------------------------------------------*/
02296 int
02297 irplib_detmon_ronbias_dfs_set_groups(cpl_frameset * set, const char *tag)
02298 {
02299     cpl_frame              *cur_frame;
02300     const char             *cur_tag;
02301     int                     nframes;
02302     int                     i;
02303 
02304     /* Check entries */
02305     if(set == NULL)
02306         return -1;
02307 
02308     /* Initialize */
02309     nframes = cpl_frameset_get_size(set);
02310 
02311     /* Loop on frames */
02312     for(i = 0; i < nframes; i++) {
02313         cur_frame = cpl_frameset_get_frame(set, i);
02314         cur_tag = cpl_frame_get_tag(cur_frame);
02315 
02316         /* RAW frames */
02317         if(!strcmp(cur_tag, tag))
02318             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
02319         /* CALIB frames */
02320 
02321 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
02322             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
02323 */
02324     }
02325     return 0;
02326 }
02327 
02328 /*---------------------------------------------------------------------------*/
02329 
02330 /*
02331  * @brief  Retrieve input parameters
02332  * @param  pipeline_name        Input image
02333  * @param  recipe_name          Input image
02334  * @param  parlist              Shift to apply on the x-axis
02335  * @return CPL_ERROR_NONE on success.
02336  */
02337 
02338 /*---------------------------------------------------------------------------*/
02339 static cpl_image *
02340 irplib_detmon_build_synthetic(cpl_image * prescan, cpl_image * overscan)
02341 {
02342     int                     j;
02343 
02344     int                     distance = detmon_ronbias_config.overscan_urx -
02345         detmon_ronbias_config.prescan_llx + 1;
02346 
02347     double                 *mean_x =
02348         (double *) cpl_malloc(sizeof(double) * distance);
02349 
02350     double                 *xvalues =
02351         (double *) cpl_malloc(sizeof(double) * distance);
02352 
02353     cpl_vector             *x = NULL;
02354     cpl_vector             *y = NULL;
02355 
02356     cpl_polynomial         *poly = NULL;
02357     cpl_polynomial         *poly2 = NULL;
02358 
02359     double                  mse;
02360     int                     pows[2] = { 0, 0 };
02361 
02362     cpl_image              *synthetic = NULL;
02363 
02364     double                  initial = 0;
02365 
02366     /* Initialize */
02367     for(j = 0; j < distance; j++) {
02368         *(mean_x + j) = 0;
02369         *(xvalues + j) = j;
02370     }
02371 
02372     for(j = 0; j < cpl_image_get_size_x(prescan); j++) {
02373         *(mean_x + j) =
02374             cpl_image_get_mean_window(prescan, j + 1, 1, j + 1,
02375                                       cpl_image_get_size_y(prescan));
02376     }
02377 
02378     for(j = 0; j < cpl_image_get_size_x(overscan); j++) {
02379         *(mean_x + distance - cpl_image_get_size_x(overscan) + j) =
02380             cpl_image_get_mean_window(overscan, j + 1, 1, j + 1,
02381                                       cpl_image_get_size_y(overscan));
02382     }
02383 
02384     x = cpl_vector_wrap(distance, xvalues);
02385     y = cpl_vector_wrap(distance, mean_x);
02386 
02387     poly =
02388         cpl_polynomial_fit_1d_create(x, y,
02389                                      detmon_ronbias_config.preoverscan_degree,
02390                                      &mse);
02391     cpl_vector_unwrap(x);
02392     cpl_vector_unwrap(y);
02393 
02394     initial = *mean_x;
02395 
02396     cpl_free(xvalues);
02397     cpl_free(mean_x);
02398 
02399     poly2 = cpl_polynomial_new(2);
02400 
02401     j = 0;
02402     cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
02403 
02404     pows[0] = 1;
02405     j = 1;
02406     cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
02407 
02408     cpl_polynomial_delete(poly);
02409 
02410     synthetic =
02411         cpl_image_new(distance, cpl_image_get_size_y(prescan),
02412                       CPL_TYPE_DOUBLE);
02413 
02414     if(cpl_image_fill_polynomial(synthetic, poly2, initial, 1, 1, 1)) {
02415         cpl_msg_error(cpl_func, "Error creating the synthetic frame");
02416         cpl_polynomial_delete(poly2);
02417         return NULL;
02418     }
02419 
02420     cpl_polynomial_delete(poly2);
02421 
02422     return synthetic;
02423 }
02424 
02425 /*---------------------------------------------------------------------------*/
02426 
02427 /*
02428  * @brief  Retrieve input parameters
02429  * @param  pipeline_name        Input image
02430  * @param  recipe_name          Input image
02431  * @param  parlist              Shift to apply on the x-axis
02432  * @return CPL_ERROR_NONE on success.
02433  */
02434 
02435 /*---------------------------------------------------------------------------*/
02436 static cpl_error_code
02437 irplib_detmon_ronbias_dutycycl(const cpl_frameset * frameset,
02438                                cpl_propertylist * qclist)
02439 {
02440     const cpl_frame        *first;
02441     cpl_propertylist       *plistfirst;
02442     double                  tfirst;
02443     int                     nraws;
02444     const cpl_frame        *last;
02445     cpl_propertylist       *plistlast;
02446     double                  tlast;
02447     double                  dutycycl;
02448     cpl_error_code          error;
02449 
02450     first = cpl_frameset_get_first_const(frameset);
02451     cpl_ensure_code(first != NULL, cpl_error_get_code());
02452 
02453     plistfirst = cpl_propertylist_load(cpl_frame_get_filename(first), 0);
02454     cpl_ensure_code(plistfirst != NULL, cpl_error_get_code());
02455 
02456     tfirst = cpl_propertylist_get_double(plistfirst, "MJD-OBS");
02457     cpl_ensure_code(tfirst != 0, cpl_error_get_code());
02458 
02459     nraws = cpl_frameset_get_size(frameset);
02460     cpl_ensure_code(nraws != -1, cpl_error_get_code());
02461 
02462     last = cpl_frameset_get_frame_const(frameset, nraws - 1);
02463     cpl_ensure_code(last != NULL, cpl_error_get_code());
02464 
02465     plistlast = cpl_propertylist_load(cpl_frame_get_filename(last), 0);
02466     cpl_ensure_code(plistlast != NULL, cpl_error_get_code());
02467 
02468     tlast = cpl_propertylist_get_double(plistlast, "MJD-OBS");
02469     cpl_ensure_code(tlast != 0, cpl_error_get_code());
02470 
02471     dutycycl = (tlast - tfirst) / (nraws - 1);
02472 
02473     error =
02474     cpl_propertylist_append_double(qclist, "ESO QC DUTYCYCL", dutycycl);
02475     cpl_ensure_code(!error, error);
02476 
02477     cpl_propertylist_delete(plistfirst);
02478     cpl_propertylist_delete(plistlast);
02479 
02480     return CPL_ERROR_NONE;
02481 }
02482 
02483 /*--------------------------------------------------------------------------*/
02484 
02485 /*
02486  * @brief  Reduce periodic noise
02487  * @param  image         Input image
02488  * @param  freq          Readout frequency, given in Kpixel/s.
02489  *
02490  * @return 1-d image, representing the distribution of noise. NULL if failed.
02491  */
02492 
02493 /*--------------------------------------------------------------------------*/
02494 
02495 
02496 #define HORIZONTAL TRUE
02497 
02498 cpl_table              *
02499 irplib_detmon_pernoise_reduce(cpl_image * image)
02500 {
02501     int                     nsamples, nffts;
02502     int                     i, j;
02503 
02504     int status;
02505     float * hanning;
02506     float * data;
02507     float * power;
02508     cpl_image * power_im;
02509     cpl_image * output;
02510     cpl_image * pos_spec;
02511     cpl_table * table;
02512     double freq;
02513     cpl_error_code error;
02514     cpl_image * sub_image;
02515     int nffts_old;
02516 
02517 #ifdef HAVE_FFTW
02518     fftw_complex * fourier;
02519     fftw_complex * input;
02520     fftw_plan p;
02521 #endif
02522 
02523     if(detmon_pernoise_config.direction == HORIZONTAL) {
02524         error = cpl_image_flip(image, 1);
02525         cpl_ensure(!error, error, NULL);
02526     }
02527 
02528     nsamples = cpl_image_get_size_x(image);
02529     nffts = cpl_image_get_size_y(image);
02530 
02531 
02532     /* Rewrite the previous lines with a better style (: ...) */
02533 
02534     /*
02535      * 1. preprocessing task:
02536      * Estimate the background fitting the image to a
02537      * 2-D polynomial and substract it from the image.
02538      */
02539 
02540     error = irplib_detmon_pernoise_rm_bg(image, nsamples, nffts);
02541     cpl_ensure(!error, error, NULL);
02542 /*
02543         char                   *frame_name =
02544             cpl_sprintf("poly_bg.fits");
02545         assert(frame_name != NULL);
02546         cpl_propertylist * plist = cpl_propertylist_new();
02547         cpl_propertylist_append_double(plist, "ESO DET DIT", 3);
02548 
02549         cpl_propertylist_append_double(plist, "EXPTIME", 3);
02550 
02551         cpl_image_save(image, frame_name, CPL_BPP_IEEE_FLOAT, plist,
02552                        CPL_IO_DEFAULT);
02553         cpl_propertylist_delete(plist);
02554         cpl_free(frame_name);
02555 
02556 */
02557 //    cpl_msg_error(cpl_func, "mean %f", cpl_image_get_mean(image));
02558 //    cpl_image_subtract_scalar(image, cpl_image_get_mean(image));
02559 //    cpl_msg_error(cpl_func, "mean %f", cpl_image_get_mean(image));
02560 
02561 
02562 
02563     sub_image = cpl_image_extract(image, nsamples/8 + 1, nffts/8+1,
02564                                               nsamples*7/8, nffts*7/8);
02565     nffts_old = nffts;
02566     nsamples = cpl_image_get_size_x(sub_image);
02567     nffts = cpl_image_get_size_y(sub_image);
02568 
02569 
02570     /*
02571      * 2. preprocessing task:
02572      * Remove the effect of hot and dark pixels, replacing their values by
02573      * the average value of the neighbouring pixels.
02574      */
02575 //    error = irplib_detmon_rm_bpixs(&sub_image, detmon_pernoise_config.kappa, nffts, nsamples);
02576     //  cpl_ensure(!error, error, NULL);
02577 
02578 
02579     /*
02580      * 3. preprocessing task:
02581      * Apply a Hanning vector
02582      */
02583 
02584     hanning = cpl_malloc(sizeof(float) * nsamples);
02585 
02586     for(i = 0; i < nsamples; i++) {
02587         *(hanning + i) = 0.5 - 0.5 * cos(2 * CPL_MATH_PI * (float) i / nsamples);
02588         for(j = 0; j < nffts; j++) {
02589             double                  value =
02590                 cpl_image_get(sub_image, i + 1, j + 1, &status);
02591             error = cpl_image_set(sub_image, i + 1, j + 1, (*(hanning + i)) * value);
02592             //Aqui tb habi sub_image
02593             cpl_ensure(!error, error, NULL);
02594         }
02595     }
02596 
02597     cpl_free(hanning);
02598 
02599     data = cpl_image_get_data_float(sub_image);
02600 
02601     power = (float *) cpl_calloc(sizeof(float), nsamples * nffts);
02602 
02603 #ifdef HAVE_FFTW
02604 //    fftwf_init_threads();
02605 
02606     fourier =
02607     (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nsamples*nffts);
02608 
02609     input = 
02610     (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nsamples*nffts);
02611 
02612     for(i = 0; i< nffts*nsamples; i++){
02613     *((float complex *)input + i) = data[i] + I * 0.0;
02614     }
02615 //    fftwf_plan_with_nthreads(4);
02616 
02617     p = fftw_create_plan(nsamples, FFTW_FORWARD, FFTW_ESTIMATE);
02618 
02619     fftw(p, nffts, input, 1, nsamples,
02620      fourier, 1, nsamples);
02621 
02622 /*
02623     fftw_plan p = fftwf_plan_many_dft_r2c(1, &nsamples, nffts,
02624                       data, NULL, 1, nsamples,
02625                       fourier, NULL, 1, nsamples,
02626                       FFTW_ESTIMATE);
02627 
02628     fftwf_execute(p);
02629 */
02630 
02631     fftw_destroy_plan(p);
02632 //    fftwf_cleanup_threads();
02633 
02634     for(i = 0; i < nffts; i++) {
02635         for(j = 0; j < nsamples; j++) {
02636             *(power + j + i * nsamples) = *((float complex *)fourier + j + i * nsamples) *
02637         conjf(*((float complex *)fourier +j + i * nsamples));
02638         }
02639         /* Is it necessary to divide here by 2 * pi? */
02640     }
02641 
02642     fftw_free(fourier);
02643     fftw_free(input);
02644 #endif
02645 
02646     power_im = cpl_image_wrap_float(nsamples, nffts, power);
02647     output   = cpl_image_collapse_create(power_im, 0);
02648     pos_spec = cpl_image_extract(output, 1, 1, nsamples/2, 1);
02649 
02650     cpl_image_unwrap(power_im);
02651     cpl_free(power);
02652 
02653     cpl_image_delete(output);
02654 
02655     table = cpl_table_new(nsamples/2);
02656     cpl_table_new_column(table, "FREQ", CPL_TYPE_DOUBLE);
02657     cpl_table_new_column(table, "POW", CPL_TYPE_DOUBLE);
02658 
02659     freq = detmon_pernoise_config.speed*1000/nffts_old;
02660 
02661     for(i = 0; i < nsamples/2; i++) {
02662         error = cpl_table_set(table, "FREQ", i, freq/(nsamples/2)*i);
02663         error = cpl_table_set(table, "POW", i, cpl_image_get(pos_spec, i+1, 1, &status));
02664     }
02665 
02666     for(i= 0; i < 5; i++) {
02667         error = cpl_table_set(table, "POW", i, 0.0);
02668     }
02669 
02670     cpl_ensure(!error, error, NULL);
02671 
02672     cpl_image_delete(pos_spec);
02673 
02674     cpl_image_delete(sub_image);
02675     return table;
02676 }
02677 #undef HORIZONTAL
02678 
02679 
02680 
02681 /*---------------------------------------------------------------------------*/
02682 
02683 /*
02684  * @brief  Retrieve input parameters
02685  * @param  pipeline_name        Input image
02686  * @param  recipe_name          Input image
02687  * @param  parlist              Shift to apply on the x-axis
02688  * @return CPL_ERROR_NONE on success.
02689  */
02690 
02691 /*---------------------------------------------------------------------------*/
02692 
02693 
02694 cpl_error_code
02695 irplib_detmon_rm_bpixs(cpl_image ** image,
02696                        const double kappa, int nffts, int nsamples)
02697 {
02698     int                     i, j;
02699 
02700     float                  *data = cpl_image_get_data_float(*image);
02701     int k = 0;
02702     for(i = 0; i < nffts; i++) {
02703         for(j = 0; j < nsamples; j++) {
02704             float                   neighbours = 0;
02705             int                     nneighs = 0;
02706             float                   average = 0;
02707 
02708             /*
02709              * Look for the way to optimize this:
02710              * Some of the points added to neighbours coincide
02711              * in one iteration and the following
02712              */
02713             if(i > 0) {
02714                 neighbours += *(data + (i - 1) * nsamples + j);
02715                 nneighs++;
02716             }
02717             if(i < nffts - 1) {
02718                 neighbours += *(data + (i + 1) * nsamples + j);
02719                 nneighs++;
02720             }
02721             if(j > 0) {
02722                 neighbours += *(data + i * nsamples + (j - 1));
02723                 nneighs++;
02724             }
02725             if(j < nsamples - 1) {
02726                 neighbours += *(data + i * nsamples + (j + 1));
02727                 nneighs++;
02728             }
02729             average = neighbours / nneighs;
02730             if(average > 0) {
02731                 if(*(data + i * nsamples + j) < average * (-1 * kappa) ||
02732                    *(data + i * nsamples + j) > average * (kappa)) {
02733                     k++;
02734                     *(data + i * nsamples + j) = average;
02735                 }
02736             } 
02737             if(average < 0) {
02738                 if(*(data + i * nsamples + j) > average * (-1 * kappa) ||
02739                    *(data + i * nsamples + j) < average * (kappa)) {
02740                     k++;
02741                     *(data + i * nsamples + j) = average;
02742                 }
02743             } 
02744 
02745         }
02746     }
02747 
02748 
02749     return cpl_error_get_code();
02750 
02751 }
02752 
02753 /* Start duplicated code */
02754 
02755 #define RECT_RON_HS         4
02756 #define RECT_RON_SAMPLES    100
02757 
02758 /*---------------------------------------------------------------------------*/
02759 
02760 /*
02761  * @brief  Retrieve input parameters
02762  * @param  pipeline_name        Input image
02763  * @param  recipe_name          Input image
02764  * @param  parlist              Shift to apply on the x-axis
02765  * @return CPL_ERROR_NONE on success.
02766  */
02767 
02768 /*---------------------------------------------------------------------------*/
02769 static cpl_error_code
02770 irplib_flux_get_bias_window(const cpl_image * diff,
02771                             const int *zone_def,
02772                             int ron_hsize,
02773                             int ron_nsamp, double *bias, double *error)
02774 {
02775     const int               hsize = ron_hsize < 0 ? RECT_RON_HS : ron_hsize;
02776     const int               nsamples =
02777         ron_nsamp < 0 ? RECT_RON_SAMPLES : ron_nsamp;
02778     cpl_bivector           *sample_reg;
02779     cpl_vector             *rms_list;
02780     int                     rect[4];
02781     int                     zone[4];
02782     double                 *px;
02783     double                 *py;
02784     double                 *pr;
02785     int                     i;
02786 
02787     /* Test entries */
02788     cpl_ensure_code(diff && bias, CPL_ERROR_NULL_INPUT);
02789 
02790     /* Generate nsamples window centers in the image */
02791     if(zone_def != NULL) {
02792         rect[0] = zone_def[0] + hsize + 1;      /* xmin */
02793         rect[1] = zone_def[1] - hsize - 1;      /* xmax */
02794         rect[2] = zone_def[2] + hsize + 1;      /* ymin */
02795         rect[3] = zone_def[3] - hsize - 1;      /* ymax */
02796     } else {
02797         rect[0] = hsize + 1;    /* xmin */
02798         rect[1] = cpl_image_get_size_x(diff) - hsize - 1;       /* xmax */
02799         rect[2] = hsize + 1;    /* ymin */
02800         rect[3] = cpl_image_get_size_y(diff) - hsize - 1;       /* ymax */
02801     }
02802 
02803     cpl_ensure_code(rect[0] < rect[1] && rect[2] < rect[3],
02804                     CPL_ERROR_ILLEGAL_INPUT);
02805 
02806     /* Generate n+1 regions, because the first region is always at (0,0) */
02807     /* and it would bias the measurement. */
02808     sample_reg =
02809         irplib_bivector_gen_rect_poisson(rect, nsamples + 1, nsamples + 1);
02810     cpl_ensure(sample_reg != NULL, CPL_ERROR_ILLEGAL_INPUT,
02811                CPL_ERROR_ILLEGAL_INPUT);
02812 
02813     px = cpl_bivector_get_x_data(sample_reg);
02814     py = cpl_bivector_get_y_data(sample_reg);
02815 
02816     /* Now, for each window center, extract a vignette and compute the */
02817     /* signal RMS in it. Store this rms into a table. */
02818     rms_list = cpl_vector_new(nsamples);
02819     cpl_ensure(rms_list != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02820     pr = cpl_vector_get_data(rms_list);
02821 
02822     for(i = 0; i < nsamples; i++) {
02823         zone[0] = (int) px[i + 1] - hsize;
02824         zone[1] = (int) px[i + 1] + hsize;
02825         zone[2] = (int) py[i + 1] - hsize;
02826         zone[3] = (int) py[i + 1] + hsize;
02827         pr[i] = cpl_image_get_mean_window(diff,
02828                                           zone[0], zone[2], zone[1], zone[3]);
02829     }
02830     cpl_bivector_delete(sample_reg);
02831 
02832     /* The error is the rms of the rms */
02833     if(error != NULL)
02834         *error = cpl_vector_get_stdev(rms_list);
02835 
02836     /* The final computed RMS is the median of all values.  */
02837     /* This call will modify the rms_list */
02838     *bias = cpl_vector_get_median(rms_list);
02839 
02840     cpl_vector_delete(rms_list);
02841 
02842     return CPL_ERROR_NONE;
02843 }
02844 
02845 #undef RECT_RON_HS
02846 #undef RECT_RON_SAMPLES
02847 
02848 /*---------------------------------------------------------------------------*/
02849 
02850 /*
02851  * @brief  Retrieve input parameters
02852  * @param  pipeline_name        Input image
02853  * @param  recipe_name          Input image
02854  * @param  parlist              Shift to apply on the x-axis
02855  * @return CPL_ERROR_NONE on success.
02856  */
02857 
02858 /*---------------------------------------------------------------------------*/
02859 static cpl_bivector    *
02860 irplib_bivector_gen_rect_poisson(const int *r, const int np, const int homog)
02861 {
02862     double                  min_dist;
02863     int                     i;
02864     int                     gnp;
02865     cpl_bivector           *list;
02866     double                  cand_x, cand_y;
02867     int                     ok;
02868     int                     start_ndx;
02869     int                     xmin, xmax, ymin, ymax;
02870 
02871     /* Corrected Homogeneity factor */
02872     const int               homogc = 0 < homog && homog < np ? homog : np;
02873     double                 *px;
02874     double                 *py;
02875 
02876     /* error handling: test arguments are correct */
02877     cpl_ensure(r, CPL_ERROR_NULL_INPUT, NULL);
02878     cpl_ensure(np > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
02879 
02880     list = cpl_bivector_new(np);
02881     cpl_ensure(list, CPL_ERROR_NULL_INPUT, NULL);
02882     px = cpl_bivector_get_x_data(list);
02883     py = cpl_bivector_get_y_data(list);
02884 
02885     xmin = r[0];
02886     xmax = r[1];
02887     ymin = r[2];
02888     ymax = r[3];
02889 
02890     min_dist =
02891         CPL_MATH_SQRT1_2 * ((xmax - xmin) * (ymax - ymin) / (double) (homogc + 1));
02892     gnp = 1;
02893     px[0] = 0;
02894     py[0] = 0;
02895 
02896     /* First: generate <homog> points */
02897     while(gnp < homogc) {
02898         /* Pick a random point within requested range */
02899         cand_x = cpl_drand() * (xmax - xmin) + xmin;
02900         cand_y = cpl_drand() * (ymax - ymin) + ymin;
02901 
02902         /* Check the candidate obeys the minimal Poisson distance */
02903         ok = 1;
02904         for(i = 0; i < gnp; i++) {
02905             if(pdist(cand_x, cand_y, px[i], py[i]) < min_dist) {
02906                 /* does not check Poisson law: reject point */
02907                 ok = 0;
02908                 break;
02909             }
02910         }
02911         if(ok) {
02912             /* obeys Poisson law: register the point as valid */
02913             px[gnp] = cand_x;
02914             py[gnp] = cand_y;
02915             gnp++;
02916         }
02917     }
02918 
02919     /* Iterative process: */
02920     /* Pick points out of Poisson distance of the last <homogc-1> points. */
02921     start_ndx = 0;
02922     while(gnp < np) {
02923         /* Pick a random point within requested range */
02924         cand_x = cpl_drand() * (xmax - xmin) + xmin;
02925         cand_y = cpl_drand() * (ymax - ymin) + ymin;
02926 
02927         /* Check the candidate obeys the minimal Poisson distance */
02928         ok = 1;
02929         for(i = 0; i < homogc; i++) {
02930             if(pdist(cand_x,
02931                      cand_y,
02932                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
02933                 /* does not check Poisson law: reject point */
02934                 ok = 0;
02935                 break;
02936             }
02937         }
02938         if(ok) {
02939             /* obeys Poisson law: register the point as valid */
02940             px[gnp] = cand_x;
02941             py[gnp] = cand_y;
02942             gnp++;
02943         }
02944     }
02945 
02946     /* Iterative process: */
02947     /* Pick points out of Poisson distance of the last <homogc-1> points. */
02948     start_ndx = 0;
02949     while(gnp < np) {
02950         /* Pick a random point within requested range */
02951         cand_x = cpl_drand() * (xmax - xmin) + xmin;
02952         cand_y = cpl_drand() * (ymax - ymin) + ymin;
02953 
02954         /* Check the candidate obeys the minimal Poisson distance */
02955         ok = 1;
02956         for(i = 0; i < homogc; i++) {
02957             if(pdist(cand_x,
02958                      cand_y,
02959                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
02960                 /* does not check Poisson law: reject point */
02961                 ok = 0;
02962                 break;
02963             }
02964         }
02965         if(ok) {
02966             /* obeys Poisson law: register the point as valid */
02967             px[gnp] = cand_x;
02968             py[gnp] = cand_y;
02969             gnp++;
02970             start_ndx++;
02971         }
02972     }
02973     return list;
02974 }
02975 
02976 /* End of duplicated code */
02977 
02978 /*---------------------------------------------------------------------------*/
02979 
02980 /*
02981  * @brief  Retrieve input parameters
02982  * @param  pipeline_name        Input image
02983  * @param  recipe_name          Input image
02984  * @param  parlist              Shift to apply on the x-axis
02985  * @return CPL_ERROR_NONE on success.
02986  */
02987 
02988 /*---------------------------------------------------------------------------*/
02989 cpl_error_code
02990 irplib_detmon_pernoise(cpl_frameset      * frameset,
02991                        const cpl_parameterlist * parlist,
02992                        const char        * tag,
02993                        const char        * recipe_name,
02994                        const char        * pipeline_name,
02995                        const char        * procatg_tbl,
02996                        const char        * package,
02997                        int              (*compare)(const cpl_frame *,
02998                                                    const cpl_frame *))
02999 {
03000     int                     nsets;
03001     int                    *selection = NULL;
03002     int                     i;
03003     cpl_error_code          error;
03004 
03005     if(irplib_detmon_pernoise_dfs_set_groups(frameset, tag)) {
03006         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
03007     }
03008 
03009     /*
03010      * This function reads all inputs parameters from parlist
03011      * and stores them in a global variable detmon_ronbias_config.
03012      * Similar to irplib_detmon_lg_retrieve_parlist(). See irplib_detmon.c
03013      */
03014     error = irplib_detmon_pernoise_retrieve_parlist(pipeline_name,
03015                                                    recipe_name, parlist);
03016     cpl_ensure_code(!error, error);
03017 
03018     /* Labelise all input frames */
03019     if(compare == NULL)
03020         nsets = 1;
03021     else {
03022         cpl_msg_info(cpl_func, "Identify the different settings");
03023         selection = cpl_frameset_labelise(frameset, compare, &nsets);
03024         if(selection == NULL)
03025             cpl_msg_error(cpl_func, "Cannot labelise input frames");
03026     }
03027 
03028     detmon_pernoise_config.nb_extensions = 1;
03029     if(detmon_pernoise_config.exts < 0) {
03030         const cpl_frame        *cur_frame =
03031             cpl_frameset_get_first_const(frameset);
03032         /* Get the nb of extensions */
03033         detmon_pernoise_config.nb_extensions =
03034             cpl_frame_get_nextensions(cur_frame);
03035     }
03036 
03037     /* Extract settings and reduce each of them */
03038     for(i = 0; i < nsets; i++) {
03039         int j;
03040         cpl_table ** freq_table;
03041         cpl_propertylist ** qclist =
03042             (cpl_propertylist **)
03043             cpl_malloc(detmon_pernoise_config.nb_extensions *
03044                        sizeof(cpl_propertylist *));
03045 
03046         cpl_imagelist ** raws = (cpl_imagelist **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_imagelist *));
03047         cpl_image ** input = (cpl_image **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_image *));
03048 
03049         /* Initialise memory for products */
03050         if(detmon_pernoise_config.mode == 1) {
03051             freq_table =
03052                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03053                                           4 * sizeof(cpl_table *));
03054         } else {
03055             freq_table =
03056                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03057                                           sizeof(cpl_table *));
03058         }
03059         
03060         if(detmon_pernoise_config.exts >= 0) {
03061             *raws =
03062                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03063                                             detmon_pernoise_config.exts);
03064             *input = cpl_image_subtract_create(cpl_imagelist_get(*raws,0),
03065                                                cpl_imagelist_get(*raws,1));
03066         } else {
03067             cpl_imagelist          *raws_all_exts =
03068                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03069                                             -1);
03070             for(j = 0; j < detmon_pernoise_config.nb_extensions; j++) {
03071                 int nframes = cpl_frameset_get_size(frameset);
03072                 int                     k;
03073                 for(k = 0; k < nframes; k++) {
03074                     cpl_image              *image =
03075                         cpl_imagelist_unset(raws_all_exts,
03076                                             (detmon_pernoise_config.
03077                                              nb_extensions - 1 - j) * k);
03078                     cpl_imagelist_set(raws[j], image, k);
03079                 }
03080                 input[j] = 
03081                     cpl_image_subtract_create(cpl_imagelist_get(raws[j],0),
03082                                               cpl_imagelist_get(raws[j],1));
03083             }
03084         }
03085 
03086         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++) {
03087             cpl_msg_info(cpl_func, "Starting reduction");
03088             if(detmon_pernoise_config.mode == 1){
03089                 int nx = cpl_image_get_size_x(input[j]);
03090                 int ny = cpl_image_get_size_y(input[j]);
03091 
03092                 cpl_image * quad1 = cpl_image_extract(input[j],
03093                                                       1, 1, nx/2, ny/2);
03094                 cpl_image * quad2 = cpl_image_extract(input[j],
03095                                                       1, ny/2+1, nx/2, ny);
03096                 cpl_image * quad3 = cpl_image_extract(input[j],
03097                                                       nx/2+1, 1, nx, ny/2);
03098                 cpl_image * quad4 = cpl_image_extract(input[j],
03099                                                       nx/2+1, ny/2+1, nx, ny);
03100                 freq_table[j * 4    ] = irplib_detmon_pernoise_reduce(quad1);
03101                 cpl_ensure_code(freq_table[j * 4    ]!= NULL,
03102                                 cpl_error_get_code());  
03103                 freq_table[j * 4 + 1] = irplib_detmon_pernoise_reduce(quad2);
03104                 cpl_ensure_code(freq_table[j * 4 + 1]!= NULL,
03105                                 cpl_error_get_code()); 
03106                 freq_table[j * 4 + 2] = irplib_detmon_pernoise_reduce(quad3);
03107                 cpl_ensure_code(freq_table[j * 4 + 2]!= NULL,
03108                                 cpl_error_get_code()); 
03109                 freq_table[j * 4 + 3] = irplib_detmon_pernoise_reduce(quad4);
03110                 cpl_ensure_code(freq_table[j * 4 + 3]!= NULL,
03111                                 cpl_error_get_code()); 
03112                 qclist[j] = cpl_propertylist_new();
03113                 error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j], 1);
03114                 cpl_ensure_code(!error, error);
03115                 error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j+1], 2);
03116                 cpl_ensure_code(!error, error);
03117                 error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j+2], 3);
03118                 cpl_ensure_code(!error, error);
03119                 error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j+3], 4);
03120                 cpl_ensure_code(!error, error);
03121         cpl_image_delete(quad1);
03122         cpl_image_delete(quad2);
03123         cpl_image_delete(quad3);
03124         cpl_image_delete(quad4);
03125             } else {
03126                 freq_table[j] = irplib_detmon_pernoise_reduce(input[j]);
03127                 cpl_ensure_code(freq_table[j]!= NULL, cpl_error_get_code()); 
03128                 qclist[j] = cpl_propertylist_new();
03129                 error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j], 0);
03130                 cpl_ensure_code(!error, error);
03131             }
03132         }
03133         error = irplib_detmon_pernoise_save(parlist, frameset, recipe_name,
03134                                             pipeline_name, procatg_tbl,
03135                                             package, freq_table, qclist, 0,
03136                                             0, frameset);
03137         cpl_ensure_code(!error, error);
03138 
03139         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++) {
03140             cpl_propertylist_delete(qclist[j]);
03141         cpl_imagelist_delete(raws[j]);
03142         cpl_image_delete(input[j]);
03143         }
03144     cpl_free(qclist);
03145     cpl_free(raws);
03146     cpl_free(input);
03147         if(detmon_pernoise_config.mode == 1) {
03148             for(j= 0; j < detmon_pernoise_config.nb_extensions * 4; j++) {
03149                 cpl_table_delete(freq_table[j]);
03150             }
03151         } else {
03152             for(j= 0; j < detmon_pernoise_config.nb_extensions; j++) {
03153                 cpl_table_delete(freq_table[j]);
03154             }
03155         }
03156     cpl_free(freq_table);
03157     }
03158 
03159     return cpl_error_get_code();
03160 }
03161 
03162 /*---------------------------------------------------------------------------*/
03163 
03164 /*
03165  * @brief  Retrieve input parameters
03166  * @param  pipeline_name        Input image
03167  * @param  recipe_name          Input image
03168  * @param  parlist              Shift to apply on the x-axis
03169  * @return CPL_ERROR_NONE on success.
03170  */
03171 
03172 /*---------------------------------------------------------------------------*/
03173 int
03174 irplib_detmon_pernoise_dfs_set_groups(cpl_frameset * set, const char *tag)
03175 {
03176     cpl_frame              *cur_frame;
03177     const char             *cur_tag;
03178     int                     nframes;
03179     int                     i;
03180 
03181     /* Check entries */
03182     if(set == NULL)
03183         return -1;
03184 
03185     /* Initialize */
03186     nframes = cpl_frameset_get_size(set);
03187 
03188     /* Loop on frames */
03189     for(i = 0; i < nframes; i++) {
03190         cur_frame = cpl_frameset_get_frame(set, i);
03191         cur_tag = cpl_frame_get_tag(cur_frame);
03192 
03193         /* RAW frames */
03194         if(!strcmp(cur_tag, tag))
03195             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
03196         /* CALIB frames */
03197 
03198 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
03199           cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
03200 */
03201     }
03202     return 0;
03203 }
03204 
03205 /*---------------------------------------------------------------------------*/
03206 
03207 /*
03208  * @brief  Retrieve input parameters
03209  * @param  pipeline_name        Input image
03210  * @param  recipe_name          Input image
03211  * @param  parlist              Shift to apply on the x-axis
03212  * @return CPL_ERROR_NONE on success.
03213  */
03214 
03215 /*---------------------------------------------------------------------------*/
03216 cpl_error_code
03217 irplib_detmon_fill_pernoise_params(cpl_parameterlist * parlist,
03218                                    const char *recipe_name,
03219                                    const char *pipeline_name,
03220                                    int mode,
03221                                    const char * direction,
03222                                    double speed,
03223                                    int llx,
03224                                    int lly,
03225                                    int urx,
03226                                    int ury,
03227                                    int kappa,
03228                                    int exts)
03229 {
03230     irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 9,
03231 
03232                                "mode",
03233                                "Mode",
03234                                "CPL_TYPE_INT", mode,
03235 
03236                                "direction",
03237                                "Readout direction",
03238                                "CPL_TYPE_BOOL", direction,
03239 
03240                                "speed",
03241                                "Readout speed",
03242                                "CPL_TYPE_DOUBLE", speed,
03243 
03244                                "llx",
03245                                "(yet unsupported) x coordinate of the lower-left "
03246                                "point of the region of interest. If not modified, default value will be 1.",
03247                                "CPL_TYPE_INT", llx,
03248                                "lly",
03249                                "(yet unsupported) y coordinate of the lower-left "
03250                                "point of the region of interest. If not modified, default value will be 1.",
03251                                "CPL_TYPE_INT", lly,
03252                                "urx",
03253                                "(yet unsupported) x coordinate of the upper-right "
03254                                "point of the region of interest. If not modified, default value will be X dimension of the input image.",
03255                                "CPL_TYPE_INT", urx,
03256                                "ury",
03257                                "(yet unsupported) y coordinate of the upper-right "
03258                                "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
03259                                "CPL_TYPE_INT", ury,
03260 
03261                                "kappa",
03262                                "Kappa used for determining threshold of bad (hot, cold) pixels",
03263                                "CPL_TYPE_INT", kappa,
03264 
03265                                "exts",
03266                                "Activate the multi-exts option",
03267                                "CPL_TYPE_INT", exts);
03268 
03269     return 0;
03270 }
03271 
03272 /*---------------------------------------------------------------------------*/
03273 
03274 /*
03275  * @brief  Retrieve input parameters
03276  * @param  pipeline_name        Input image
03277  * @param  recipe_name          Input image
03278  * @param  parlist              Shift to apply on the x-axis
03279  * @return CPL_ERROR_NONE on success.
03280  */
03281 
03282 /*---------------------------------------------------------------------------*/
03283 int
03284 irplib_detmon_fill_pernoise_params_default(cpl_parameterlist * parlist,
03285                                            const char *recipe_name,
03286                                            const char *pipeline_name)
03287 {
03288     irplib_detmon_fill_pernoise_params(parlist, recipe_name, pipeline_name,
03289                                        1,           /* --mode      */
03290                                        "CPL_TRUE",  /* --direction */
03291                                        84.5,        /* --speed     */
03292                                        -1,          /* --llx       */
03293                                        -1,          /* --lly       */
03294                                        -1,          /* --urx       */
03295                                        -1,          /* --ury       */
03296                                        100,          /* --kappa     */
03297                                        0);          /* --exts      */
03298 
03299     return 0;
03300 
03301 }
03302 
03303 
03304 static cpl_error_code
03305 irplib_detmon_pernoise_retrieve_parlist(const char *pipeline_name,
03306                                        const char *recipe_name,
03307                                        const cpl_parameterlist * parlist)
03308 {
03309     char                   *par_name;
03310     cpl_parameter          *par;
03311 
03312     /* --mode */
03313     detmon_pernoise_config.mode =
03314         irplib_detmon_retrieve_par("mode", pipeline_name, recipe_name,
03315                                    parlist);
03316 
03317     /* --direction */
03318     par_name = cpl_sprintf("%s.%s.direction", pipeline_name, recipe_name);
03319     assert(par_name != NULL);
03320     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03321     detmon_pernoise_config.direction = cpl_parameter_get_bool(par);
03322     cpl_free(par_name);
03323 
03324     /* --speed */
03325     par_name = cpl_sprintf("%s.%s.speed", pipeline_name, recipe_name);
03326     assert(par_name != NULL);
03327     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03328     detmon_pernoise_config.speed = cpl_parameter_get_double(par);
03329     cpl_free(par_name);
03330 
03331     /* --llx */
03332     detmon_pernoise_config.llx =
03333         irplib_detmon_retrieve_par("llx", pipeline_name, recipe_name,
03334                                    parlist);
03335 
03336     /* --lly */
03337     detmon_pernoise_config.lly =
03338         irplib_detmon_retrieve_par("lly", pipeline_name, recipe_name,
03339                                    parlist);
03340     /* --urx */
03341     detmon_pernoise_config.urx =
03342         irplib_detmon_retrieve_par("urx", pipeline_name, recipe_name,
03343                                    parlist);
03344     /* --ury */
03345     detmon_pernoise_config.ury =
03346         irplib_detmon_retrieve_par("ury", pipeline_name, recipe_name,
03347                                    parlist);
03348     /* --kappa */
03349     detmon_pernoise_config.kappa =
03350         irplib_detmon_retrieve_par("kappa", pipeline_name, recipe_name,
03351                                    parlist);
03352 
03353     /* --exts */
03354     detmon_pernoise_config.exts =
03355         irplib_detmon_retrieve_par("exts", pipeline_name, recipe_name,
03356                                    parlist);
03357 
03358     if(cpl_error_get_code()) {
03359         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
03360         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
03361     }
03362 
03363     return cpl_error_get_code();
03364 }
03365 
03366 /*---------------------------------------------------------------------------*/
03367 
03368 /*
03369  * @brief  Retrieve input parameters
03370  * @param  pipeline_name        Input image
03371  * @param  recipe_name          Input image
03372  * @param  parlist              Shift to apply on the x-axis
03373  * @return CPL_ERROR_NONE on success.
03374  */
03375 
03376 /*---------------------------------------------------------------------------*/
03377 static                  cpl_error_code
03378 irplib_detmon_pernoise_save(const cpl_parameterlist * parlist,
03379                             cpl_frameset * frameset,
03380                             const char *recipe_name,
03381                             const char *pipeline_name,
03382                             const char *procatg_tbl,
03383                             const char *package,
03384                             cpl_table ** freq_table,
03385                             cpl_propertylist ** qclist,
03386                             const int flag_sets,
03387                             const int which_set,
03388                             const cpl_frameset * usedframes)
03389 {
03390 
03391     cpl_frame              *ref_frame;
03392     cpl_propertylist       *plist;
03393     char                   *name_o = NULL; /* Avoid (false) uninit warning */
03394     int                     i, j;
03395     cpl_propertylist       *paflist;
03396     cpl_error_code          error;
03397 
03398     /*******************************/
03399     /*  Write the FREQ TABLE  */
03400 
03401     /*******************************/
03402 
03403     if(detmon_pernoise_config.mode != 1) {
03404         /* Set the file name for the table */
03405         if(!flag_sets) {
03406             name_o = cpl_sprintf("%s_freq_table.fits", recipe_name);
03407             assert(name_o != NULL);
03408         } else {
03409             name_o =
03410                 cpl_sprintf("%s_freq_table_set%02d.fits", recipe_name,
03411                                which_set);
03412             assert(name_o != NULL);
03413         }
03414 
03415         /* Save the table */
03416         if(cpl_dfs_save_table(frameset, parlist, usedframes, freq_table[0],
03417                               NULL, recipe_name, procatg_tbl, qclist[0], NULL,
03418                               package, name_o)) {
03419             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03420             cpl_free(name_o);
03421             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03422         }
03423 
03424         if(detmon_pernoise_config.exts < 0) {
03425 
03426             for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03427                 error =
03428                     cpl_table_save(freq_table[i], NULL, qclist[i], name_o,
03429                                    CPL_IO_EXTEND);
03430                 cpl_ensure_code(!error, error);
03431             }
03432         }
03433 
03434         /* Free */
03435         cpl_free(name_o);
03436 
03437     } else {
03438         for (j = 1; j <= 4; j++) {
03439             /* Set the file name for the table */
03440             if(!flag_sets) {
03441                 name_o = cpl_sprintf("%s_freq_table_quad%02d.fits",
03442                                         recipe_name, j);
03443                 assert(name_o != NULL);
03444             } else {
03445                 name_o =
03446                     cpl_sprintf("%s_freq_table_quad%02d_set%02d.fits",
03447                                    recipe_name, j, which_set);
03448                 assert(name_o != NULL);
03449             }
03450 
03451             /* Save the table */
03452             if(cpl_dfs_save_table(frameset, parlist, usedframes,
03453                                   freq_table[j - 1],
03454                                   NULL, recipe_name, procatg_tbl, qclist[0], NULL,
03455                                   package, name_o)) {
03456                 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03457                 cpl_free(name_o);
03458                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03459             }
03460 
03461             if(detmon_pernoise_config.exts < 0) {
03462                 for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03463                     error = cpl_table_save(freq_table[(j-1) + 4 * i],
03464                                            NULL, qclist[i], name_o,
03465                                            CPL_IO_EXTEND);
03466                     cpl_ensure_code(!error, error);
03467                 }
03468             }
03469 
03470             /* Free */
03471             cpl_free(name_o);
03472         }
03473 
03474     }
03475     /*******************************/
03476     /*  Write the PAF file(s)      */
03477     /*******************************/
03478 
03479     /* Get FITS header from reference file */
03480     ref_frame = cpl_frameset_get_first(frameset);
03481     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03482                                       0)) == NULL) {
03483         cpl_msg_error(cpl_func, "getting header from reference frame");
03484         cpl_ensure_code(0, cpl_error_get_code());
03485     }
03486 
03487     /* Get the keywords for the paf file */
03488     paflist = cpl_propertylist_new();
03489     cpl_propertylist_copy_property_regexp(paflist, plist,
03490                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
03491                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
03492                                           "ESO DET NCORRS|"
03493                                           "ESO DET MODE NAME)$", 0);
03494 
03495     for(i = 0; i < detmon_pernoise_config.nb_extensions; i++) {
03496         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
03497         error = cpl_propertylist_append(c_paflist, qclist[i]);
03498         cpl_ensure_code(!error, error);
03499 
03500         /* Set the file name for the bpm */
03501         if(detmon_pernoise_config.exts >= 0) {
03502             if(!flag_sets) {
03503                 name_o = cpl_sprintf("%s.paf", recipe_name);
03504                 assert(name_o != NULL);
03505             } else {
03506                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
03507                 assert(name_o != NULL);
03508             }
03509         } else {
03510             if(!flag_sets) {
03511                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
03512                 assert(name_o != NULL);
03513             } else {
03514                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
03515                 assert(name_o != NULL);
03516             }
03517         }
03518         /* Save the PAF */
03519         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
03520             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03521             cpl_free(name_o);
03522             cpl_propertylist_delete(paflist);
03523             cpl_propertylist_delete(plist);
03524             cpl_free(name_o);
03525             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03526         }
03527         cpl_propertylist_delete(c_paflist);
03528         cpl_free(name_o);
03529     } 
03530 
03531     cpl_propertylist_delete(plist);
03532     cpl_propertylist_delete(paflist);
03533 
03534     return cpl_error_get_code();
03535 }
03536 
03537 static cpl_error_code
03538 irplib_detmon_pernoise_qc(cpl_propertylist * qclist,
03539                           cpl_table * table,
03540                           int iquad)
03541 {
03542 //    cpl_propertylist       *reflist = cpl_propertylist_new();
03543     cpl_error_code error;
03544     char * propname;
03545 
03546     double freqs[3] = {0, 0, 0};
03547     double pows[3] = {0, 0, 0};
03548 
03549 /*    error = cpl_propertylist_append_bool(reflist, "POW", TRUE);
03550     cpl_ensure_code(!error, error);
03551 
03552     error = cpl_table_sort(table, reflist);
03553     cpl_ensure_code(!error, error);
03554 */
03555 
03556     int nrows = cpl_table_get_nrow(table);
03557     int i;
03558 
03559     double * all_freqs = cpl_table_get_data_double(table, "FREQ");
03560     double * all_pows  = cpl_table_get_data_double(table, "POW");
03561 
03562     for ( i= 1; i< nrows-1; i++){
03563         if (all_pows[i] > pows[0]) {
03564             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03565                 pows[2]=pows[1];
03566                 pows[1]=pows[0];
03567                 pows[0]=all_pows[i];
03568 
03569                 freqs[2]=freqs[1];
03570                 freqs[1]=freqs[0];
03571                 freqs[0]=all_freqs[i];
03572             }
03573         } else if (all_pows[i] > pows[1]) {
03574             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03575                 pows[2]=pows[1];
03576                 pows[1]=all_pows[i];
03577 
03578                 freqs[2]=freqs[1];
03579                 freqs[1]=all_freqs[i];
03580             }
03581 
03582         } else if(all_pows[i] > pows[2]) {
03583             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03584                 pows[2]=all_pows[i];
03585 
03586                 freqs[2]=all_freqs[i];
03587             }
03588 
03589         }
03590     }
03591 
03592     if (detmon_pernoise_config.mode == 1) {
03593         propname = cpl_sprintf("ESO QC FREQ1 %d", iquad);
03594         assert(propname != NULL);
03595     } else {
03596         propname = cpl_sprintf("ESO QC FREQ1");
03597     }
03598 
03599     error = cpl_propertylist_append_double(qclist, propname, freqs[0]);
03600     cpl_ensure_code(!error, error);
03601 
03602     cpl_free(propname);
03603 
03604     if (detmon_pernoise_config.mode == 1) {
03605         propname = cpl_sprintf("ESO QC FREQ2 %d", iquad);
03606         assert(propname != NULL);
03607     } else {
03608         propname = cpl_sprintf("ESO QC FREQ2");
03609     }
03610 
03611     error = cpl_propertylist_append_double(qclist, propname, freqs[1]);
03612     cpl_ensure_code(!error, error);
03613 
03614     cpl_free(propname);
03615 
03616     if (detmon_pernoise_config.mode == 1) {
03617         propname = cpl_sprintf("ESO QC FREQ3 %d", iquad);
03618         assert(propname != NULL);
03619     } else {
03620         propname = cpl_sprintf("ESO QC FREQ3");
03621     }
03622 
03623     error = cpl_propertylist_append_double(qclist, propname, freqs[2]);
03624     cpl_ensure_code(!error, error);
03625 
03626     cpl_free(propname);
03627 
03628     if (detmon_pernoise_config.mode == 1) {
03629         propname = cpl_sprintf("ESO QC POW1 %d", iquad);
03630         assert(propname != NULL);
03631     } else {
03632         propname = cpl_sprintf("ESO QC POW1");
03633     }
03634 
03635     error = cpl_propertylist_append_double(qclist, propname, pows[0]);
03636     cpl_ensure_code(!error, error);
03637 
03638     cpl_free(propname);
03639 
03640     if (detmon_pernoise_config.mode == 1) {
03641         propname = cpl_sprintf("ESO QC POW2 %d", iquad);
03642         assert(propname != NULL);
03643     } else {
03644         propname = cpl_sprintf("ESO QC POW2");
03645     }
03646 
03647     error = cpl_propertylist_append_double(qclist, propname, pows[1]);
03648     cpl_ensure_code(!error, error);
03649 
03650     cpl_free(propname);
03651 
03652     if (detmon_pernoise_config.mode == 1) {
03653         propname = cpl_sprintf("ESO QC POW3 %d", iquad);
03654         assert(propname != NULL);
03655     } else {
03656         propname = cpl_sprintf("ESO QC POW3");
03657     }
03658 
03659     error = cpl_propertylist_append_double(qclist, propname, pows[2]);
03660     cpl_ensure_code(!error, error);
03661 
03662 
03663     cpl_free(propname);
03664 
03665     return cpl_error_get_code();
03666 }
03667 
03668 /*---------------------------------------------------------------------------*/
03669 
03670 /*
03671  * @brief  Retrieve input parameters
03672  * @param  pipeline_name        Input image
03673  * @param  recipe_name          Input image
03674  * @param  parlist              Shift to apply on the x-axis
03675  * @return CPL_ERROR_NONE on success.
03676  */
03677 
03678 /*---------------------------------------------------------------------------*/
03679 cpl_error_code
03680 irplib_detmon_pernoise_rm_bg(cpl_image * image, int nsamples, int nffts)
03681 {
03682     cpl_vector             *x = cpl_vector_new(nsamples * nffts);
03683     cpl_vector             *y = cpl_vector_new(nsamples * nffts);
03684     cpl_vector             *values = cpl_vector_new(nsamples * nffts);
03685 
03686     int                     rejected;
03687     int i, j;
03688     cpl_bivector *xy_pos;
03689     double mse;
03690     cpl_polynomial * poly_2d;
03691     cpl_image * poly_ima;
03692 
03693     for(i = 1; i <= nffts; i++) {
03694         for(j = 1; j <= nsamples; j++) {
03695             cpl_vector_set(x, (i - 1) * nsamples + (j - 1), j);
03696             cpl_vector_set(y, (i - 1) * nsamples + (j - 1), i);
03697             cpl_vector_set(values, (i - 1) * nsamples + (j - 1),
03698                            cpl_image_get(image, j, i, &rejected));
03699             cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03700         }
03701     }
03702 
03703     xy_pos = cpl_bivector_wrap_vectors(x, y);
03704     poly_2d = cpl_polynomial_fit_2d_create(xy_pos, values, 3, &mse);
03705     poly_ima = cpl_image_new(nsamples, nffts, CPL_TYPE_FLOAT);
03706 
03707     cpl_image_fill_polynomial(poly_ima, poly_2d, 1, 1, 1, 1);
03708 
03709     cpl_image_subtract(image, poly_ima);
03710 /*
03711         char                   *frame_name =
03712             cpl_sprintf("poly.fits");
03713         assert(frame_name != NULL);
03714         cpl_propertylist * plist = cpl_propertylist_new();
03715         cpl_propertylist_append_double(plist, "ESO DET DIT", 3);
03716 
03717         cpl_propertylist_append_double(plist, "EXPTIME", 3);
03718 
03719         cpl_image_save(poly_ima, frame_name, CPL_BPP_IEEE_FLOAT, plist,
03720                        CPL_IO_DEFAULT);
03721         cpl_propertylist_delete(plist);
03722         cpl_free(frame_name);
03723 */
03724 
03725     cpl_polynomial_delete(poly_2d);
03726     cpl_image_delete(poly_ima);
03727     cpl_bivector_unwrap_vectors(xy_pos);
03728     cpl_vector_delete(x);
03729     cpl_vector_delete(y);
03730     cpl_vector_delete(values);
03731 
03732     return cpl_error_get_code();
03733 }
03734 
03735 /*---------------------------------------------------------------------------*/
03736 
03737 /*
03738  * @brief  Retrieve input parameters
03739  * @param  pipeline_name        Input image
03740  * @param  recipe_name          Input image
03741  * @param  parlist              Shift to apply on the x-axis
03742  * @return CPL_ERROR_NONE on success.
03743  */
03744 
03745 /*---------------------------------------------------------------------------*/
03746 cpl_error_code
03747 irplib_detmon_dark(cpl_frameset      * frameset,
03748                    const cpl_parameterlist * parlist,
03749                    const char        * tag,
03750                    const char        * recipe_name,
03751                    const char        * pipeline_name,
03752                    const char        * procatg_master,
03753                    const char        * procatg_dsnu,
03754                    const char        * procatg_tbl,
03755                    const char        * package,
03756                    int              (*compare)(const cpl_frame *,
03757                                                const cpl_frame *))
03758 {
03759     int                     nsets;
03760     int                    *selection = NULL;
03761     int                     i;
03762     cpl_error_code          error;
03763 
03764     if(irplib_detmon_dark_dfs_set_groups(frameset, tag)) {
03765         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
03766     }
03767 
03768     /*
03769      * This function reads all inputs parameters from parlist
03770      * and stores them in a global variable detmon_ronbias_config.
03771      * Similar to irplib_detmon_lg_retrieve_parlist(). See irplib_detmon.c
03772      */
03773     error = irplib_detmon_retrieve_dark_params(pipeline_name,
03774                                                recipe_name, parlist);
03775     cpl_ensure_code(!error, error);
03776 
03777     /* Labelise all input frames */
03778     if(compare == NULL)
03779         nsets = 1;
03780     else {
03781         cpl_msg_info(cpl_func, "Identify the different settings");
03782         selection = cpl_frameset_labelise(frameset, compare, &nsets);
03783         if(selection == NULL)
03784             cpl_msg_error(cpl_func, "Cannot labelise input frames");
03785     }
03786 
03787     detmon_dark_config.nb_extensions = 1;
03788     if(detmon_dark_config.exts < 0) {
03789         const cpl_frame        *cur_frame =
03790             cpl_frameset_get_first_const(frameset);
03791         /* Get the nb of extensions */
03792         detmon_dark_config.nb_extensions =
03793             cpl_frame_get_nextensions(cur_frame);
03794     }
03795 
03796     /* Extract settings and reduce each of them */
03797     for(i = 0; i < nsets; i++) {
03798         int                    *select_dits = NULL;
03799         cpl_frameset           *cur_fset =
03800             nsets == 1 ? cpl_frameset_duplicate(frameset) :
03801             cpl_frameset_extract(frameset, selection, i);
03802 
03803         int                     ndits = 0;
03804         int                     j, k;
03805         cpl_table ** dsnu_table = NULL;
03806         cpl_imagelist ** dsnu = NULL;
03807 
03808         cpl_propertylist ** qclist =
03809             (cpl_propertylist **)
03810             cpl_malloc(detmon_dark_config.nb_extensions *
03811                        sizeof(cpl_propertylist *));
03812 
03813 
03814         cpl_imagelist ** masters =
03815             (cpl_imagelist **)
03816             cpl_malloc(detmon_dark_config.nb_extensions *
03817                        sizeof(cpl_imagelist *));
03818 
03819         /* Initialise memory for products */
03820         if(detmon_dark_config.opt_nir == OPT) {
03821             dsnu_table =
03822                 (cpl_table **) cpl_malloc(detmon_dark_config.nb_extensions *
03823                                           sizeof(cpl_table *));
03824             dsnu =
03825                 (cpl_imagelist **)
03826                 cpl_malloc(detmon_dark_config.nb_extensions *
03827                                           sizeof(cpl_imagelist *));
03828         }
03829         
03830         select_dits = cpl_frameset_labelise(cur_fset,
03831                                             irplib_detmon_compare_dits,
03832                                             &ndits);
03833 
03834 //        irplib_ensure((select_dits != NULL),
03835     //    CPL_ERROR_ILLEGAL_INPUT,
03836     //        "You must provide at least one input frame tagged as DARK");
03837 
03838 
03839         if(detmon_dark_config.exts >= 0) {
03840             *masters = cpl_imagelist_new();
03841             if(detmon_dark_config.opt_nir == OPT) {
03842                 *dsnu = cpl_imagelist_new();
03843                 *dsnu_table = cpl_table_new(ndits);
03844             }
03845             *qclist = cpl_propertylist_new();
03846             cpl_table_new_column(*dsnu_table, "DIT", CPL_TYPE_DOUBLE);
03847             cpl_table_new_column(*dsnu_table, "STDEV", CPL_TYPE_DOUBLE);
03848         } else {
03849             for ( j = 0; j < detmon_dark_config.nb_extensions; j ++) {
03850                 masters[j] = cpl_imagelist_new();
03851                 if(detmon_dark_config.opt_nir == OPT) {
03852                     dsnu[j] = cpl_imagelist_new();
03853                     dsnu_table[j] = cpl_table_new(ndits);
03854                 }
03855                 qclist[j] = cpl_propertylist_new();
03856                 cpl_table_new_column(dsnu_table[j], "DIT", CPL_TYPE_DOUBLE);
03857                 cpl_table_new_column(dsnu_table[j], "STDEV", CPL_TYPE_DOUBLE);
03858             }
03859         }
03860 
03861         for(j = 0; j < ndits; j++) {
03862             cpl_frameset  * cur_fdit = cpl_frameset_extract(cur_fset,
03863                                                             select_dits, j);   
03864             cpl_imagelist ** raws = 
03865                 (cpl_imagelist **)
03866                 cpl_malloc(detmon_dark_config.nb_extensions *
03867                            sizeof(cpl_imagelist *));
03868 
03869             if(detmon_dark_config.exts >= 0) {
03870                 cpl_image * collapsed;
03871                 *raws =
03872                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
03873                                                 detmon_dark_config.exts);
03874                 collapsed = cpl_imagelist_collapse_create(*raws);
03875                 cpl_imagelist_set(*masters, collapsed, j);
03876                 if(detmon_dark_config.opt_nir == OPT) {
03877                     irplib_detmon_dark_dsnu(cur_fdit, *dsnu, *dsnu_table,
03878                                             collapsed, j);
03879                 }
03880                 irplib_detmon_dark_qc(*qclist, collapsed);
03881             } else {
03882                 cpl_imagelist          *raws_all_exts =
03883                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
03884                                                 -1);
03885                 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
03886                     int nframes = cpl_frameset_get_size(cur_fdit);
03887                     int h;
03888                     cpl_image * collapsed;
03889                     for(h = 0; h < nframes; h++) {
03890                         cpl_image              *image =
03891                             cpl_imagelist_unset(raws_all_exts,
03892                                                 (detmon_dark_config.
03893                                                  nb_extensions - 1 - k) * h);
03894                         cpl_imagelist_set(raws[k], image, h);
03895                     }
03896                     collapsed = cpl_imagelist_collapse_create(raws[k]);
03897                     cpl_imagelist_set(masters[k],collapsed, j);
03898                     if(detmon_dark_config.opt_nir == OPT) {
03899                         irplib_detmon_dark_dsnu(cur_fdit, dsnu[k],
03900                                                 dsnu_table[j], collapsed, j);
03901                     }
03902                     irplib_detmon_dark_qc(qclist[k], collapsed);
03903                 }
03904             }
03905 
03906             cpl_frameset_delete(cur_fdit);
03907             for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
03908                 cpl_imagelist_delete(raws[k]);
03909             }
03910             cpl_free(raws);
03911         } /* end of loop (for) around different DIT values */
03912 
03913         cpl_frameset_delete(cur_fset);
03914 
03915         irplib_detmon_dark_save(parlist, frameset, recipe_name, pipeline_name,
03916                                 procatg_master, procatg_tbl, procatg_dsnu,
03917                                 package, masters, dsnu_table, dsnu, qclist,
03918                                 0, 0, frameset);
03919 
03920         if(detmon_dark_config.opt_nir == OPT) {
03921             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
03922                 cpl_table_delete(dsnu_table[j]);
03923                 cpl_imagelist_delete(dsnu[j]);
03924             }
03925             cpl_free(dsnu_table);
03926             cpl_free(dsnu);
03927         }
03928 
03929         for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
03930             cpl_propertylist_delete(qclist[j]);
03931             cpl_imagelist_delete(masters[j]);
03932         }
03933         cpl_free(qclist);
03934         cpl_free(masters);
03935         cpl_free(select_dits);
03936 
03937     } /* end of loop (for) around different setting */
03938 
03939     cpl_free(selection);
03940 
03941     return cpl_error_get_code();
03942 }
03943 
03944 
03945 /*---------------------------------------------------------------------------*/
03946 
03947 /*
03948  * @brief  Retrieve input parameters
03949  * @param  pipeline_name        Input image
03950  * @param  recipe_name          Input image
03951  * @param  parlist              Shift to apply on the x-axis
03952  * @return CPL_ERROR_NONE on success.
03953  */
03954 
03955 /*---------------------------------------------------------------------------*/
03956 int
03957 irplib_detmon_dark_dfs_set_groups(cpl_frameset * set, const char *tag)
03958 {
03959     cpl_frame              *cur_frame;
03960     const char             *cur_tag;
03961     int                     nframes;
03962     int                     i;
03963 
03964     /* Check entries */
03965     if(set == NULL)
03966         return -1;
03967 
03968     /* Initialize */
03969     nframes = cpl_frameset_get_size(set);
03970 
03971     /* Loop on frames */
03972     for(i = 0; i < nframes; i++) {
03973         cur_frame = cpl_frameset_get_frame(set, i);
03974         cur_tag = cpl_frame_get_tag(cur_frame);
03975 
03976         /* RAW frames */
03977         if(!strcmp(cur_tag, tag))
03978             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
03979         /* CALIB frames */
03980 
03981 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
03982           cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
03983 */
03984     }
03985     return 0;
03986 }
03987 
03988 /*---------------------------------------------------------------------------*/
03989 
03990 /*
03991  * @brief  Retrieve input parameters
03992  * @param  pipeline_name        Input image
03993  * @param  recipe_name          Input image
03994  * @param  parlist              Shift to apply on the x-axis
03995  * @return CPL_ERROR_NONE on success.
03996  */
03997 
03998 /*---------------------------------------------------------------------------*/
03999 static                  cpl_error_code
04000 irplib_detmon_retrieve_dark_params(const char *pipeline_name,
04001                                       const char *recipe_name,
04002                                       const cpl_parameterlist * parlist)
04003 {
04004     char                   *par_name;
04005     cpl_parameter          *par;
04006 
04007     /* --ron.method */
04008     par_name = cpl_sprintf("%s.%s.ron.method", pipeline_name, recipe_name);
04009     assert(par_name != NULL);
04010     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04011     detmon_dark_config.ron_method = cpl_parameter_get_string(par);
04012     cpl_free(par_name);
04013 
04014     /* --dsnu.method */
04015     par_name = cpl_sprintf("%s.%s.dsnu.method", pipeline_name, recipe_name);
04016     assert(par_name != NULL);
04017     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04018     detmon_dark_config.dsnu_method = cpl_parameter_get_string(par);
04019     cpl_free(par_name);
04020 
04021     /* --opt_nir */
04022     par_name = cpl_sprintf("%s.%s.opt_nir", pipeline_name, recipe_name);
04023     assert(par_name != NULL);
04024     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04025     detmon_dark_config.opt_nir = cpl_parameter_get_bool(par);
04026     cpl_free(par_name);
04027 
04028     /* --exts */
04029     detmon_dark_config.exts =
04030         irplib_detmon_retrieve_par("exts", pipeline_name, recipe_name,
04031                                    parlist);
04032 
04033     if(cpl_error_get_code()) {
04034         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
04035         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
04036     }
04037 
04038 
04039     return CPL_ERROR_NONE;
04040 }
04041 
04042 
04043 /*---------------------------------------------------------------------------*/
04044 
04045 /*
04046  * @brief  Retrieve input parameters
04047  * @param  pipeline_name        Input image
04048  * @param  recipe_name          Input image
04049  * @param  parlist              Shift to apply on the x-axis
04050  * @return CPL_ERROR_NONE on success.
04051  */
04052 
04053 /*---------------------------------------------------------------------------*/
04054 cpl_error_code
04055 irplib_detmon_fill_dark_params(cpl_parameterlist * parlist,
04056                                const char *recipe_name,
04057                                const char *pipeline_name,
04058                                const char * ron_method,
04059                                const char * dsnu_method,
04060                                const char * opt_nir,
04061                                int exts)
04062 {
04063     irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 4,
04064 
04065                                "ron.method",
04066                                "Method used to compute RON. Currently no "
04067                    "change is possible, RMS computed",
04068                                "CPL_TYPE_STRING", ron_method,
04069 
04070                                "dsnu.method",
04071                                "Method used to compute DSNU map. Currently no "
04072                    "change is possible. Method used STDEV",
04073                                "CPL_TYPE_STRING", dsnu_method,
04074 
04075                                "opt_nir",
04076                                "Boolean, OPT (FALSE) or NIR(TRUE)",
04077                                "CPL_TYPE_BOOL", opt_nir,
04078 
04079                                "exts",
04080                                "Activate the multi-exts option. Default 0"
04081                    "(primary unit), -1 (all exts)",
04082                                "CPL_TYPE_INT", exts);
04083 
04084     return cpl_error_get_code();
04085 }
04086 
04087 /*---------------------------------------------------------------------------*/
04088 
04089 /*
04090  * @brief  Retrieve input parameters
04091  * @param  pipeline_name        Input image
04092  * @param  recipe_name          Input image
04093  * @param  parlist              Shift to apply on the x-axis
04094  * @return CPL_ERROR_NONE on success.
04095  */
04096 
04097 /*---------------------------------------------------------------------------*/
04098 int
04099 irplib_detmon_fill_dark_params_default(cpl_parameterlist * parlist,
04100                                        const char *recipe_name,
04101                                        const char *pipeline_name)
04102 {
04103     irplib_detmon_fill_dark_params(parlist, recipe_name, pipeline_name,
04104                                    "SIMPLE", /* --ron.method  */
04105                                    "STDEV",  /* --dsnu.method */
04106                                    "CPL_FALSE",  /* OPT*/
04107                                    0);       /* --exts        */
04108     return cpl_error_get_code();
04109 }
04110 
04111 /*---------------------------------------------------------------------------*/
04112 
04113 /*
04114  * @brief  Retrieve input parameters
04115  * @param  pipeline_name        Input image
04116  * @param  recipe_name          Input image
04117  * @param  parlist              Shift to apply on the x-axis
04118  * @return CPL_ERROR_NONE on success.
04119  */
04120 
04121 /*---------------------------------------------------------------------------*/
04122 cpl_error_code
04123 irplib_detmon_dark_dsnu(cpl_frameset * cur_fdit,
04124                         cpl_imagelist * dsnu,
04125                         cpl_table * dsnu_table,
04126                         cpl_image * collapsed,
04127                         int pos)
04128 {
04129     cpl_frame * first = cpl_frameset_get_first(cur_fdit);
04130     cpl_propertylist * plist =
04131         cpl_propertylist_load(cpl_frame_get_filename(first), 0);
04132     double dit = irplib_pfits_get_exptime(plist);
04133     double mean = cpl_image_get_mean(collapsed);
04134 
04135     cpl_image * dsnu_map = 
04136         cpl_image_subtract_scalar_create(collapsed, mean);
04137     double stdev;
04138     cpl_image_divide_scalar(dsnu_map, mean);
04139     stdev = cpl_image_get_stdev(dsnu_map);
04140 
04141     cpl_imagelist_set(dsnu, dsnu_map, pos);
04142 
04143     cpl_table_set(dsnu_table, "DIT", pos, dit);
04144     cpl_table_set(dsnu_table, "STDEV", pos, stdev);
04145 
04146     cpl_propertylist_delete(plist);
04147 
04148     return cpl_error_get_code();
04149 
04150 }
04151 
04152 /*---------------------------------------------------------------------------*/
04153 
04154 /*
04155  * @brief  Retrieve input parameters
04156  * @param  pipeline_name        Input image
04157  * @param  recipe_name          Input image
04158  * @param  parlist              Shift to apply on the x-axis
04159  * @return CPL_ERROR_NONE on success.
04160  */
04161 
04162 /*---------------------------------------------------------------------------*/
04163 static                  cpl_error_code
04164 irplib_detmon_dark_save(const cpl_parameterlist * parlist,
04165                         cpl_frameset * frameset,
04166                         const char *recipe_name,
04167                         const char *pipeline_name,
04168                         const char *procatg_master,
04169                         const char *procatg_tbl,
04170                         const char *procatg_dsnu,
04171                         const char *package,
04172                         cpl_imagelist ** masters,
04173                         cpl_table ** dsnu_table,
04174                         cpl_imagelist ** dsnu,
04175                         cpl_propertylist ** qclist,
04176                         const int flag_sets,
04177                         const int which_set,
04178                         const cpl_frameset * usedframes)
04179 {
04180 
04181     cpl_frame              *ref_frame;
04182     cpl_propertylist       *plist;
04183     char                   *name_o = NULL; /* Avoid (false) uninit warning */
04184     int                     i, j;
04185     cpl_propertylist       *paflist;
04186     cpl_error_code          error;
04187     int nb_images;
04188 
04189     /***************************/
04190     /*  Write the MASTER FITS  */
04191     /***************************/
04192 
04193     nb_images = cpl_imagelist_get_size(masters[0]);
04194     cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
04195 
04196 
04197     for(i = 0; i < nb_images; i++) {
04198         /* Set the file name for each image */
04199         if(!flag_sets) {
04200             name_o =
04201                 cpl_sprintf("%s_master_dit_%d.fits", recipe_name, i+1);
04202             assert(name_o != NULL);
04203         } else {
04204             name_o =
04205                 cpl_sprintf("%s_master_dit_%d_set%02d.fits",
04206                                recipe_name, i, which_set);
04207             assert(name_o != NULL);
04208         }
04209 
04210 
04211         /* Save the image */
04212         if(detmon_dark_config.exts >= 0) {
04213             if(cpl_dfs_save_image
04214                (frameset, parlist, usedframes,
04215                 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
04216                 recipe_name, procatg_master, qclist[0], NULL, package,
04217                 name_o)) {
04218                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04219                               name_o);
04220                 cpl_free(name_o);
04221                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04222 
04223             }
04224         } else {
04225             if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
04226                                   CPL_BPP_IEEE_FLOAT, recipe_name,
04227                                   procatg_master, qclist[0], NULL,
04228                                   package, name_o)) {
04229                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04230                               name_o);
04231                 cpl_free(name_o);
04232                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04233             }
04234 
04235             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04236                 error =
04237                     cpl_image_save(cpl_imagelist_get(masters[j], i),
04238                                    name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04239                                    CPL_IO_EXTEND);
04240                 cpl_ensure_code(!error, error);
04241             }
04242         }
04243     cpl_free(name_o);
04244     }
04245 
04246     if (detmon_dark_config.opt_nir == OPT) {
04247 
04248         /*******************************/
04249         /*  Write the LINEARITY TABLE  */
04250         /*******************************/
04251 
04252         /* Set the file name for the table */
04253         if(!flag_sets) {
04254             name_o = cpl_sprintf("%s_dsnu_table.fits", recipe_name);
04255             assert(name_o != NULL);
04256         } else {
04257             name_o =
04258                 cpl_sprintf("%s_dsnu_table_set%02d.fits", recipe_name,
04259                                which_set);
04260             assert(name_o != NULL);
04261         }
04262 
04263         /* Save the table */
04264         if(cpl_dfs_save_table(frameset, parlist, usedframes, dsnu_table[0],
04265                               NULL, recipe_name, procatg_tbl, qclist[0], NULL,
04266                               package, name_o)) {
04267             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04268             cpl_free(name_o);
04269             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04270         }
04271 
04272         if(detmon_dark_config.exts < 0) {
04273 
04274             for(i = 1; i < detmon_dark_config.nb_extensions; i++) {
04275                 error =
04276                     cpl_table_save(dsnu_table[i], NULL, qclist[i], name_o,
04277                                    CPL_IO_EXTEND);
04278                 cpl_ensure_code(!error, error);
04279             }
04280         }
04281 
04282         /* Free */
04283         cpl_free(name_o);
04284 
04285         /***************************/
04286         /*  Write the DSNU_MAP FITS  */
04287         /***************************/
04288 
04289         for(i = 0; i < nb_images; i++) {
04290             /* Set the file name for each image */
04291             if(!flag_sets) {
04292                 name_o =
04293                     cpl_sprintf("%s_dsnu_map_dit_%d.fits", recipe_name, i+1);
04294                 assert(name_o != NULL);
04295             } else {
04296                 name_o =
04297                     cpl_sprintf("%s_dsnu_map_dit_%d_set%02d.fits",
04298                                    recipe_name, i, which_set);
04299                 assert(name_o != NULL);
04300             }
04301 
04302 
04303             /* Save the image */
04304             if(detmon_dark_config.exts >= 0) {
04305                 if(cpl_dfs_save_image
04306                    (frameset, parlist, usedframes,
04307                     cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
04308                     recipe_name, procatg_dsnu, qclist[0], NULL, package,
04309                     name_o)) {
04310                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04311                                   name_o);
04312                     cpl_free(name_o);
04313                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04314 
04315                 }
04316             } else {
04317                 if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
04318                                       CPL_BPP_IEEE_FLOAT, recipe_name,
04319                                       procatg_dsnu, qclist[0], NULL,
04320                                       package, name_o)) {
04321                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04322                                   name_o);
04323                     cpl_free(name_o);
04324                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04325                 }
04326 
04327                 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04328                     error =
04329                         cpl_image_save(cpl_imagelist_get(dsnu[j], i),
04330                                        name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04331                                        CPL_IO_EXTEND);
04332                     cpl_ensure_code(!error, error);
04333                 }
04334             }
04335         cpl_free(name_o);
04336         }
04337 
04338 
04339 
04340     } /* End of if(OPT) */
04341 
04342     /*******************************/
04343     /*  Write the PAF file(s)      */
04344     /*******************************/
04345 
04346     /* Get FITS header from reference file */
04347     ref_frame = cpl_frameset_get_first(frameset);
04348     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04349                                       0)) == NULL) {
04350         cpl_msg_error(cpl_func, "getting header from reference frame");
04351         cpl_ensure_code(0, cpl_error_get_code());
04352     }
04353 
04354     /* Get the keywords for the paf file */
04355     paflist = cpl_propertylist_new();
04356     cpl_propertylist_copy_property_regexp(paflist, plist,
04357                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
04358                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
04359                                           "ESO DET NCORRS|"
04360                                           "ESO DET MODE NAME)$", 0);
04361 
04362     for(i = 0; i < detmon_dark_config.nb_extensions; i++) {
04363         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
04364         error = cpl_propertylist_append(c_paflist, qclist[i]);
04365         cpl_ensure_code(!error, error);
04366 
04367         /* Set the file name for the bpm */
04368         if(detmon_dark_config.exts >= 0) {
04369             if(!flag_sets) {
04370                 name_o = cpl_sprintf("%s.paf", recipe_name);
04371                 assert(name_o != NULL);
04372             } else {
04373                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
04374                 assert(name_o != NULL);
04375             }
04376         } else {
04377             if(!flag_sets) {
04378                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
04379                 assert(name_o != NULL);
04380             } else {
04381                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
04382                 assert(name_o != NULL);
04383             }
04384         }
04385         /* Save the PAF */
04386         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
04387             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04388             cpl_free(name_o);
04389             cpl_propertylist_delete(paflist);
04390             cpl_propertylist_delete(plist);
04391             cpl_free(name_o);
04392             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04393         }
04394         cpl_propertylist_delete(c_paflist);
04395         cpl_free(name_o);
04396     } 
04397 
04398     cpl_propertylist_delete(plist);
04399     cpl_propertylist_delete(paflist);
04400 
04401     return cpl_error_get_code();
04402 }
04403 
04404 cpl_error_code
04405 irplib_detmon_dark_qc(cpl_propertylist * qclist,
04406                       cpl_image * collapsed)
04407 {
04408     double mean = cpl_image_get_mean(collapsed);
04409     double stdev = cpl_image_get_stdev(collapsed);
04410 
04411     cpl_error_code error;
04412 
04413     error = cpl_propertylist_append_double(qclist, "ESO QC DARK", mean);
04414     cpl_ensure_code(!error, error);
04415 
04416     error = cpl_propertylist_append_double(qclist, "ESO QC DARK STDEV", stdev);
04417     cpl_ensure_code(!error, error);
04418 
04419     return cpl_error_get_code();
04420 }
04421 
04422 
04423 /*---------------------------------------------------------------------------*/
04440 /*---------------------------------------------------------------------------*/
04441 cpl_image * 
04442 irplib_imagelist_collapse_stdev_create(const cpl_imagelist * imlist)
04443 {
04444     cpl_image          *    mean;
04445     cpl_image          *    delta;
04446     cpl_image          *    sq_delta;
04447     cpl_image          *    stdev;
04448 
04449     int                     i;
04450     
04451     /* Check inputs */
04452     cpl_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
04453     cpl_ensure(cpl_imagelist_is_uniform(imlist) == 0, CPL_ERROR_ILLEGAL_INPUT,
04454                NULL);
04455     
04456     /* Create mean image with its first iterative value = first image */
04457     mean = cpl_image_duplicate(cpl_imagelist_get_const(imlist, 0));
04458     cpl_image_fill_rejected(mean, 0.0);
04459     cpl_image_accept_all(mean);
04460 
04461     stdev = cpl_image_new(cpl_image_get_size_x(mean),
04462               cpl_image_get_size_y(mean),
04463               CPL_TYPE_FLOAT);
04464 
04465     for (i = 1; i < cpl_imagelist_get_size(imlist); i++) {
04466         delta = cpl_image_subtract_create(cpl_imagelist_get_const(imlist, i),
04467                                       mean);
04468         cpl_image_fill_rejected(delta, 0.0);
04469         cpl_image_accept_all(delta);
04470 
04471     sq_delta = cpl_image_multiply_create(delta, delta);
04472 
04473     cpl_image_multiply_scalar(sq_delta, ((double) i / (double)(i+1)));
04474     cpl_image_add(stdev, sq_delta);
04475 
04476     cpl_image_divide_scalar(delta, i + 1);
04477     cpl_image_add(mean, delta);
04478 
04479         cpl_image_delete(delta);
04480         cpl_image_delete(sq_delta);
04481     }
04482 
04483     cpl_image_divide_scalar(stdev, cpl_imagelist_get_size(imlist) - 1);
04484     cpl_image_power(stdev, 0.5);
04485 
04486     cpl_image_delete(mean);
04487 
04488     return stdev;    
04489 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.5.2.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Jun 13 14:36:25 2008 by doxygen 1.4.6 written by Dimitri van Heesch, © 1997-2004