GIRAFFE Pipeline Reference Manual

irplib_detmon.c

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.7.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Aug 6 13:56:42 2010 by doxygen 1.5.1 written by Dimitri van Heesch, © 1997-2004