GIRAFFE Pipeline Reference Manual

irplib_detmon.c

00001 /* $Id: irplib_detmon.c,v 1.232 2010/08/07 07:05:08 amodigli 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: amodigli $
00023  * $Date: 2010/08/07 07:05:08 $
00024  * $Revision: 1.232 $
00025  * $Name:  $
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 /*
03044       fourier =
03045     (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nsamples*nffts);
03046 
03047       input =
03048     (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nsamples*nffts);
03049 
03050       for(i = 0; i< nffts*nsamples; i++){
03051     *((float complex *)input + i) = data[i] + I * 0.0;
03052       }
03053 
03054       p = fftw_create_plan(nsamples, FFTW_FORWARD, FFTW_ESTIMATE);
03055 
03056       fftw(p, nffts, input, 1, nsamples,
03057      fourier, 1, nsamples);
03058 
03059       fftw_destroy_plan(p);
03060 */
03061     for(i = 1; i <= nffts; i++) {
03062         for(j = 1; j <= nsamples; j++) {
03063             int rej = 0;
03064             double complex cvalue = cpl_image_get_complex(fourier_im,j, i, &rej );
03065             double value = cabs(cvalue);
03066                 /*
03067              *(power + j + i * nsamples) = *((float complex *)fourier + j + i * nsamples) *
03068         conjf(*((float complex *)fourier +j + i * nsamples));
03069                 */
03070             cpl_image_set(power_im, j, i, value);
03071         }
03072         /*  Is it necessary to divide here by 2 * pi? */
03073     }
03074     cpl_image_delete(fourier_im);
03075 
03076 /*
03077     fftw_free(fourier);
03078     fftw_free(input);
03079     power_im = cpl_image_wrap_float(nsamples, nffts, power);
03080 */
03081     output   = cpl_image_collapse_create(power_im, 0);
03082     pos_spec = cpl_image_extract(output, 1, 1, nsamples/2, 1);
03083 
03084     /* cpl_image_unwrap(power_im); */
03085     cpl_image_delete(power_im);
03086     cpl_free(power);
03087 
03088     cpl_image_delete(output);
03089 
03090     table = cpl_table_new(nsamples/2);
03091     cpl_table_new_column(table, "FREQ", CPL_TYPE_DOUBLE);
03092     cpl_table_new_column(table, "POW", CPL_TYPE_DOUBLE);
03093 
03094     freq = detmon_pernoise_config.speed*1000/nffts_old;
03095 
03096     for(i = 0; i < nsamples/2; i++) {
03097         error = cpl_table_set(table, "FREQ", i, freq/(nsamples/2)*i);
03098         error = cpl_table_set(table, "POW", i, cpl_image_get(pos_spec, i+1, 1, &status));
03099     }
03100 
03101     for(i= 0; i < 5; i++) {
03102         error = cpl_table_set(table, "POW", i, 0.0);
03103     }
03104 
03105 
03106 cleanup:
03107     cpl_image_delete(pos_spec);
03108 
03109     cpl_image_delete(sub_image);
03110     if (error != CPL_ERROR_NONE)
03111     {
03112         cpl_table_delete(table);
03113         table = 0;
03114     }
03115     return table;
03116 }
03117 #undef HORIZONTAL
03118 
03119 
03120 
03121 /*---------------------------------------------------------------------------*/
03122 
03123 /*
03124  * @brief  Retrieve input parameters
03125  * @param  pipeline_name        Input image
03126  * @param  recipe_name          Input image
03127  * @param  parlist              Shift to apply on the x-axis
03128  * @return CPL_ERROR_NONE on success.
03129  */
03130 
03131 /*---------------------------------------------------------------------------*/
03132 
03133 
03134 cpl_error_code
03135 irplib_detmon_rm_bpixs(cpl_image ** image,
03136                        const double kappa, int nffts, int nsamples)
03137 {
03138     int                     i, j;
03139 
03140     float                  *data = cpl_image_get_data_float(*image);
03141     int k = 0;
03142     for(i = 0; i < nffts; i++) {
03143         for(j = 0; j < nsamples; j++) {
03144             float                   neighbours = 0;
03145             int                     nneighs = 0;
03146             float                   average = 0;
03147 
03148             /*
03149              * Look for the way to optimize this:
03150              * Some of the points added to neighbours coincide
03151              * in one iteration and the following
03152              */
03153             if(i > 0) {
03154                 neighbours += *(data + (i - 1) * nsamples + j);
03155                 nneighs++;
03156             }
03157             if(i < nffts - 1) {
03158                 neighbours += *(data + (i + 1) * nsamples + j);
03159                 nneighs++;
03160             }
03161             if(j > 0) {
03162                 neighbours += *(data + i * nsamples + (j - 1));
03163                 nneighs++;
03164             }
03165             if(j < nsamples - 1) {
03166                 neighbours += *(data + i * nsamples + (j + 1));
03167                 nneighs++;
03168             }
03169             average = neighbours / nneighs;
03170             if(average > 0) {
03171                 if(*(data + i * nsamples + j) < average * (-1 * kappa) ||
03172                    *(data + i * nsamples + j) > average * (kappa)) {
03173                     k++;
03174                     *(data + i * nsamples + j) = average;
03175                 }
03176             }
03177             if(average < 0) {
03178                 if(*(data + i * nsamples + j) > average * (-1 * kappa) ||
03179                    *(data + i * nsamples + j) < average * (kappa)) {
03180                     k++;
03181                     *(data + i * nsamples + j) = average;
03182                 }
03183             }
03184 
03185         }
03186     }
03187 
03188 
03189     return cpl_error_get_code();
03190 
03191 }
03192 
03193 /* Start duplicated code */
03194 
03195 #define RECT_RON_HS         4
03196 #define RECT_RON_SAMPLES    100
03197 
03198 /*---------------------------------------------------------------------------*/
03199 
03200 /*
03201  * @brief  Retrieve input parameters
03202  * @param  pipeline_name        Input image
03203  * @param  recipe_name          Input image
03204  * @param  parlist              Shift to apply on the x-axis
03205  * @return CPL_ERROR_NONE on success.
03206  */
03207 
03208 /*---------------------------------------------------------------------------*/
03209 cpl_error_code
03210 irplib_flux_get_bias_window(const cpl_image * diff,
03211                             const int *zone_def,
03212                             int ron_hsize,
03213                             int ron_nsamp, double *bias, double *error)
03214 {
03215     const int               hsize = ron_hsize < 0 ? RECT_RON_HS : ron_hsize;
03216     const int               nsamples =
03217         ron_nsamp < 0 ? RECT_RON_SAMPLES : ron_nsamp;
03218     cpl_bivector           *sample_reg;
03219     cpl_vector             *rms_list;
03220     int                     rect[4];
03221     int                     zone[4];
03222     double                 *px;
03223     double                 *py;
03224     double                 *pr;
03225     int                     i;
03226 
03227     /* Test entries */
03228     cpl_ensure_code(diff && bias, CPL_ERROR_NULL_INPUT);
03229 
03230     /* Generate nsamples window centers in the image */
03231     if(zone_def != NULL) {
03232         rect[0] = zone_def[0] + hsize + 1;      /* xmin */
03233         rect[1] = zone_def[1] - hsize - 1;      /* xmax */
03234         rect[2] = zone_def[2] + hsize + 1;      /* ymin */
03235         rect[3] = zone_def[3] - hsize - 1;      /* ymax */
03236     } else {
03237         rect[0] = hsize + 1;    /* xmin */
03238         rect[1] = cpl_image_get_size_x(diff) - hsize - 1;       /* xmax */
03239         rect[2] = hsize + 1;    /* ymin */
03240         rect[3] = cpl_image_get_size_y(diff) - hsize - 1;       /* ymax */
03241     }
03242 
03243     cpl_ensure_code(rect[0] < rect[1] && rect[2] < rect[3],
03244                     CPL_ERROR_ILLEGAL_INPUT);
03245 
03246     /* Generate n+1 regions, because the first region is always at (0,0) */
03247     /* and it would bias the measurement. */
03248     sample_reg =
03249         irplib_bivector_gen_rect_poisson(rect, nsamples + 1, nsamples + 1);
03250     cpl_ensure(sample_reg != NULL, CPL_ERROR_ILLEGAL_INPUT,
03251                CPL_ERROR_ILLEGAL_INPUT);
03252 
03253     px = cpl_bivector_get_x_data(sample_reg);
03254     py = cpl_bivector_get_y_data(sample_reg);
03255 
03256     /* Now, for each window center, extract a vignette and compute the */
03257     /* signal RMS in it. Store this rms into a table. */
03258     rms_list = cpl_vector_new(nsamples);
03259     cpl_ensure(rms_list != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
03260     pr = cpl_vector_get_data(rms_list);
03261 
03262     for(i = 0; i < nsamples; i++) {
03263         zone[0] = (int) px[i + 1] - hsize;
03264         zone[1] = (int) px[i + 1] + hsize;
03265         zone[2] = (int) py[i + 1] - hsize;
03266         zone[3] = (int) py[i + 1] + hsize;
03267         pr[i] = cpl_image_get_mean_window(diff,
03268                                           zone[0], zone[2], zone[1], zone[3]);
03269     }
03270     cpl_bivector_delete(sample_reg);
03271 
03272     /* The error is the rms of the rms */
03273     if(error != NULL)
03274         *error = cpl_vector_get_stdev(rms_list);
03275 
03276     /* The final computed RMS is the median of all values.  */
03277     /* This call will modify the rms_list */
03278     *bias = cpl_vector_get_median(rms_list);
03279 
03280     cpl_vector_delete(rms_list);
03281 
03282     return CPL_ERROR_NONE;
03283 }
03284 
03285 #undef RECT_RON_HS
03286 #undef RECT_RON_SAMPLES
03287 
03288 /*---------------------------------------------------------------------------*/
03289 
03290 /*
03291  * @brief  Retrieve input parameters
03292  * @param  pipeline_name        Input image
03293  * @param  recipe_name          Input image
03294  * @param  parlist              Shift to apply on the x-axis
03295  * @return CPL_ERROR_NONE on success.
03296  */
03297 
03298 /*---------------------------------------------------------------------------*/
03299 static cpl_bivector    *
03300 irplib_bivector_gen_rect_poisson(const int *r, const int np, const int homog)
03301 {
03302     double                  min_dist;
03303     int                     i;
03304     int                     gnp;
03305     cpl_bivector           *list;
03306     double                  cand_x, cand_y;
03307     int                     ok;
03308     int                     start_ndx;
03309     int                     xmin, xmax, ymin, ymax;
03310 
03311     /* Corrected Homogeneity factor */
03312     const int               homogc = 0 < homog && homog < np ? homog : np;
03313     double                 *px;
03314     double                 *py;
03315 
03316     /* error handling: test arguments are correct */
03317     cpl_ensure(r, CPL_ERROR_NULL_INPUT, NULL);
03318     cpl_ensure(np > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
03319 
03320     list = cpl_bivector_new(np);
03321     cpl_ensure(list, CPL_ERROR_NULL_INPUT, NULL);
03322     px = cpl_bivector_get_x_data(list);
03323     py = cpl_bivector_get_y_data(list);
03324 
03325     xmin = r[0];
03326     xmax = r[1];
03327     ymin = r[2];
03328     ymax = r[3];
03329 
03330     min_dist =
03331         CPL_MATH_SQRT1_2 * ((xmax - xmin) * (ymax - ymin) / (double) (homogc + 1));
03332     gnp = 1;
03333     px[0] = 0;
03334     py[0] = 0;
03335 
03336     /* First: generate <homog> points */
03337     while(gnp < homogc) {
03338         /* Pick a random point within requested range */
03339         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03340         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03341 
03342         /* Check the candidate obeys the minimal Poisson distance */
03343         ok = 1;
03344         for(i = 0; i < gnp; i++) {
03345             if(pdist(cand_x, cand_y, px[i], py[i]) < min_dist) {
03346                 /* does not check Poisson law: reject point */
03347                 ok = 0;
03348                 break;
03349             }
03350         }
03351         if(ok) {
03352             /* obeys Poisson law: register the point as valid */
03353             px[gnp] = cand_x;
03354             py[gnp] = cand_y;
03355             gnp++;
03356         }
03357     }
03358 
03359     /* Iterative process: */
03360     /* Pick points out of Poisson distance of the last <homogc-1> points. */
03361     start_ndx = 0;
03362     while(gnp < np) {
03363         /* Pick a random point within requested range */
03364         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03365         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03366 
03367         /* Check the candidate obeys the minimal Poisson distance */
03368         ok = 1;
03369         for(i = 0; i < homogc; i++) {
03370             if(pdist(cand_x,
03371                      cand_y,
03372                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
03373                 /* does not check Poisson law: reject point */
03374                 ok = 0;
03375                 break;
03376             }
03377         }
03378         if(ok) {
03379             /* obeys Poisson law: register the point as valid */
03380             px[gnp] = cand_x;
03381             py[gnp] = cand_y;
03382             gnp++;
03383         }
03384     }
03385 
03386     /* Iterative process: */
03387     /* Pick points out of Poisson distance of the last <homogc-1> points. */
03388     start_ndx = 0;
03389     while(gnp < np) {
03390         /* Pick a random point within requested range */
03391         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03392         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03393 
03394         /* Check the candidate obeys the minimal Poisson distance */
03395         ok = 1;
03396         for(i = 0; i < homogc; i++) {
03397             if(pdist(cand_x,
03398                      cand_y,
03399                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
03400                 /* does not check Poisson law: reject point */
03401                 ok = 0;
03402                 break;
03403             }
03404         }
03405         if(ok) {
03406             /* obeys Poisson law: register the point as valid */
03407             px[gnp] = cand_x;
03408             py[gnp] = cand_y;
03409             gnp++;
03410             start_ndx++;
03411         }
03412     }
03413     return list;
03414 }
03415 
03416 /* End of duplicated code */
03417 
03418 /*---------------------------------------------------------------------------*/
03419 
03420 /*
03421  * @brief  Retrieve input parameters
03422  * @param  pipeline_name        Input image
03423  * @param  recipe_name          Input image
03424  * @param  parlist              Shift to apply on the x-axis
03425  * @return CPL_ERROR_NONE on success.
03426  */
03427 
03428 /*---------------------------------------------------------------------------*/
03429 cpl_error_code
03430 irplib_detmon_pernoise(cpl_frameset      * frameset,
03431                        const cpl_parameterlist * parlist,
03432                        const char        * tag,
03433                        const char        * recipe_name,
03434                        const char        * pipeline_name,
03435                        const char        * procatg_tbl,
03436                        const char        * package,
03437                        int              (*compare)(const cpl_frame *,
03438                                                    const cpl_frame *))
03439 {
03440     int                     nsets;
03441     int                    *selection = NULL;
03442     int                     i;
03443     cpl_error_code          error;
03444 
03445     if(irplib_detmon_pernoise_dfs_set_groups(frameset, tag)) {
03446         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
03447     }
03448 
03449     /*
03450      * This function reads all inputs parameters from parlist
03451      * and stores them in a global variable detmon_ronbias_config.
03452      * Similar to irplib_detmon_lg_retrieve_parlist(). See irplib_detmon.c
03453      */
03454     error = irplib_detmon_pernoise_retrieve_parlist(pipeline_name,
03455                                                    recipe_name, parlist);
03456     cpl_ensure_code(!error, error);
03457 
03458     /* Labelise all input frames */
03459     if(compare == NULL)
03460         nsets = 1;
03461     else {
03462         cpl_msg_info(cpl_func, "Identify the different settings");
03463         selection = cpl_frameset_labelise(frameset, compare, &nsets);
03464         if(selection == NULL)
03465             cpl_msg_error(cpl_func, "Cannot labelise input frames");
03466     }
03467 
03468     detmon_pernoise_config.nb_extensions = 1;
03469     if(detmon_pernoise_config.exts < 0) {
03470         const cpl_frame        *cur_frame =
03471             cpl_frameset_get_first_const(frameset);
03472         /* Get the nb of extensions */
03473         detmon_pernoise_config.nb_extensions =
03474             cpl_frame_get_nextensions(cur_frame);
03475     }
03476 
03477     /* Extract settings and reduce each of them */
03478     for(i = 0; i < nsets; i++)
03479     {
03480         int j;
03481         cpl_table ** freq_table;
03482         cpl_propertylist ** qclist =
03483             (cpl_propertylist **)
03484             cpl_malloc(detmon_pernoise_config.nb_extensions *
03485                        sizeof(cpl_propertylist *));
03486 
03487         cpl_imagelist ** raws = (cpl_imagelist **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_imagelist *));
03488         cpl_image ** input = (cpl_image **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_image *));
03489 
03490         /* Initialise memory for products */
03491         if(detmon_pernoise_config.mode == 1)
03492         {
03493             freq_table =
03494                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03495                                           4 * sizeof(cpl_table *));
03496         } else
03497         {
03498             freq_table =
03499                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03500                                           sizeof(cpl_table *));
03501         }
03502 
03503         if(detmon_pernoise_config.exts >= 0)
03504         {
03505             *raws =
03506                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03507                                             detmon_pernoise_config.exts);
03508             *input = cpl_image_subtract_create(cpl_imagelist_get(*raws,0),
03509                                                cpl_imagelist_get(*raws,1));
03510         } else
03511         {
03512             cpl_imagelist          *raws_all_exts =
03513                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03514                                             -1);
03515             for(j = 0; j < detmon_pernoise_config.nb_extensions; j++)
03516             {
03517                 int nframes = cpl_frameset_get_size(frameset);
03518                 int                     k;
03519                 for(k = 0; k < nframes; k++)
03520                 {
03521                     cpl_image              *image =
03522                         cpl_imagelist_unset(raws_all_exts,
03523                                             (detmon_pernoise_config.
03524                                              nb_extensions - 1 - j) * k);
03525                     cpl_imagelist_set(raws[j], image, k);
03526                 }
03527                 input[j] =
03528                     cpl_image_subtract_create(cpl_imagelist_get(raws[j],0),
03529                                               cpl_imagelist_get(raws[j],1));
03530             }
03531         }
03532 
03533         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++) {
03534             cpl_msg_info(cpl_func, "Starting reduction");
03535             qclist[j] = cpl_propertylist_new();
03536             if(detmon_pernoise_config.mode == 1)
03537             {
03538                 int nx = cpl_image_get_size_x(input[j]);
03539                 int ny = cpl_image_get_size_y(input[j]);
03540                 int k = 0;
03541                 cpl_image* quad[4];
03542 
03543                 quad[0] = cpl_image_extract(input[j], 1, 1, nx/2, ny/2);
03544                 quad[1] = cpl_image_extract(input[j], 1, ny/2+1, nx/2, ny);
03545                 quad[2] = cpl_image_extract(input[j], nx/2+1, 1, nx, ny/2);
03546                 quad[3] = cpl_image_extract(input[j], nx/2+1, ny/2+1, nx, ny);
03547 
03548                 for (k = 0; k < 4; k++)
03549                 {
03550                     freq_table[j * 4 + k] = irplib_detmon_pernoise_reduce(quad[k]);
03551                 }
03552                 for(k = 0; k < 4; k++)
03553                 {
03554                     error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j + k], k+1);
03555                     if (error != CPL_ERROR_NONE)
03556                         break;
03557                 }
03558                 for (k = 0; k < 4; k++)
03559                 {
03560                     cpl_image_delete(quad[k]);
03561                 }
03562             } else
03563             {
03564                 freq_table[j] = irplib_detmon_pernoise_reduce(input[j]);
03565                 if(freq_table[j] != NULL)
03566                 {
03567                     error = irplib_detmon_pernoise_qc(qclist[j], freq_table[j], 0);
03568                 }
03569             }
03570             if (error != CPL_ERROR_NONE)
03571             {
03572                 break;
03573             }
03574         }
03575         if (error == CPL_ERROR_NONE)
03576         {
03577             error = irplib_detmon_pernoise_save(parlist, frameset, recipe_name,
03578                                             pipeline_name, procatg_tbl,
03579                                             package, freq_table, qclist, 0,
03580                                             0, frameset);
03581         }
03582 
03583         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++)
03584         {
03585             cpl_propertylist_delete(qclist[j]);
03586             cpl_imagelist_delete(raws[j]);
03587             cpl_image_delete(input[j]);
03588         }
03589         cpl_free(qclist);
03590         cpl_free(raws);
03591         cpl_free(input);
03592         if(detmon_pernoise_config.mode == 1)
03593         {
03594             for(j= 0; j < detmon_pernoise_config.nb_extensions * 4; j++) {
03595                 cpl_table_delete(freq_table[j]);
03596             }
03597         } else {
03598             for(j= 0; j < detmon_pernoise_config.nb_extensions; j++) {
03599                 cpl_table_delete(freq_table[j]);
03600             }
03601         }
03602         cpl_free(freq_table);
03603         if (error != CPL_ERROR_NONE)
03604         {
03605             break;
03606         }
03607     }
03608 
03609     return cpl_error_get_code();
03610 }
03611 
03612 /*---------------------------------------------------------------------------*/
03613 
03614 /*
03615  * @brief  Retrieve input parameters
03616  * @param  pipeline_name        Input image
03617  * @param  recipe_name          Input image
03618  * @param  parlist              Shift to apply on the x-axis
03619  * @return CPL_ERROR_NONE on success.
03620  */
03621 
03622 /*---------------------------------------------------------------------------*/
03623 int
03624 irplib_detmon_pernoise_dfs_set_groups(cpl_frameset * set, const char *tag)
03625 {
03626     cpl_frame              *cur_frame;
03627     const char             *cur_tag;
03628     int                     nframes;
03629     int                     i;
03630 
03631     /* Check entries */
03632     if(set == NULL)
03633         return -1;
03634 
03635     /* Initialize */
03636     nframes = cpl_frameset_get_size(set);
03637 
03638     /* Loop on frames */
03639     for(i = 0; i < nframes; i++) {
03640         cur_frame = cpl_frameset_get_frame(set, i);
03641         cur_tag = cpl_frame_get_tag(cur_frame);
03642 
03643         /* RAW frames */
03644         if(!strcmp(cur_tag, tag))
03645             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
03646         /* CALIB frames */
03647 
03648 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
03649           cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
03650 */
03651     }
03652     return 0;
03653 }
03654 
03655 /*---------------------------------------------------------------------------*/
03656 
03657 /*
03658  * @brief  Retrieve input parameters
03659  * @param  pipeline_name        Input image
03660  * @param  recipe_name          Input image
03661  * @param  parlist              Shift to apply on the x-axis
03662  * @return CPL_ERROR_NONE on success.
03663  */
03664 
03665 /*---------------------------------------------------------------------------*/
03666 cpl_error_code
03667 irplib_detmon_fill_pernoise_params(cpl_parameterlist * parlist,
03668                                    const char *recipe_name,
03669                                    const char *pipeline_name,
03670                                    int mode,
03671                                    const char * direction,
03672                                    double speed,
03673                                    int llx,
03674                                    int lly,
03675                                    int urx,
03676                                    int ury,
03677                                    double kappa,
03678                                    int exts)
03679 {
03680     irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 9,
03681 
03682                                "mode",
03683                                "Mode",
03684                                "CPL_TYPE_INT", mode,
03685 
03686                                "direction",
03687                                "Readout direction",
03688                                "CPL_TYPE_BOOL", direction,
03689 
03690                                "speed",
03691                                "Readout speed",
03692                                "CPL_TYPE_DOUBLE", speed,
03693 
03694                                "llx",
03695                                "(yet unsupported) x coordinate of the lower-left "
03696                                "point of the region of interest. If not modified, default value will be 1.",
03697                                "CPL_TYPE_INT", llx,
03698                                "lly",
03699                                "(yet unsupported) y coordinate of the lower-left "
03700                                "point of the region of interest. If not modified, default value will be 1.",
03701                                "CPL_TYPE_INT", lly,
03702                                "urx",
03703                                "(yet unsupported) x coordinate of the upper-right "
03704                                "point of the region of interest. If not modified, default value will be X dimension of the input image.",
03705                                "CPL_TYPE_INT", urx,
03706                                "ury",
03707                                "(yet unsupported) y coordinate of the upper-right "
03708                                "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
03709                                "CPL_TYPE_INT", ury,
03710 
03711                                "kappa",
03712                                "Kappa used for determining threshold of bad (hot, cold) pixels",
03713                                "CPL_TYPE_DOUBLE", kappa,
03714 
03715                                "exts",
03716                                "Activate the multi-exts option",
03717                                "CPL_TYPE_INT", exts);
03718 
03719     return 0;
03720 }
03721 
03722 /*---------------------------------------------------------------------------*/
03723 
03724 /*
03725  * @brief  Retrieve input parameters
03726  * @param  pipeline_name        Input image
03727  * @param  recipe_name          Input image
03728  * @param  parlist              Shift to apply on the x-axis
03729  * @return CPL_ERROR_NONE on success.
03730  */
03731 
03732 /*---------------------------------------------------------------------------*/
03733 int
03734 irplib_detmon_fill_pernoise_params_default(cpl_parameterlist * parlist,
03735                                            const char *recipe_name,
03736                                            const char *pipeline_name)
03737 {
03738     irplib_detmon_fill_pernoise_params(parlist, recipe_name, pipeline_name,
03739                                        1,           /* --mode      */
03740                                        "CPL_TRUE",  /* --direction */
03741                                        84.5,        /* --speed     */
03742                                        -1,          /* --llx       */
03743                                        -1,          /* --lly       */
03744                                        -1,          /* --urx       */
03745                                        -1,          /* --ury       */
03746                                        100,          /* --kappa     */
03747                                        0);          /* --exts      */
03748 
03749     return 0;
03750 
03751 }
03752 
03753 
03754 static cpl_error_code
03755 irplib_detmon_pernoise_retrieve_parlist(const char *pipeline_name,
03756                                        const char *recipe_name,
03757                                        const cpl_parameterlist * parlist)
03758 {
03759     char                   *par_name;
03760     cpl_parameter          *par;
03761 
03762     /* --mode */
03763     detmon_pernoise_config.mode =
03764         irplib_detmon_retrieve_par_int("mode", pipeline_name, recipe_name,
03765                                    parlist);
03766 
03767     /* --direction */
03768     par_name = cpl_sprintf("%s.%s.direction", pipeline_name, recipe_name);
03769     assert(par_name != NULL);
03770     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03771     detmon_pernoise_config.direction = cpl_parameter_get_bool(par);
03772     cpl_free(par_name);
03773 
03774     /* --speed */
03775     par_name = cpl_sprintf("%s.%s.speed", pipeline_name, recipe_name);
03776     assert(par_name != NULL);
03777     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03778     detmon_pernoise_config.speed = cpl_parameter_get_double(par);
03779     cpl_free(par_name);
03780 
03781     /* --llx */
03782     detmon_pernoise_config.llx =
03783         irplib_detmon_retrieve_par_int("llx", pipeline_name, recipe_name,
03784                                    parlist);
03785 
03786     /* --lly */
03787     detmon_pernoise_config.lly =
03788         irplib_detmon_retrieve_par_int("lly", pipeline_name, recipe_name,
03789                                    parlist);
03790     /* --urx */
03791     detmon_pernoise_config.urx =
03792         irplib_detmon_retrieve_par_int("urx", pipeline_name, recipe_name,
03793                                    parlist);
03794     /* --ury */
03795     detmon_pernoise_config.ury =
03796         irplib_detmon_retrieve_par_int("ury", pipeline_name, recipe_name,
03797                                    parlist);
03798     /* --kappa */
03799     detmon_pernoise_config.kappa =
03800         irplib_detmon_retrieve_par_double("kappa", pipeline_name, recipe_name,
03801                                    parlist);
03802 
03803     /* --exts */
03804     detmon_pernoise_config.exts =
03805         irplib_detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
03806                                    parlist);
03807 
03808     if(cpl_error_get_code()) {
03809         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
03810         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
03811     }
03812 
03813     return cpl_error_get_code();
03814 }
03815 
03816 /*---------------------------------------------------------------------------*/
03817 
03818 /*
03819  * @brief  Retrieve input parameters
03820  * @param  pipeline_name        Input image
03821  * @param  recipe_name          Input image
03822  * @param  parlist              Shift to apply on the x-axis
03823  * @return CPL_ERROR_NONE on success.
03824  */
03825 
03826 /*---------------------------------------------------------------------------*/
03827 static                  cpl_error_code
03828 irplib_detmon_pernoise_save(const cpl_parameterlist * parlist,
03829                             cpl_frameset * frameset,
03830                             const char *recipe_name,
03831                             const char *pipeline_name,
03832                             const char *procatg_tbl,
03833                             const char *package,
03834                             cpl_table ** freq_table,
03835                             cpl_propertylist ** qclist,
03836                             const int flag_sets,
03837                             const int which_set,
03838                             const cpl_frameset * usedframes)
03839 {
03840 
03841     cpl_frame              *ref_frame;
03842     cpl_propertylist       *plist;
03843     char                   *name_o = NULL; /* Avoid (false) uninit warning */
03844     int                     i, j;
03845     cpl_propertylist       *paflist;
03846     cpl_error_code          error;
03847 
03848 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
03849     cpl_propertylist * pro_tbl = cpl_propertylist_new();
03850 
03851     cpl_propertylist_append_string(pro_tbl,
03852                                    CPL_DFS_PRO_CATG, procatg_tbl);
03853 
03854     cpl_propertylist_append(pro_tbl, qclist[0]);
03855 
03856 #endif
03857     /*******************************/
03858     /*  Write the FREQ TABLE  */
03859 
03860     /*******************************/
03861 
03862     if(detmon_pernoise_config.mode != 1) {
03863         /* Set the file name for the table */
03864         if(!flag_sets) {
03865             name_o = cpl_sprintf("%s_freq_table.fits", recipe_name);
03866             assert(name_o != NULL);
03867         } else {
03868             name_o =
03869                 cpl_sprintf("%s_freq_table_set%02d.fits", recipe_name,
03870                                which_set);
03871             assert(name_o != NULL);
03872         }
03873 
03874 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
03875         /* Save the table */
03876         if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, freq_table[0],
03877                               NULL, recipe_name, pro_tbl, NULL,
03878                               package, name_o)) {
03879             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03880             cpl_free(name_o);
03881             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03882         }
03883 #else
03884         /* Save the table */
03885         if(cpl_dfs_save_table(frameset, parlist, usedframes, freq_table[0],
03886                               NULL, recipe_name, procatg_tbl, qclist[0], NULL,
03887                               package, name_o)) {
03888             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03889             cpl_free(name_o);
03890             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03891         }
03892 #endif
03893 
03894         if(detmon_pernoise_config.exts < 0) {
03895 
03896             for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03897                 error =
03898                     cpl_table_save(freq_table[i], NULL, qclist[i], name_o,
03899                                    CPL_IO_EXTEND);
03900                 cpl_ensure_code(!error, error);
03901             }
03902         }
03903 
03904         /* Free */
03905         cpl_free(name_o);
03906 
03907     } else {
03908         for (j = 1; j <= 4; j++) {
03909             /* Set the file name for the table */
03910             if(!flag_sets) {
03911                 name_o = cpl_sprintf("%s_freq_table_quad%02d.fits",
03912                                         recipe_name, j);
03913                 assert(name_o != NULL);
03914             } else {
03915                 name_o =
03916                     cpl_sprintf("%s_freq_table_quad%02d_set%02d.fits",
03917                                    recipe_name, j, which_set);
03918                 assert(name_o != NULL);
03919             }
03920 
03921 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
03922             /* Save the table */
03923             if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
03924                                   freq_table[j - 1],
03925                                   NULL, recipe_name, pro_tbl, NULL,
03926                                   package, name_o)) {
03927                 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03928                 cpl_free(name_o);
03929                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03930             }
03931 #else
03932             /* Save the table */
03933             if(cpl_dfs_save_table(frameset, parlist, usedframes,
03934                                   freq_table[j - 1],
03935                                   NULL, recipe_name, procatg_tbl, qclist[0], NULL,
03936                                   package, name_o)) {
03937                 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03938                 cpl_free(name_o);
03939                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03940             }
03941 #endif
03942 
03943             if(detmon_pernoise_config.exts < 0) {
03944                 for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03945                     error = cpl_table_save(freq_table[(j-1) + 4 * i],
03946                                            NULL, qclist[i], name_o,
03947                                            CPL_IO_EXTEND);
03948                     cpl_ensure_code(!error, error);
03949                 }
03950             }
03951 
03952             /* Free */
03953             cpl_free(name_o);
03954         }
03955 
03956     }
03957     /*******************************/
03958     /*  Write the PAF file(s)      */
03959     /*******************************/
03960 
03961     /* Get FITS header from reference file */
03962     ref_frame = cpl_frameset_get_first(frameset);
03963     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03964                                       0)) == NULL) {
03965         cpl_msg_error(cpl_func, "getting header from reference frame");
03966         cpl_ensure_code(0, cpl_error_get_code());
03967     }
03968 
03969     /* Get the keywords for the paf file */
03970     paflist = cpl_propertylist_new();
03971     cpl_propertylist_copy_property_regexp(paflist, plist,
03972                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
03973                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
03974                                           "ESO DET NCORRS|"
03975                                           "ESO DET MODE NAME)$", 0);
03976 
03977     for(i = 0; i < detmon_pernoise_config.nb_extensions; i++) {
03978         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
03979         error = cpl_propertylist_append(c_paflist, qclist[i]);
03980         cpl_ensure_code(!error, error);
03981 
03982         /* Set the file name for the bpm */
03983         if(detmon_pernoise_config.exts >= 0) {
03984             if(!flag_sets) {
03985                 name_o = cpl_sprintf("%s.paf", recipe_name);
03986                 assert(name_o != NULL);
03987             } else {
03988                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
03989                 assert(name_o != NULL);
03990             }
03991         } else {
03992             if(!flag_sets) {
03993                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
03994                 assert(name_o != NULL);
03995             } else {
03996                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
03997                 assert(name_o != NULL);
03998             }
03999         }
04000         /* Save the PAF */
04001         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
04002             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04003             cpl_free(name_o);
04004             cpl_propertylist_delete(paflist);
04005             cpl_propertylist_delete(plist);
04006             cpl_free(name_o);
04007             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04008         }
04009         cpl_propertylist_delete(c_paflist);
04010         cpl_free(name_o);
04011     }
04012 
04013     cpl_propertylist_delete(plist);
04014     cpl_propertylist_delete(paflist);
04015 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04016     cpl_propertylist_delete(pro_tbl);
04017 #endif
04018     return cpl_error_get_code();
04019 }
04020 
04021 static cpl_error_code
04022 irplib_detmon_pernoise_qc(cpl_propertylist * qclist,
04023                           cpl_table * table,
04024                           int iquad)
04025 {
04026     cpl_error_code error;
04027     char * propname;
04028 
04029     double freqs[3] = {0, 0, 0};
04030     double pows[3] = {0, 0, 0};
04031 
04032 /*    error = cpl_propertylist_append_bool(reflist, "POW", TRUE);
04033     cpl_ensure_code(!error, error);
04034 
04035     error = cpl_table_sort(table, reflist);
04036     cpl_ensure_code(!error, error);
04037 */
04038 
04039     int nrows = cpl_table_get_nrow(table);
04040     int i;
04041 
04042     double * all_freqs = cpl_table_get_data_double(table, "FREQ");
04043     double * all_pows  = cpl_table_get_data_double(table, "POW");
04044 
04045     for ( i= 1; i< nrows-1; i++){
04046         if (all_pows[i] > pows[0]) {
04047             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
04048                 pows[2]=pows[1];
04049                 pows[1]=pows[0];
04050                 pows[0]=all_pows[i];
04051 
04052                 freqs[2]=freqs[1];
04053                 freqs[1]=freqs[0];
04054                 freqs[0]=all_freqs[i];
04055             }
04056         } else if (all_pows[i] > pows[1]) {
04057             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
04058                 pows[2]=pows[1];
04059                 pows[1]=all_pows[i];
04060 
04061                 freqs[2]=freqs[1];
04062                 freqs[1]=all_freqs[i];
04063             }
04064 
04065         } else if(all_pows[i] > pows[2]) {
04066             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
04067                 pows[2]=all_pows[i];
04068 
04069                 freqs[2]=all_freqs[i];
04070             }
04071 
04072         }
04073     }
04074 
04075     if (detmon_pernoise_config.mode == 1) {
04076         propname = cpl_sprintf("ESO QC FREQ1 %d", iquad);
04077         assert(propname != NULL);
04078     } else {
04079         propname = cpl_sprintf("ESO QC FREQ1");
04080     }
04081 
04082     error = cpl_propertylist_append_double(qclist, propname, freqs[0]);
04083     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
04084     cpl_ensure_code(!error, error);
04085 
04086     cpl_free(propname);
04087 
04088     if (detmon_pernoise_config.mode == 1) {
04089         propname = cpl_sprintf("ESO QC FREQ2 %d", iquad);
04090         assert(propname != NULL);
04091     } else {
04092         propname = cpl_sprintf("ESO QC FREQ2");
04093     }
04094 
04095     error = cpl_propertylist_append_double(qclist, propname, freqs[1]);
04096     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
04097     cpl_ensure_code(!error, error);
04098 
04099     cpl_free(propname);
04100 
04101     if (detmon_pernoise_config.mode == 1) {
04102         propname = cpl_sprintf("ESO QC FREQ3 %d", iquad);
04103         assert(propname != NULL);
04104     } else {
04105         propname = cpl_sprintf("ESO QC FREQ3");
04106     }
04107 
04108     error = cpl_propertylist_append_double(qclist, propname, freqs[2]);
04109     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
04110     cpl_ensure_code(!error, error);
04111 
04112     cpl_free(propname);
04113 
04114     if (detmon_pernoise_config.mode == 1) {
04115         propname = cpl_sprintf("ESO QC POW1 %d", iquad);
04116         assert(propname != NULL);
04117     } else {
04118         propname = cpl_sprintf("ESO QC POW1");
04119     }
04120 
04121     error = cpl_propertylist_append_double(qclist, propname, pows[0]);
04122     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
04123     cpl_ensure_code(!error, error);
04124 
04125     cpl_free(propname);
04126 
04127     if (detmon_pernoise_config.mode == 1) {
04128         propname = cpl_sprintf("ESO QC POW2 %d", iquad);
04129         assert(propname != NULL);
04130     } else {
04131         propname = cpl_sprintf("ESO QC POW2");
04132     }
04133 
04134     error = cpl_propertylist_append_double(qclist, propname, pows[1]);
04135     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
04136     cpl_ensure_code(!error, error);
04137 
04138     cpl_free(propname);
04139 
04140     if (detmon_pernoise_config.mode == 1) {
04141         propname = cpl_sprintf("ESO QC POW3 %d", iquad);
04142         assert(propname != NULL);
04143     } else {
04144         propname = cpl_sprintf("ESO QC POW3");
04145     }
04146 
04147     error = cpl_propertylist_append_double(qclist, propname, pows[2]);
04148     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
04149     cpl_ensure_code(!error, error);
04150 
04151 
04152     cpl_free(propname);
04153 
04154     return cpl_error_get_code();
04155 }
04156 
04157 /*---------------------------------------------------------------------------*/
04158 
04159 /*
04160  * @brief  Retrieve input parameters
04161  * @param  pipeline_name        Input image
04162  * @param  recipe_name          Input image
04163  * @param  parlist              Shift to apply on the x-axis
04164  * @return CPL_ERROR_NONE on success.
04165  */
04166 
04167 /*---------------------------------------------------------------------------*/
04168 cpl_error_code
04169 irplib_detmon_pernoise_rm_bg(cpl_image * image, int nsamples, int nffts)
04170 {
04171     cpl_vector             *values = cpl_vector_new(nsamples * nffts);
04172 
04173     int                     rejected;
04174     int i, j;
04175     cpl_vector *xy_pos = cpl_vector_new(nsamples * nffts * 2);
04176     double mse = 0;
04177     cpl_polynomial * poly_2d = 0;
04178     cpl_image * poly_ima = 0;
04179     int degree = 3;
04180     cpl_error_code error = CPL_ERROR_NONE;
04181     cpl_matrix * samppos = 0;
04182     cpl_vector * fitresidual = 0;
04183 
04184     for(i = 1; i <= nffts; i++) {
04185         for(j = 1; j <= nsamples; j++) {
04186             cpl_vector_set(xy_pos, (i - 1) * nsamples + (j - 1), j);
04187             cpl_vector_set(xy_pos, (i - 1) * nsamples + (j - 1) + nsamples * nffts, i);
04188             cpl_vector_set(values, (i - 1) * nsamples + (j - 1),
04189                            cpl_image_get(image, j, i, &rejected));
04190             error = cpl_error_get_code();
04191             if (error != CPL_ERROR_NONE)
04192             {
04193                 break;
04194             }
04195         }
04196         if (error != CPL_ERROR_NONE)
04197         {
04198             break;
04199         }
04200     }
04201     if (error != CPL_ERROR_NONE)
04202     {
04203         goto cleanup;
04204     }
04205 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04206     poly_2d = cpl_polynomial_new(2);
04207     samppos =
04208     cpl_matrix_wrap(2, nsamples * nffts, cpl_vector_get_data(xy_pos));
04209     fitresidual = cpl_vector_new(nsamples * nffts);
04210     cpl_polynomial_fit(poly_2d, samppos, NULL, values, NULL,
04211                CPL_FALSE, NULL, &degree);
04212 
04213     cpl_vector_fill_polynomial_fit_residual(fitresidual, values, NULL, poly_2d,
04214                         samppos, NULL);
04215     cpl_matrix_unwrap(samppos);
04216     mse = cpl_vector_product(fitresidual, fitresidual)
04217     / cpl_vector_get_size(fitresidual);
04218     cpl_vector_delete(fitresidual);
04219 
04220 #else
04221     poly_2d = cpl_polynomial_fit_2d_create(xy_pos, values, 3, &mse);
04222 #endif
04223 
04224     poly_ima = cpl_image_new(nsamples, nffts, CPL_TYPE_FLOAT);
04225 
04226     cpl_image_fill_polynomial(poly_ima, poly_2d, 1, 1, 1, 1);
04227 
04228     cpl_image_subtract(image, poly_ima);
04229 
04230 cleanup:
04231     cpl_polynomial_delete(poly_2d);
04232     cpl_image_delete(poly_ima);
04233     cpl_vector_delete(xy_pos);
04234     cpl_vector_delete(values);
04235 
04236     return cpl_error_get_code();
04237 }
04238 
04239 /*---------------------------------------------------------------------------*/
04240 
04241 /*
04242  * @brief  Retrieve input parameters
04243  * @param  pipeline_name        Input image
04244  * @param  recipe_name          Input image
04245  * @param  parlist              Shift to apply on the x-axis
04246  * @return CPL_ERROR_NONE on success.
04247  */
04248 
04249 /*---------------------------------------------------------------------------*/
04250 cpl_error_code
04251 irplib_detmon_dark(cpl_frameset      * frameset,
04252                    const cpl_parameterlist * parlist,
04253                    const char        * tag,
04254                    const char        * recipe_name,
04255                    const char        * pipeline_name,
04256                    const char        * procatg_master,
04257                    const char        * procatg_dsnu,
04258                    const char        * procatg_tbl,
04259                    const char        * package,
04260                    int              (*compare)(const cpl_frame *,
04261                                                const cpl_frame *))
04262 {
04263     int                     nsets;
04264     int                    *selection = NULL;
04265     int                     i;
04266     cpl_error_code          error;
04267 
04268     if(irplib_detmon_dark_dfs_set_groups(frameset, tag)) {
04269         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
04270     }
04271 
04272     /*
04273      * This function reads all inputs parameters from parlist
04274      * and stores them in a global variable detmon_ronbias_config.
04275      * Similar to irplib_detmon_lg_retrieve_parlist(). See irplib_detmon.c
04276      */
04277     error = irplib_detmon_retrieve_dark_params(pipeline_name,
04278                                                recipe_name, parlist);
04279     cpl_ensure_code(!error, error);
04280 
04281     /* Labelise all input frames */
04282     if(compare == NULL)
04283         nsets = 1;
04284     else {
04285         cpl_msg_info(cpl_func, "Identify the different settings");
04286         selection = cpl_frameset_labelise(frameset, compare, &nsets);
04287         if(selection == NULL)
04288             cpl_msg_error(cpl_func, "Cannot labelise input frames");
04289     }
04290 
04291     detmon_dark_config.nb_extensions = 1;
04292     if(detmon_dark_config.exts < 0) {
04293         const cpl_frame        *cur_frame =
04294             cpl_frameset_get_first_const(frameset);
04295         /* Get the nb of extensions */
04296         detmon_dark_config.nb_extensions =
04297             cpl_frame_get_nextensions(cur_frame);
04298     }
04299 
04300     /* Extract settings and reduce each of them */
04301     for(i = 0; i < nsets; i++) {
04302         int                    *select_dits = NULL;
04303         cpl_frameset           *cur_fset =
04304             nsets == 1 ? cpl_frameset_duplicate(frameset) :
04305             cpl_frameset_extract(frameset, selection, i);
04306 
04307         int                     ndits = 0;
04308         int                     j, k;
04309         cpl_table ** dsnu_table = NULL;
04310         cpl_imagelist ** dsnu = NULL;
04311 
04312         cpl_propertylist ** qclist =
04313             (cpl_propertylist **)
04314             cpl_malloc(detmon_dark_config.nb_extensions *
04315                        sizeof(cpl_propertylist *));
04316 
04317 
04318         cpl_imagelist ** masters =
04319             (cpl_imagelist **)
04320             cpl_malloc(detmon_dark_config.nb_extensions *
04321                        sizeof(cpl_imagelist *));
04322 
04323         /* Initialise memory for products */
04324         if(detmon_dark_config.opt_nir == OPT) {
04325             dsnu_table =
04326                 (cpl_table **) cpl_malloc(detmon_dark_config.nb_extensions *
04327                                           sizeof(cpl_table *));
04328             dsnu =
04329                 (cpl_imagelist **)
04330                 cpl_malloc(detmon_dark_config.nb_extensions *
04331                                           sizeof(cpl_imagelist *));
04332         }
04333 
04334         select_dits = cpl_frameset_labelise(cur_fset,
04335                                             irplib_detmon_compare_dits,
04336                                             &ndits);
04337 
04338         if(detmon_dark_config.exts >= 0) {
04339             *masters = cpl_imagelist_new();
04340             if(detmon_dark_config.opt_nir == OPT) {
04341                 *dsnu = cpl_imagelist_new();
04342                 *dsnu_table = cpl_table_new(ndits);
04343             }
04344             *qclist = cpl_propertylist_new();
04345             cpl_table_new_column(*dsnu_table, "DIT", CPL_TYPE_DOUBLE);
04346             cpl_table_new_column(*dsnu_table, "STDEV", CPL_TYPE_DOUBLE);
04347         } else {
04348             for ( j = 0; j < detmon_dark_config.nb_extensions; j ++) {
04349                 masters[j] = cpl_imagelist_new();
04350                 if(detmon_dark_config.opt_nir == OPT) {
04351                     dsnu[j] = cpl_imagelist_new();
04352                     dsnu_table[j] = cpl_table_new(ndits);
04353                 }
04354                 qclist[j] = cpl_propertylist_new();
04355                 cpl_table_new_column(dsnu_table[j], "DIT", CPL_TYPE_DOUBLE);
04356                 cpl_table_new_column(dsnu_table[j], "STDEV", CPL_TYPE_DOUBLE);
04357             }
04358         }
04359 
04360         for(j = 0; j < ndits; j++) {
04361             cpl_frameset  * cur_fdit = cpl_frameset_extract(cur_fset,
04362                                                             select_dits, j);
04363             cpl_imagelist ** raws =
04364                 (cpl_imagelist **)
04365                 cpl_malloc(detmon_dark_config.nb_extensions *
04366                            sizeof(cpl_imagelist *));
04367 
04368             if(detmon_dark_config.exts >= 0) {
04369                 cpl_image * collapsed;
04370                 *raws =
04371                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
04372                                                 detmon_dark_config.exts);
04373                 collapsed = cpl_imagelist_collapse_create(*raws);
04374                 cpl_imagelist_set(*masters, collapsed, j);
04375                 if(detmon_dark_config.opt_nir == OPT) {
04376                     irplib_detmon_dark_dsnu(cur_fdit, *dsnu, *dsnu_table,
04377                                             collapsed, j);
04378                 }
04379                 irplib_detmon_dark_qc(*qclist, collapsed);
04380             } else {
04381                 cpl_imagelist          *raws_all_exts =
04382                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
04383                                                 -1);
04384                 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
04385                     int nframes = cpl_frameset_get_size(cur_fdit);
04386                     int h;
04387                     cpl_image * collapsed;
04388                     for(h = 0; h < nframes; h++) {
04389                         cpl_image              *image =
04390                             cpl_imagelist_unset(raws_all_exts,
04391                                                 (detmon_dark_config.
04392                                                  nb_extensions - 1 - k) * h);
04393                         cpl_imagelist_set(raws[k], image, h);
04394                     }
04395                     collapsed = cpl_imagelist_collapse_create(raws[k]);
04396                     cpl_imagelist_set(masters[k],collapsed, j);
04397                     if(detmon_dark_config.opt_nir == OPT) {
04398                         irplib_detmon_dark_dsnu(cur_fdit, dsnu[k],
04399                                                 dsnu_table[j], collapsed, j);
04400                     }
04401                     irplib_detmon_dark_qc(qclist[k], collapsed);
04402                 }
04403             }
04404 
04405             cpl_frameset_delete(cur_fdit);
04406             for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
04407                 cpl_imagelist_delete(raws[k]);
04408             }
04409             cpl_free(raws);
04410         } /* end of loop (for) around different DIT values */
04411 
04412         cpl_frameset_delete(cur_fset);
04413 
04414         irplib_detmon_dark_save(parlist, frameset, recipe_name, pipeline_name,
04415                                 procatg_master, procatg_tbl, procatg_dsnu,
04416                                 package, masters, dsnu_table, dsnu, qclist,
04417                                 0, 0, frameset);
04418 
04419         if(detmon_dark_config.opt_nir == OPT) {
04420             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04421                 cpl_table_delete(dsnu_table[j]);
04422                 cpl_imagelist_delete(dsnu[j]);
04423             }
04424             cpl_free(dsnu_table);
04425             cpl_free(dsnu);
04426         }
04427 
04428         for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04429             cpl_propertylist_delete(qclist[j]);
04430             cpl_imagelist_delete(masters[j]);
04431         }
04432         cpl_free(qclist);
04433         cpl_free(masters);
04434         cpl_free(select_dits);
04435 
04436     } /* end of loop (for) around different setting */
04437 
04438     cpl_free(selection);
04439 
04440     return cpl_error_get_code();
04441 }
04442 
04443 
04444 /*---------------------------------------------------------------------------*/
04445 
04446 /*
04447  * @brief  Retrieve input parameters
04448  * @param  pipeline_name        Input image
04449  * @param  recipe_name          Input image
04450  * @param  parlist              Shift to apply on the x-axis
04451  * @return CPL_ERROR_NONE on success.
04452  */
04453 
04454 /*---------------------------------------------------------------------------*/
04455 int
04456 irplib_detmon_dark_dfs_set_groups(cpl_frameset * set, const char *tag)
04457 {
04458     cpl_frame              *cur_frame;
04459     const char             *cur_tag;
04460     int                     nframes;
04461     int                     i;
04462 
04463     /* Check entries */
04464     if(set == NULL)
04465         return -1;
04466 
04467     /* Initialize */
04468     nframes = cpl_frameset_get_size(set);
04469 
04470     /* Loop on frames */
04471     for(i = 0; i < nframes; i++) {
04472         cur_frame = cpl_frameset_get_frame(set, i);
04473         cur_tag = cpl_frame_get_tag(cur_frame);
04474 
04475         /* RAW frames */
04476         if(!strcmp(cur_tag, tag))
04477             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
04478         /* CALIB frames */
04479 
04480 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
04481           cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
04482 */
04483     }
04484     return 0;
04485 }
04486 
04487 /*---------------------------------------------------------------------------*/
04488 
04489 /*
04490  * @brief  Retrieve input parameters
04491  * @param  pipeline_name        Input image
04492  * @param  recipe_name          Input image
04493  * @param  parlist              Shift to apply on the x-axis
04494  * @return CPL_ERROR_NONE on success.
04495  */
04496 
04497 /*---------------------------------------------------------------------------*/
04498 static                  cpl_error_code
04499 irplib_detmon_retrieve_dark_params(const char *pipeline_name,
04500                                       const char *recipe_name,
04501                                       const cpl_parameterlist * parlist)
04502 {
04503     char                   *par_name;
04504     cpl_parameter          *par;
04505 
04506     /* --ron.method */
04507     par_name = cpl_sprintf("%s.%s.ron.method", pipeline_name, recipe_name);
04508     assert(par_name != NULL);
04509     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04510     detmon_dark_config.ron_method = cpl_parameter_get_string(par);
04511     cpl_free(par_name);
04512 
04513     /* --dsnu.method */
04514     par_name = cpl_sprintf("%s.%s.dsnu.method", pipeline_name, recipe_name);
04515     assert(par_name != NULL);
04516     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04517     detmon_dark_config.dsnu_method = cpl_parameter_get_string(par);
04518     cpl_free(par_name);
04519 
04520     /* --opt_nir */
04521     par_name = cpl_sprintf("%s.%s.opt_nir", pipeline_name, recipe_name);
04522     assert(par_name != NULL);
04523     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04524     detmon_dark_config.opt_nir = cpl_parameter_get_bool(par);
04525     cpl_free(par_name);
04526 
04527     /* --exts */
04528     detmon_dark_config.exts =
04529         irplib_detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
04530                                    parlist);
04531 
04532     if(cpl_error_get_code()) {
04533         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
04534         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
04535     }
04536 
04537 
04538     return CPL_ERROR_NONE;
04539 }
04540 
04541 
04542 /*---------------------------------------------------------------------------*/
04543 
04544 /*
04545  * @brief  Retrieve input parameters
04546  * @param  pipeline_name        Input image
04547  * @param  recipe_name          Input image
04548  * @param  parlist              Shift to apply on the x-axis
04549  * @return CPL_ERROR_NONE on success.
04550  */
04551 
04552 /*---------------------------------------------------------------------------*/
04553 cpl_error_code
04554 irplib_detmon_fill_dark_params(cpl_parameterlist * parlist,
04555                                const char *recipe_name,
04556                                const char *pipeline_name,
04557                                const char * ron_method,
04558                                const char * dsnu_method,
04559                                const char * opt_nir,
04560                                int exts)
04561 {
04562     irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 4,
04563 
04564                                "ron.method",
04565                                "Method used to compute RON. Currently no "
04566                    "change is possible, RMS computed",
04567                                "CPL_TYPE_STRING", ron_method,
04568 
04569                                "dsnu.method",
04570                                "Method used to compute DSNU map. Currently no "
04571                    "change is possible. Method used STDEV",
04572                                "CPL_TYPE_STRING", dsnu_method,
04573 
04574                                "opt_nir",
04575                                "Boolean, OPT (FALSE) or NIR(TRUE)",
04576                                "CPL_TYPE_BOOL", opt_nir,
04577 
04578                                "exts",
04579                                "Activate the multi-exts option. Default 0"
04580                    "(primary unit), -1 (all exts)",
04581                                "CPL_TYPE_INT", exts);
04582 
04583     return cpl_error_get_code();
04584 }
04585 
04586 /*---------------------------------------------------------------------------*/
04587 
04588 /*
04589  * @brief  Retrieve input parameters
04590  * @param  pipeline_name        Input image
04591  * @param  recipe_name          Input image
04592  * @param  parlist              Shift to apply on the x-axis
04593  * @return CPL_ERROR_NONE on success.
04594  */
04595 
04596 /*---------------------------------------------------------------------------*/
04597 int
04598 irplib_detmon_fill_dark_params_default(cpl_parameterlist * parlist,
04599                                        const char *recipe_name,
04600                                        const char *pipeline_name)
04601 {
04602     irplib_detmon_fill_dark_params(parlist, recipe_name, pipeline_name,
04603                                    "SIMPLE", /* --ron.method  */
04604                                    "STDEV",  /* --dsnu.method */
04605                                    "CPL_FALSE",  /* OPT*/
04606                                    0);       /* --exts        */
04607     return cpl_error_get_code();
04608 }
04609 
04610 /*---------------------------------------------------------------------------*/
04611 
04612 /*
04613  * @brief  Retrieve input parameters
04614  * @param  pipeline_name        Input image
04615  * @param  recipe_name          Input image
04616  * @param  parlist              Shift to apply on the x-axis
04617  * @return CPL_ERROR_NONE on success.
04618  */
04619 
04620 /*---------------------------------------------------------------------------*/
04621 cpl_error_code
04622 irplib_detmon_dark_dsnu(cpl_frameset * cur_fdit,
04623                         cpl_imagelist * dsnu,
04624                         cpl_table * dsnu_table,
04625                         cpl_image * collapsed,
04626                         int pos)
04627 {
04628     cpl_frame * first = cpl_frameset_get_first(cur_fdit);
04629     cpl_propertylist * plist =
04630         cpl_propertylist_load(cpl_frame_get_filename(first), 0);
04631     double dit = irplib_pfits_get_exptime(plist);
04632     double mean = cpl_image_get_mean(collapsed);
04633 
04634     cpl_image * dsnu_map =
04635         cpl_image_subtract_scalar_create(collapsed, mean);
04636     double stdev;
04637     cpl_image_divide_scalar(dsnu_map, mean);
04638     stdev = cpl_image_get_stdev(dsnu_map);
04639 
04640     cpl_imagelist_set(dsnu, dsnu_map, pos);
04641 
04642     cpl_table_set(dsnu_table, "DIT", pos, dit);
04643     cpl_table_set(dsnu_table, "STDEV", pos, stdev);
04644 
04645     cpl_propertylist_delete(plist);
04646 
04647     return cpl_error_get_code();
04648 
04649 }
04650 
04651 /*---------------------------------------------------------------------------*/
04652 
04653 /*
04654  * @brief  Retrieve input parameters
04655  * @param  pipeline_name        Input image
04656  * @param  recipe_name          Input image
04657  * @param  parlist              Shift to apply on the x-axis
04658  * @return CPL_ERROR_NONE on success.
04659  */
04660 
04661 /*---------------------------------------------------------------------------*/
04662 static                  cpl_error_code
04663 irplib_detmon_dark_save(const cpl_parameterlist * parlist,
04664                         cpl_frameset * frameset,
04665                         const char *recipe_name,
04666                         const char *pipeline_name,
04667                         const char *procatg_master,
04668                         const char *procatg_tbl,
04669                         const char *procatg_dsnu,
04670                         const char *package,
04671                         cpl_imagelist ** masters,
04672                         cpl_table ** dsnu_table,
04673                         cpl_imagelist ** dsnu,
04674                         cpl_propertylist ** qclist,
04675                         const int flag_sets,
04676                         const int which_set,
04677                         const cpl_frameset * usedframes)
04678 {
04679 
04680     cpl_frame              *ref_frame;
04681     cpl_propertylist       *plist;
04682     char                   *name_o = NULL; /* Avoid (false) uninit warning */
04683     int                     i, j;
04684     cpl_propertylist       *paflist;
04685     cpl_error_code          error;
04686     int nb_images;
04687 
04688     /***************************/
04689     /*  Write the MASTER FITS  */
04690     /***************************/
04691 
04692     nb_images = cpl_imagelist_get_size(masters[0]);
04693     cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
04694 
04695 
04696     for(i = 0; i < nb_images; i++) {
04697         /* Set the file name for each image */
04698         if(!flag_sets) {
04699             name_o =
04700                 cpl_sprintf("%s_master_dit_%d.fits", recipe_name, i+1);
04701             assert(name_o != NULL);
04702         } else {
04703             name_o =
04704                 cpl_sprintf("%s_master_dit_%d_set%02d.fits",
04705                                recipe_name, i, which_set);
04706             assert(name_o != NULL);
04707         }
04708 
04709 
04710         /* Save the image */
04711         if(detmon_dark_config.exts >= 0) {
04712 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04713             cpl_propertylist * pro_master = cpl_propertylist_new();
04714 
04715             cpl_propertylist_append_string(pro_master,
04716                                            CPL_DFS_PRO_CATG, procatg_master);
04717 
04718             cpl_propertylist_append(pro_master, qclist[0]);
04719 
04720             if(cpl_dfs_save_image
04721                (frameset, NULL, parlist, usedframes, NULL,
04722                 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
04723                 recipe_name, pro_master, NULL, package,
04724                 name_o)) {
04725                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04726                               name_o);
04727                 cpl_free(name_o);
04728                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04729 
04730             }
04731 
04732         cpl_propertylist_delete(pro_master);
04733 #else
04734             if(cpl_dfs_save_image
04735                (frameset, parlist, usedframes,
04736                 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
04737                 recipe_name, procatg_master, qclist[0], NULL, package,
04738                 name_o)) {
04739                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04740                               name_o);
04741                 cpl_free(name_o);
04742                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04743 
04744             }
04745 #endif
04746         } else {
04747 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04748             cpl_propertylist * pro_master = cpl_propertylist_new();
04749 
04750             cpl_propertylist_append_string(pro_master,
04751                                            CPL_DFS_PRO_CATG, procatg_master);
04752 
04753             cpl_propertylist_append(pro_master, qclist[0]);
04754 
04755             if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
04756                               NULL, CPL_BPP_IEEE_FLOAT, recipe_name,
04757                                   pro_master, NULL,
04758                                   package, name_o)) {
04759                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04760                               name_o);
04761                 cpl_free(name_o);
04762                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04763             }
04764 
04765         cpl_propertylist_delete(pro_master);
04766 #else
04767             if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
04768                                   CPL_BPP_IEEE_FLOAT, recipe_name,
04769                                   procatg_master, qclist[0], NULL,
04770                                   package, name_o)) {
04771                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04772                               name_o);
04773                 cpl_free(name_o);
04774                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04775             }
04776 #endif
04777             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04778                 error =
04779                     cpl_image_save(cpl_imagelist_get(masters[j], i),
04780                                    name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04781                                    CPL_IO_EXTEND);
04782                 cpl_ensure_code(!error, error);
04783             }
04784         }
04785     cpl_free(name_o);
04786     }
04787 
04788     if (detmon_dark_config.opt_nir == OPT) {
04789 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04790         cpl_propertylist * pro_tbl = cpl_propertylist_new();
04791 
04792         cpl_propertylist_append_string(pro_tbl,
04793                                      CPL_DFS_PRO_CATG, procatg_tbl);
04794 
04795         cpl_propertylist_append(pro_tbl, qclist[0]);
04796 #endif
04797         /*******************************/
04798         /*  Write the LINEARITY TABLE  */
04799         /*******************************/
04800 
04801         /* Set the file name for the table */
04802         if(!flag_sets) {
04803             name_o = cpl_sprintf("%s_dsnu_table.fits", recipe_name);
04804             assert(name_o != NULL);
04805         } else {
04806             name_o =
04807                 cpl_sprintf("%s_dsnu_table_set%02d.fits", recipe_name,
04808                                which_set);
04809             assert(name_o != NULL);
04810         }
04811 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04812         /* Save the table */
04813         if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
04814                               dsnu_table[0], NULL, recipe_name, pro_tbl, NULL,
04815                               package, name_o)) {
04816             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04817             cpl_free(name_o);
04818             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04819         }
04820 #else
04821         /* Save the table */
04822         if(cpl_dfs_save_table(frameset, parlist, usedframes, dsnu_table[0],
04823                               NULL, recipe_name, procatg_tbl, qclist[0], NULL,
04824                               package, name_o)) {
04825             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04826             cpl_free(name_o);
04827             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04828         }
04829 #endif
04830 
04831 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04832         cpl_propertylist_delete(pro_tbl);
04833 #endif
04834 
04835         if(detmon_dark_config.exts < 0) {
04836 
04837             for(i = 1; i < detmon_dark_config.nb_extensions; i++) {
04838                 error =
04839                     cpl_table_save(dsnu_table[i], NULL, qclist[i], name_o,
04840                                    CPL_IO_EXTEND);
04841                 cpl_ensure_code(!error, error);
04842             }
04843         }
04844 
04845         /* Free */
04846         cpl_free(name_o);
04847 
04848         /***************************/
04849         /*  Write the DSNU_MAP FITS  */
04850         /***************************/
04851 
04852         for(i = 0; i < nb_images; i++) {
04853             /* Set the file name for each image */
04854             if(!flag_sets) {
04855                 name_o =
04856                     cpl_sprintf("%s_dsnu_map_dit_%d.fits", recipe_name, i+1);
04857                 assert(name_o != NULL);
04858             } else {
04859                 name_o =
04860                     cpl_sprintf("%s_dsnu_map_dit_%d_set%02d.fits",
04861                                    recipe_name, i, which_set);
04862                 assert(name_o != NULL);
04863             }
04864 
04865 
04866             /* Save the image */
04867             if(detmon_dark_config.exts >= 0) {
04868 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04869             cpl_propertylist * pro_dsnu = cpl_propertylist_new();
04870 
04871         cpl_propertylist_append_string(pro_dsnu,
04872                                            CPL_DFS_PRO_CATG, procatg_dsnu);
04873 
04874             cpl_propertylist_append(pro_dsnu, qclist[0]);
04875 
04876                 if(cpl_dfs_save_image
04877                    (frameset, NULL, parlist, usedframes, NULL,
04878                     cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
04879                     recipe_name, pro_dsnu, NULL, package,
04880                     name_o)) {
04881                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04882                                   name_o);
04883                     cpl_free(name_o);
04884                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04885 
04886                 }
04887 
04888             cpl_propertylist_delete(pro_dsnu);
04889 #else
04890                 if(cpl_dfs_save_image
04891                    (frameset, parlist, usedframes,
04892                     cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
04893                     recipe_name, procatg_dsnu, qclist[0], NULL, package,
04894                     name_o)) {
04895                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04896                                   name_o);
04897                     cpl_free(name_o);
04898                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04899 
04900                 }
04901 #endif
04902             } else {
04903 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 8, 0)
04904             cpl_propertylist * pro_dsnu = cpl_propertylist_new();
04905 
04906         cpl_propertylist_append_string(pro_dsnu,
04907                                            CPL_DFS_PRO_CATG, procatg_dsnu);
04908 
04909             cpl_propertylist_append(pro_dsnu, qclist[0]);
04910 
04911             if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
04912                                   NULL, NULL,
04913                                       CPL_BPP_IEEE_FLOAT, recipe_name,
04914                                       pro_dsnu, NULL,
04915                                       package, name_o)) {
04916                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04917                                   name_o);
04918                     cpl_free(name_o);
04919                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04920                 }
04921 
04922             cpl_propertylist_delete(pro_dsnu);
04923 #else
04924                 if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
04925                                       CPL_BPP_IEEE_FLOAT, recipe_name,
04926                                       procatg_dsnu, qclist[0], NULL,
04927                                       package, name_o)) {
04928                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04929                                   name_o);
04930                     cpl_free(name_o);
04931                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04932                 }
04933 #endif
04934                 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04935                     error =
04936                         cpl_image_save(cpl_imagelist_get(dsnu[j], i),
04937                                        name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04938                                        CPL_IO_EXTEND);
04939                     cpl_ensure_code(!error, error);
04940                 }
04941             }
04942         cpl_free(name_o);
04943         }
04944 
04945 
04946 
04947     } /* End of if(OPT) */
04948 
04949     /*******************************/
04950     /*  Write the PAF file(s)      */
04951     /*******************************/
04952 
04953     /* Get FITS header from reference file */
04954     ref_frame = cpl_frameset_get_first(frameset);
04955     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04956                                       0)) == NULL) {
04957         cpl_msg_error(cpl_func, "getting header from reference frame");
04958         cpl_ensure_code(0, cpl_error_get_code());
04959     }
04960 
04961     /* Get the keywords for the paf file */
04962     paflist = cpl_propertylist_new();
04963     cpl_propertylist_copy_property_regexp(paflist, plist,
04964                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
04965                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
04966                                           "ESO DET NCORRS|"
04967                                           "ESO DET MODE NAME)$", 0);
04968 
04969     for(i = 0; i < detmon_dark_config.nb_extensions; i++) {
04970         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
04971         error = cpl_propertylist_append(c_paflist, qclist[i]);
04972         cpl_ensure_code(!error, error);
04973 
04974         /* Set the file name for the bpm */
04975         if(detmon_dark_config.exts >= 0) {
04976             if(!flag_sets) {
04977                 name_o = cpl_sprintf("%s.paf", recipe_name);
04978                 assert(name_o != NULL);
04979             } else {
04980                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
04981                 assert(name_o != NULL);
04982             }
04983         } else {
04984             if(!flag_sets) {
04985                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
04986                 assert(name_o != NULL);
04987             } else {
04988                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
04989                 assert(name_o != NULL);
04990             }
04991         }
04992         /* Save the PAF */
04993         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
04994             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04995             cpl_free(name_o);
04996             cpl_propertylist_delete(paflist);
04997             cpl_propertylist_delete(plist);
04998             cpl_free(name_o);
04999             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
05000         }
05001         cpl_propertylist_delete(c_paflist);
05002         cpl_free(name_o);
05003     }
05004 
05005     cpl_propertylist_delete(plist);
05006     cpl_propertylist_delete(paflist);
05007 
05008     return cpl_error_get_code();
05009 }
05010 
05011 cpl_error_code
05012 irplib_detmon_dark_qc(cpl_propertylist * qclist,
05013                       cpl_image * collapsed)
05014 {
05015     double mean = cpl_image_get_mean(collapsed);
05016     double stdev = cpl_image_get_stdev(collapsed);
05017 
05018     cpl_error_code error;
05019 
05020     error = cpl_propertylist_append_double(qclist,DETMON_QC_DARK, mean);
05021     error = cpl_propertylist_set_comment(qclist,DETMON_QC_DARK,
05022                      DETMON_QC_DARK_C);
05023     cpl_ensure_code(!error, error);
05024 
05025     error = cpl_propertylist_append_double(qclist,DETMON_QC_DARK_STDEV, stdev);
05026     error = cpl_propertylist_set_comment(qclist,DETMON_QC_DARK_STDEV,
05027                      DETMON_QC_DARK_STDEV_C);
05028     cpl_ensure_code(!error, error);
05029 
05030     return cpl_error_get_code();
05031 }
05032 
05033 
05034 /*---------------------------------------------------------------------------*/
05051 /*---------------------------------------------------------------------------*/
05052 cpl_image *
05053 irplib_imagelist_collapse_stdev_create(const cpl_imagelist * imlist)
05054 {
05055     cpl_image          *    mean;
05056     cpl_image          *    delta;
05057     cpl_image          *    sq_delta;
05058     cpl_image          *    stdev;
05059 
05060     int                     i;
05061 
05062     /* Check inputs */
05063     cpl_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
05064     cpl_ensure(cpl_imagelist_is_uniform(imlist) == 0, CPL_ERROR_ILLEGAL_INPUT,
05065                NULL);
05066 
05067     /* Create mean image with its first iterative value = first image */
05068     mean = cpl_image_duplicate(cpl_imagelist_get_const(imlist, 0));
05069     cpl_image_fill_rejected(mean, 0.0);
05070     cpl_image_accept_all(mean);
05071 
05072     stdev = cpl_image_new(cpl_image_get_size_x(mean),
05073               cpl_image_get_size_y(mean),
05074               CPL_TYPE_FLOAT);
05075 
05076     for (i = 1; i < cpl_imagelist_get_size(imlist); i++) {
05077         delta = cpl_image_subtract_create(cpl_imagelist_get_const(imlist, i),
05078                                       mean);
05079         cpl_image_fill_rejected(delta, 0.0);
05080         cpl_image_accept_all(delta);
05081 
05082     sq_delta = cpl_image_multiply_create(delta, delta);
05083 
05084     cpl_image_multiply_scalar(sq_delta, ((double) i / (double)(i+1)));
05085     cpl_image_add(stdev, sq_delta);
05086 
05087     cpl_image_divide_scalar(delta, i + 1);
05088     cpl_image_add(mean, delta);
05089 
05090         cpl_image_delete(delta);
05091         cpl_image_delete(sq_delta);
05092     }
05093 
05094     cpl_image_divide_scalar(stdev, cpl_imagelist_get_size(imlist) - 1);
05095     cpl_image_power(stdev, 0.5);
05096 
05097     cpl_image_delete(mean);
05098 
05099     return stdev;
05100 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.8.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Mar 4 10:50:28 2011 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004