irplib_detmon.c

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

Generated on Fri Jul 3 11:15:22 2009 for VISIR Pipeline Reference Manual by  doxygen 1.5.8