GIRAFFE Pipeline Reference Manual

irplib_detmon.c

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.9.0.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Jan 26 14:20:29 2012 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004