irplib_detmon.c

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

Generated on Tue Jun 29 12:16:39 2010 for NACO Pipeline Reference Manual by  doxygen 1.4.7