GIRAFFE Pipeline Reference Manual

irplib_detmon.c

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Tue Jun 2 07:15:35 2009 by doxygen 1.5.1 written by Dimitri van Heesch, © 1997-2004