detmon.c

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

Generated on 7 Mar 2012 for DETMON Pipeline Reference Manual by  doxygen 1.6.1