detmon.c

00001 /* $Id: detmon.c,v 1.10 2013/01/28 14:33:46 jtaylor 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: jtaylor $
00023  * $Date: 2013/01/28 14:33:46 $
00024  * $Revision: 1.10 $
00025  * $Name: HEAD $
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     cpl_size                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 
01565     cpl_image * dupi;
01566     unsigned long           x1a = 1;
01567     unsigned long           x2a = 1;
01568 
01569     double                  x1 = 0;
01570     double                  x2 = 0;
01571 
01572     double                  maxwhere_interp;
01573     double                  max_interp;
01574     double a, b, c;
01575     cpl_matrix * coeffs =cpl_matrix_new(3, 3);
01576     cpl_matrix * rhs    =cpl_matrix_new(3, 1);
01577     int p, q;
01578     cpl_matrix * result = NULL;
01579     cpl_error_code error;
01580 
01581     dupi = cpl_image_duplicate(c_raw);
01582 
01583     /* FIXME: Still to decide if it is necessary to remove bad pixels
01584        in advance or not*/
01585 
01586     hist = irplib_hist_new();
01587     error = irplib_hist_fill(hist, dupi);
01588     cpl_ensure_code(!error, error);
01589 
01590     cpl_image_delete(dupi);
01591 
01592     irplib_hist_get_max(hist, &maxwhere);
01593 
01594     for( p = 0; p< 3; p++){
01595         unsigned long bi = irplib_hist_get_value(hist, maxwhere-1+p);
01596         cpl_matrix_set(rhs, p, 0, bi);
01597         for( q= 0; q< 3; q++) {
01598             cpl_matrix_set(coeffs, p,q,pow((maxwhere-1+p),q));
01599         }
01600     }
01601 
01602     result = cpl_matrix_solve(coeffs, rhs);
01603 
01604     a = cpl_matrix_get(result, 2, 0);
01605     b = cpl_matrix_get(result, 1, 0);
01606     c = cpl_matrix_get(result, 0, 0);
01607 
01608     maxwhere_interp = -0.5 * b / (2 * a);
01609     max_interp = -1 * b * b / (4 * a) + c;
01610 
01611     cpl_matrix_delete(coeffs);
01612     cpl_matrix_delete(rhs);
01613     cpl_matrix_delete(result);
01614 
01615     /* Look for the points of half-maximum */
01616     for(uj = 0; uj < maxwhere; uj++) {
01617         if(irplib_hist_get_value(hist, uj)     <= max_interp / 2 &&
01618            irplib_hist_get_value(hist, uj + 1) >  max_interp / 2) {
01619             x1a = uj;
01620         }
01621     }
01622     for(uj = maxwhere; uj < irplib_hist_get_nbins(hist)-1; uj++) {
01623         if(irplib_hist_get_value(hist, uj)     >= max_interp / 2 &&
01624            irplib_hist_get_value(hist, uj + 1) <  max_interp / 2) {
01625             x2a = uj;
01626         }
01627     }
01628 
01629     x1 = (max_interp / 2 - irplib_hist_get_value(hist, x1a)) /
01630         (irplib_hist_get_value(hist, x1a + 1) -
01631          irplib_hist_get_value(hist, x1a)) + x1a;
01632     x2 = (max_interp / 2 - irplib_hist_get_value(hist, x2a)) /
01633         (irplib_hist_get_value(hist, x2a + 1) -
01634          irplib_hist_get_value(hist, x2a)) + x2a;
01635 
01636     *fwhm = (x2 - x1) * irplib_hist_get_bin_size(hist);
01637 
01638     *max = max_interp;
01639 
01640     *bias =  maxwhere_interp * irplib_hist_get_bin_size(hist) +
01641         irplib_hist_get_start(hist);
01642 
01643     irplib_hist_delete(hist);
01644 
01645     return cpl_error_get_code();
01646 }
01647 /*---------------------------------------------------------------------------*/
01648 
01649 /*
01650  * @brief  Retrieve input parameters
01651  * @param  pipeline_name        Input image
01652  * @param  recipe_name          Input image
01653  * @param  parlist              Shift to apply on the x-axis
01654  * @return CPL_ERROR_NONE on success.
01655  */
01656 
01657 /*---------------------------------------------------------------------------*/
01658     static cpl_error_code
01659 detmon_ronbias_preoverscan(const cpl_imagelist * rawbiases,
01660                            cpl_propertylist * qclist,
01661                            cpl_image ** synthetic)
01662 {
01663     int                     i;
01664     int                     nx, ny;
01665     int                     nraws;
01666 
01667     cpl_vector             *meanspre;
01668     cpl_vector             *medspre;
01669     cpl_vector             *rmsspre;
01670     cpl_vector             *meansover;
01671     cpl_vector             *medsover;
01672     cpl_vector             *rmssover;
01673 
01674     cpl_error_code          error;
01675 
01676     nraws = cpl_imagelist_get_size(rawbiases);
01677     cpl_ensure_code(nraws != -1, CPL_ERROR_ILLEGAL_INPUT);
01678 
01679     meanspre = cpl_vector_new(nraws);
01680     medspre = cpl_vector_new(nraws);
01681     rmsspre = cpl_vector_new(nraws);
01682     meansover = cpl_vector_new(nraws);
01683     medsover = cpl_vector_new(nraws);
01684     rmssover = cpl_vector_new(nraws);
01685 
01686     nx = cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
01687     ny = cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
01688     cpl_ensure_code(nx != -1 && ny != -1, CPL_ERROR_ILLEGAL_INPUT);
01689 
01690     if(nx < detmon_ronbias_config.prescan_urx ||
01691        nx < detmon_ronbias_config.overscan_urx ||
01692        ny < detmon_ronbias_config.prescan_ury ||
01693        ny < detmon_ronbias_config.overscan_ury) {
01694         cpl_msg_warning(cpl_func, "PREOVERSCAN method not applied. Given "
01695                         "limits of prescan and overscan area "
01696                         "exceed image size. Please check and rerun.");
01697         return CPL_ERROR_NONE;
01698     }
01699 
01700     for(i = 0; i < nraws; i++) {
01701         double                  mean = 0;
01702         double                  stdev = 0;
01703 
01704         cpl_image              *prescan = NULL;
01705         cpl_image              *overscan = NULL;
01706 
01707         const cpl_image        *c_raw = cpl_imagelist_get_const(rawbiases, i);
01708 
01709         cpl_ensure_code(c_raw != NULL, CPL_ERROR_ILLEGAL_INPUT);
01710 
01711         prescan =
01712             cpl_image_extract(c_raw,
01713                               detmon_ronbias_config.prescan_llx,
01714                               detmon_ronbias_config.prescan_lly,
01715                               detmon_ronbias_config.prescan_urx,
01716                               detmon_ronbias_config.prescan_ury);
01717         cpl_ensure_code(prescan != NULL, CPL_ERROR_ILLEGAL_INPUT);
01718         overscan =
01719             cpl_image_extract(c_raw,
01720                               detmon_ronbias_config.overscan_llx,
01721                               detmon_ronbias_config.overscan_lly,
01722                               detmon_ronbias_config.overscan_urx,
01723                               detmon_ronbias_config.overscan_ury);
01724         cpl_ensure_code(overscan != NULL, CPL_ERROR_ILLEGAL_INPUT);
01725 
01726         if(i == 0) {
01727             *synthetic = detmon_build_synthetic(prescan, overscan);
01728             cpl_msg_info(cpl_func, "Creating SYNTHETIC frame");
01729             if(*synthetic == NULL) {
01730                 cpl_msg_error(cpl_func, "Error creating SYNTHETIC frame");
01731                 return CPL_ERROR_UNSPECIFIED;
01732             }
01733         }
01734 
01735         error = irplib_ksigma_clip(c_raw,
01736                                    detmon_ronbias_config.
01737                                    prescan_llx,
01738                                    detmon_ronbias_config.
01739                                    prescan_lly,
01740                                    detmon_ronbias_config.
01741                                    prescan_urx,
01742                                    detmon_ronbias_config.
01743                                    prescan_ury,
01744                                    (double) detmon_ronbias_config.
01745                                    stacking_ks_low,
01746                                    detmon_ronbias_config.
01747                                    stacking_ks_iter, 1e-5,
01748                                    &mean, &stdev);
01749         cpl_ensure_code(!error, error);
01750 
01751         cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
01752 
01753         error = cpl_vector_set(medspre, i, cpl_image_get_median(prescan));
01754         cpl_ensure_code(!error, error);
01755 
01756         error = cpl_vector_set(meanspre, i, mean);
01757         cpl_ensure_code(!error, error);
01758         error = cpl_vector_set(rmsspre, i, stdev);
01759         cpl_ensure_code(!error, error);
01760         error = irplib_ksigma_clip(c_raw,
01761                                    detmon_ronbias_config.
01762                                    overscan_llx,
01763                                    detmon_ronbias_config.
01764                                    overscan_lly,
01765                                    detmon_ronbias_config.
01766                                    overscan_urx,
01767                                    detmon_ronbias_config.
01768                                    overscan_ury,
01769                                    (double) detmon_ronbias_config.
01770                                    stacking_ks_low,
01771                                    detmon_ronbias_config.
01772                                    stacking_ks_iter, 1e-5,
01773                                    &mean, &stdev);
01774         cpl_ensure_code(!error, error);
01775 
01776         cpl_ensure_code(mean != 0 && stdev != 0, CPL_ERROR_UNSPECIFIED);
01777 
01778         error = cpl_vector_set(medsover, i, cpl_image_get_median(overscan));
01779         cpl_ensure_code(!error, error);
01780 
01781         error = cpl_vector_set(meansover, i, mean);
01782         cpl_ensure_code(!error, error);
01783         error = cpl_vector_set(rmssover, i, stdev);
01784         cpl_ensure_code(!error, error);
01785 
01786         cpl_image_delete(prescan);
01787         cpl_image_delete(overscan);
01788     }
01789 
01790     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_MEAN,
01791                                            cpl_vector_get_mean(meanspre));
01792 
01793     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_MEAN,
01794                                          DETMON_QC_BIAS_PRESCAN_MEAN_C);
01795 
01796     cpl_ensure_code(!error, error);
01797     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_MED,
01798                                            cpl_vector_get_mean(medspre));
01799     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_MED,
01800                                          DETMON_QC_BIAS_PRESCAN_MED_C);
01801 
01802     cpl_ensure_code(!error, error);
01803     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_PRESCAN_RON,
01804                                            cpl_vector_get_mean(rmsspre));
01805 
01806     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_PRESCAN_RON,
01807                                          DETMON_QC_BIAS_PRESCAN_RON_C);
01808     cpl_ensure_code(!error, error);
01809 
01810     error =
01811         cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_MEAN,
01812                                        cpl_vector_get_mean(meansover));
01813     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_MEAN,
01814                                          DETMON_QC_BIAS_OVERSCAN_MEAN_C);
01815     cpl_ensure_code(!error, error);
01816     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_MED,
01817                                            cpl_vector_get_mean(medsover));
01818     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_MED,
01819                                          DETMON_QC_BIAS_OVERSCAN_MED_C);
01820     cpl_ensure_code(!error, error);
01821     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_OVERSCAN_RON,
01822                                            cpl_vector_get_mean(rmssover));
01823     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_OVERSCAN_RON,
01824                                          DETMON_QC_BIAS_OVERSCAN_RON_C);
01825     cpl_ensure_code(!error, error);
01826 
01827     /* The following seems not to be necessary.
01828        Pending of revision to be removed */
01829     /*
01830        error =
01831        cpl_propertylist_append_double(qclist,
01832        "ESO QC BIAS PRESCAN MEAN STDEV",
01833        cpl_vector_get_stdev(meanspre));
01834        cpl_ensure_code(!error, error);
01835        error =
01836        cpl_propertylist_append_double(qclist,
01837        "ESO QC BIAS PRESCAN MED STDEV",
01838        cpl_vector_get_stdev(medspre));
01839        cpl_ensure_code(!error, error);
01840        error =
01841        cpl_propertylist_append_double(qclist,
01842        "ESO QC BIAS PRESCAN RMS STDEV",
01843        cpl_vector_get_stdev(rmsspre));
01844        cpl_ensure_code(!error, error);
01845 
01846        error =
01847        cpl_propertylist_append_double(qclist,
01848        "ESO QC BIAS OVERSCAN MEAN STDEV",
01849        cpl_vector_get_stdev(meansover));
01850        cpl_ensure_code(!error, error);
01851        error =
01852        cpl_propertylist_append_double(qclist,
01853        "ESO QC BIAS OVERSCAN MED STDEV",
01854        cpl_vector_get_stdev(medsover));
01855        cpl_ensure_code(!error, error);
01856        error =
01857        cpl_propertylist_append_double(qclist,
01858        "ESO QC BIAS OVERSCAN RMS STDEV",
01859        cpl_vector_get_stdev(rmssover));
01860        cpl_ensure_code(!error, error);
01861        */
01862 
01863     cpl_vector_delete(meanspre);
01864     cpl_vector_delete(medspre);
01865     cpl_vector_delete(rmsspre);
01866     cpl_vector_delete(meansover);
01867     cpl_vector_delete(medsover);
01868     cpl_vector_delete(rmssover);
01869 
01870     return CPL_ERROR_NONE;
01871 }
01872 
01873 /*---------------------------------------------------------------------------*/
01874 
01875 /*
01876  * @brief  Retrieve input parameters
01877  * @param  pipeline_name        Input image
01878  * @param  recipe_name          Input image
01879  * @param  parlist              Shift to apply on the x-axis
01880  * @return CPL_ERROR_NONE on success.
01881  */
01882 
01883 /*---------------------------------------------------------------------------*/
01884 static cpl_error_code
01885 detmon_ronbias_region(const cpl_imagelist * rawbiases,
01886                       const cpl_image * masterbias,
01887                       cpl_propertylist * qclist)
01888 {
01889 
01890     int                     nraws = cpl_imagelist_get_size(rawbiases);
01891     int                     i;
01892 
01893     int                     nx =
01894         cpl_image_get_size_x(cpl_imagelist_get_const(rawbiases, 0));
01895     int                     ny =
01896         cpl_image_get_size_y(cpl_imagelist_get_const(rawbiases, 0));
01897 
01898     cpl_vector *rmssreg;
01899     cpl_error_code          error;
01900 
01901     const cpl_image * c_raw;
01902     double median, mbias, mstdev;
01903 
01904     if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) nraws--;
01905 
01906     rmssreg = cpl_vector_new(nraws);
01907 
01908     if(nx < detmon_ronbias_config.ref_urx ||
01909        ny < detmon_ronbias_config.ref_ury) {
01910         cpl_msg_warning(cpl_func, "REGION method not applied. Given "
01911                         "limits of prescan and overscan area "
01912                         "exceed image size. Please check and rerun.");
01913         return CPL_ERROR_NONE;
01914     }
01915 
01916     for(i = 0; i < nraws; i++) {
01917         double                  mean = 0;
01918         double                  stdev = 0;
01919         if(strcmp(detmon_ronbias_config.pmethod, "DIF")) {
01920             c_raw = cpl_imagelist_get_const(rawbiases, i);
01921         } else {
01922             const cpl_image        *c1_raw = cpl_imagelist_get_const(rawbiases, i);
01923             const cpl_image        * c2_raw = cpl_imagelist_get_const(rawbiases, i+1);
01924             c_raw = cpl_image_subtract_create(c1_raw, c2_raw);
01925         }
01926         error = irplib_ksigma_clip(c_raw,
01927                                    detmon_ronbias_config.ref_llx,
01928                                    detmon_ronbias_config.ref_lly,
01929                                    detmon_ronbias_config.ref_urx,
01930                                    detmon_ronbias_config.ref_ury,
01931                                    (double) detmon_ronbias_config.
01932                                    stacking_ks_low,
01933                                    detmon_ronbias_config.
01934                                    stacking_ks_iter, 1e-5,
01935                                    &mean, &stdev);
01936         cpl_ensure_code(!error, error);
01937         /*        cpl_vector_set(rmssreg, i, cpl_image_get_stdev_window(c_raw,
01938                   detmon_ronbias_config.ref_llx,
01939                   detmon_ronbias_config.ref_lly,
01940                   detmon_ronbias_config.ref_urx,
01941                   detmon_ronbias_config.ref_ury));
01942                   */
01943         error = cpl_vector_set(rmssreg, i, stdev);
01944         cpl_ensure_code(!error, error);
01945         if(!strcmp(detmon_ronbias_config.pmethod, "DIF")) cpl_image_delete((cpl_image *)c_raw);
01946     }
01947 
01948     median =  cpl_image_get_median_window(masterbias,
01949                                           detmon_ronbias_config.ref_llx,
01950                                           detmon_ronbias_config.ref_lly,
01951                                           detmon_ronbias_config.ref_urx,
01952                                           detmon_ronbias_config.ref_ury);
01953     error = irplib_ksigma_clip(masterbias,
01954                                detmon_ronbias_config.ref_llx,
01955                                detmon_ronbias_config.ref_lly,
01956                                detmon_ronbias_config.ref_urx,
01957                                detmon_ronbias_config.ref_ury,
01958                                (double) detmon_ronbias_config.
01959                                stacking_ks_low,
01960                                detmon_ronbias_config.
01961                                stacking_ks_iter, 1e-5,
01962                                &mbias, &mstdev);
01963 
01964     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_MED,
01965                                            median);
01966     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_MED,
01967                                          DETMON_QC_BIAS_REGION_MED_C);
01968     cpl_ensure_code(!error, error);
01969 
01970     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_VAL,
01971                                            mbias);
01972     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_VAL,
01973                                          DETMON_QC_BIAS_REGION_VAL_C);
01974     cpl_ensure_code(!error, error);
01975     error = cpl_propertylist_append_double(qclist,DETMON_QC_BIAS_REGION_RON,
01976                                            cpl_vector_get_mean(rmssreg));
01977     error = cpl_propertylist_set_comment(qclist,DETMON_QC_BIAS_REGION_RON,
01978                                          DETMON_QC_BIAS_REGION_RON_C);
01979     cpl_ensure_code(!error, error);
01980     /*
01981        error =
01982        cpl_propertylist_append_double(qclist, "ESO QC BIAS REGION RMS STDEV",
01983        cpl_vector_get_stdev(rmssreg));
01984        cpl_ensure_code(!error, error);
01985        */
01986     cpl_vector_delete(rmssreg);
01987 
01988     return cpl_error_get_code();
01989 }
01990 
01991 /*---------------------------------------------------------------------------*/
01992 
01993 /*
01994  * @brief  Retrieve input parameters
01995  * @param  pipeline_name        Input image
01996  * @param  recipe_name          Input image
01997  * @param  parlist              Shift to apply on the x-axis
01998  * @return CPL_ERROR_NONE on success.
01999  */
02000 
02001 /*---------------------------------------------------------------------------*/
02002 static cpl_image *
02003 detmon_ronbias_master(const cpl_imagelist * rawbiases,
02004                       cpl_mask ** bpmhot, cpl_mask ** bpmcold,
02005                       cpl_mask ** bpmdev, cpl_propertylist * qclist)
02006 {
02007     double                  mean = 0;
02008     double                  stdev = 0;
02009     cpl_image              *masterbias = NULL;
02010     double dark_med, stdev_med,lower, upper;
02011     int hotpix_nb, coldpix_nb, devpix_nb;
02012     cpl_image * stdev_im = NULL;
02013 
02014     if(!strcmp(detmon_ronbias_config.stacking_method, "MEAN"))
02015         masterbias = cpl_imagelist_collapse_create(rawbiases);
02016     if(!strcmp(detmon_ronbias_config.stacking_method, "MINMAX"))
02017         masterbias =
02018             cpl_imagelist_collapse_minmax_create(rawbiases, 0, 10000);
02019     if(!strcmp(detmon_ronbias_config.stacking_method, "KSIGMA"))
02020         masterbias =
02021             cpl_imagelist_collapse_sigclip_create(rawbiases, 3.0, 3.0, 0.9,
02022                                                   CPL_COLLAPSE_MEAN, NULL);
02023     if(!strcmp(detmon_ronbias_config.stacking_method, "MEDIAN"))
02024         masterbias = cpl_imagelist_collapse_median_create(rawbiases);
02025 
02026     skip_if(masterbias == NULL);
02027 
02028     skip_if(irplib_ksigma_clip(masterbias, 1, 1,
02029                                cpl_image_get_size_x(masterbias),
02030                                cpl_image_get_size_y(masterbias),
02031                                (double) detmon_ronbias_config.
02032                                stacking_ks_low,
02033                                detmon_ronbias_config.
02034                                stacking_ks_iter, 1e-5,
02035                                &mean, &stdev));
02036 
02037     if(irplib_isnan(mean))
02038         cpl_msg_error(cpl_func, "We have an error in mean");
02039     if(irplib_isnan(stdev))
02040         cpl_msg_error(cpl_func, "We have an error in stdev");
02041 
02042     skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_MASTER_MEAN,
02043                                            mean));
02044     skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_MASTER_MEAN,
02045                                          DETMON_QC_MASTER_MEAN_C));
02046 
02047     skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_MASTER_RMS,
02048                                            stdev));
02049     skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_MASTER_RMS,
02050                                          DETMON_QC_MASTER_RMS_C));
02051 
02052     /* Compute median-rms of the central part of the dark  */
02053     dark_med = cpl_image_get_median(masterbias);
02054 
02055     lower = dark_med - stdev * detmon_ronbias_config.stacking_ks_low;
02056     upper = dark_med + stdev * detmon_ronbias_config.stacking_ks_high;
02057 
02058     /* Create the hot pixel map */
02059     cpl_mask_delete(*bpmhot);
02060     irplib_check(*bpmhot = cpl_mask_threshold_image_create(masterbias,
02061                                                            upper, DBL_MAX),
02062                  "Cannot compute the hot pixel map");
02063     hotpix_nb = cpl_mask_count(*bpmhot);
02064     skip_if (0);
02065 
02066     /* Create the cold pixel map */
02067     cpl_mask_delete(*bpmcold);
02068     irplib_check(*bpmcold = cpl_mask_threshold_image_create(masterbias,
02069                                                             -FLT_MAX, lower),
02070                  "Cannot compute the cold pixel map");
02071     coldpix_nb = cpl_mask_count(*bpmcold);
02072     skip_if (0);
02073 
02074     /* Create the deviant pixel map */
02075     stdev_im  = irplib_imagelist_collapse_stdev_create(rawbiases);
02076     stdev_med = cpl_image_get_median(stdev_im);
02077 
02078     skip_if(irplib_ksigma_clip(stdev_im, 1, 1,
02079                                cpl_image_get_size_x(stdev_im),
02080                                cpl_image_get_size_y(stdev_im),
02081                                (double) detmon_ronbias_config.
02082                                stacking_ks_low,
02083                                detmon_ronbias_config.
02084                                stacking_ks_iter, 1e-5,
02085                                &mean, &stdev));
02086 
02087     lower = stdev_med - stdev * detmon_ronbias_config.stacking_ks_low;
02088     upper = stdev_med + stdev * detmon_ronbias_config.stacking_ks_high;
02089 
02090     cpl_mask_delete(*bpmdev);
02091     irplib_check(*bpmdev = cpl_mask_threshold_image_create(stdev_im,
02092                                                            lower, upper),
02093                  "Cannot compute the cold pixel map");
02094     cpl_mask_not(*bpmdev);
02095     devpix_nb = cpl_mask_count(*bpmdev);
02096     skip_if (0);
02097 
02098 
02099     skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBCOLDPIX,coldpix_nb));
02100     skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBCOLDPIX,
02101                                          DETMON_QC_NBCOLDPIX_C));
02102 
02103     skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBHOTPIX, hotpix_nb));
02104     skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBHOTPIX,
02105                                          DETMON_QC_NBHOTPIX_C));
02106 
02107     skip_if(cpl_propertylist_append_int(qclist,DETMON_QC_NBDEVPIX, devpix_nb));
02108     skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_NBDEVPIX,
02109                                          DETMON_QC_NBDEVPIX_C));
02110 
02111     end_skip;
02112 
02113     cpl_image_delete(stdev_im);
02114 
02115     if (cpl_error_get_code()) {
02116         cpl_image_delete(masterbias);
02117         masterbias = NULL;
02118     }
02119 
02120     return masterbias;
02121 }
02122 
02123 /*---------------------------------------------------------------------------*/
02124 
02125 /*
02126  * @brief  Retrieve input parameters
02127  * @param  pipeline_name        Input image
02128  * @param  recipe_name          Input image
02129  * @param  parlist              Shift to apply on the x-axis
02130  * @return CPL_ERROR_NONE on success.
02131  */
02132 
02133 /*---------------------------------------------------------------------------*/
02134 static                  cpl_error_code
02135 detmon_ronbias_save(const cpl_parameterlist * parlist,
02136                     cpl_frameset * frameset,
02137                     const char *recipe_name,
02138                     const char *pipeline_name,
02139                     const char *pafregexp,
02140                     const cpl_propertylist * pro_master,
02141                     const cpl_propertylist * pro_xstr, /* Unsupported*/
02142                     const cpl_propertylist * pro_ystr, /* Unsupported*/
02143                     const cpl_propertylist * pro_synth,
02144                     const cpl_propertylist * pro_bpmhot,
02145                     const cpl_propertylist * pro_bpmcold,
02146                     const cpl_propertylist * pro_bpmdev,
02147                     const char *package,
02148                     const cpl_image * masterbias,
02149                     const cpl_image * synthetic,
02150                     const cpl_mask * bpmhot,
02151                     const cpl_mask * bpmcold,
02152                     const cpl_mask * bpmdev,
02153                     cpl_propertylist * qclist,
02154                     const int flag_sets,
02155                     const int which_set,
02156                     cpl_frameset * usedframes,
02157                     int whichext)
02158 {
02159 
02160     cpl_frame              *ref_frame;
02161     cpl_propertylist       *plist = NULL;
02162     char                   *name_o = NULL; /* Avoid (false) uninit warning */
02163 
02164     cpl_propertylist       * paflist   = NULL;
02165     cpl_propertylist       * mainplist = NULL;
02166     cpl_propertylist       * xplist    = NULL;
02167     cpl_image              * image     = NULL;
02168 
02169     cpl_propertylist  * mypro_master     =
02170         cpl_propertylist_duplicate(pro_master);
02171 
02172     cpl_propertylist  * mypro_synth = NULL;
02173     cpl_propertylist  * mypro_bpmhot    =
02174         cpl_propertylist_duplicate(pro_bpmhot);
02175     cpl_propertylist  * mypro_bpmcold =
02176         cpl_propertylist_duplicate(pro_bpmcold);
02177     cpl_propertylist  * mypro_bpmdev =
02178         cpl_propertylist_duplicate(pro_bpmdev);
02179 
02180     cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
02181     cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
02182     cpl_ensure_code(pafregexp != NULL, CPL_ERROR_NULL_INPUT);
02183     cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
02184     cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
02185     cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
02186     cpl_ensure_code(usedframes != NULL, CPL_ERROR_NULL_INPUT);
02187 
02188     if (pro_synth)
02189         mypro_synth = cpl_propertylist_duplicate(pro_synth);
02190 
02191     /* Extra check while XSTR and YSTR are not supported */
02192     cpl_ensure_code(pro_xstr == NULL && pro_ystr == NULL,
02193                     CPL_ERROR_UNSUPPORTED_MODE);
02194 
02195     /* Extract extension headers if multi-extension */
02196     if (detmon_ronbias_config.exts < 0) {
02197         const char * filename =
02198             cpl_frame_get_filename(cpl_frameset_get_first(frameset));
02199 
02200 
02201         xplist = cpl_propertylist_load_regexp(filename, whichext,
02202                                               "ESO DET", 0);
02203         skip_if(cpl_propertylist_append(xplist, qclist));
02204     }
02205 
02206     cpl_msg_info(cpl_func,"dealing with extention %d",whichext);
02207 
02208     /* This is only used later for PAF */
02209     /* Get FITS header from reference file */
02210     ref_frame = cpl_frameset_get_first(frameset);
02211     skip_if(ref_frame == NULL);
02212 
02213     skip_if((mainplist =
02214              cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02215                                    0)) == NULL);
02216 
02217     /**************************/
02218     /*  Write the MASTERBIAS  */
02219     /**************************/
02220 
02221     /* Set the file name for the table */
02222     if(!flag_sets) {
02223         name_o = cpl_sprintf("%s_masterbias.fits", recipe_name);
02224         assert(name_o != NULL);
02225     } else {
02226         name_o =
02227             cpl_sprintf("%s_masterbias_set%02d.fits", recipe_name,
02228                         which_set);
02229         assert(name_o != NULL);
02230     }
02231     /* Save the MASTERBIAS image */
02232     if (whichext == 0) {
02233         cpl_propertylist_append(mypro_master, qclist);
02234 
02235         skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
02236                                    masterbias, CPL_BPP_IEEE_FLOAT, recipe_name,
02237                                    mypro_master, NULL, package, name_o));
02238     } else
02239         skip_if(cpl_image_save(masterbias,
02240                                name_o, CPL_BPP_IEEE_FLOAT, xplist,
02241                                CPL_IO_EXTEND));
02242 
02243     /* Free */
02244     cpl_free(name_o);
02245     name_o = NULL;
02246 
02247     /*****************************/
02248     /*  Write the HOT PIXEL MAP  */
02249     /*****************************/
02250 
02251     /* Set the file name for the table */
02252     if(!flag_sets) {
02253         name_o = cpl_sprintf("%s_hotpixmap.fits", recipe_name);
02254         assert(name_o != NULL);
02255     } else {
02256         name_o =
02257             cpl_sprintf("%s_hotpixmap_set%02d.fits", recipe_name,
02258                         which_set);
02259         assert(name_o != NULL);
02260     }
02261     /* Save the HOTBPM image */
02262     skip_if(0);
02263     image = cpl_image_new_from_mask(bpmhot);
02264     cpl_error_reset();
02265 
02266     if (whichext == 0) {
02267         cpl_propertylist_append(mypro_bpmhot, qclist);
02268 
02269         skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
02270                                    image, CPL_BPP_IEEE_FLOAT, recipe_name,
02271                                    mypro_bpmhot, NULL, package, name_o));
02272     } else
02273         skip_if(cpl_image_save(image,
02274                                name_o, CPL_BPP_IEEE_FLOAT, xplist,
02275                                CPL_IO_EXTEND));
02276 
02277     /* Free */
02278     cpl_free(name_o);
02279     cpl_image_delete(image);
02280     image = NULL;
02281     name_o = NULL;
02282 
02283     /*****************************/
02284     /*  Write the COLD PIXEL MAP  */
02285     /*****************************/
02286 
02287     /* Set the file name for the table */
02288     if(!flag_sets) {
02289         name_o = cpl_sprintf("%s_coldpixmap.fits", recipe_name);
02290         assert(name_o != NULL);
02291     } else {
02292         name_o =
02293             cpl_sprintf("%s_coldpixmap_set%02d.fits", recipe_name,
02294                         which_set);
02295         assert(name_o != NULL);
02296     }
02297     /* Save the COLDBPM image */
02298     skip_if(0);
02299     image = cpl_image_new_from_mask(bpmcold);
02300     cpl_error_reset();
02301 
02302     if (whichext == 0) {
02303         cpl_propertylist_append(mypro_bpmcold, qclist);
02304 
02305         skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
02306                                    image, CPL_BPP_IEEE_FLOAT, recipe_name,
02307                                    mypro_bpmcold, NULL, package, name_o));
02308     } else
02309         skip_if(cpl_image_save(image,
02310                                name_o, CPL_BPP_IEEE_FLOAT, xplist,
02311                                CPL_IO_EXTEND));
02312 
02313     /* Free */
02314     cpl_free(name_o);
02315     cpl_image_delete(image);
02316     image = NULL;
02317     name_o = NULL;
02318 
02319     /*****************************/
02320     /*  Write the DEV PIXEL MAP  */
02321     /*****************************/
02322 
02323     /* Set the file name for the table */
02324     if(!flag_sets) {
02325         name_o = cpl_sprintf("%s_devpixmap.fits", recipe_name);
02326         assert(name_o != NULL);
02327     } else {
02328         name_o =
02329             cpl_sprintf("%s_devpixmap_set%02d.fits", recipe_name,
02330                         which_set);
02331         assert(name_o != NULL);
02332     }
02333     /* Save the DEVBPM image */
02334     skip_if(0);
02335     image = cpl_image_new_from_mask(bpmdev);
02336     cpl_error_reset();
02337 
02338     if (whichext == 0) {
02339         cpl_propertylist_append(mypro_bpmdev, qclist);
02340 
02341         skip_if(cpl_dfs_save_image(frameset, NULL,parlist, usedframes, NULL,
02342                                    image, CPL_BPP_IEEE_FLOAT, recipe_name,
02343                                    mypro_bpmdev, NULL, package, name_o));
02344     } else
02345         skip_if(cpl_image_save(image,
02346                                name_o, CPL_BPP_IEEE_FLOAT, xplist,
02347                                CPL_IO_EXTEND));
02348 
02349     /* Free */
02350     cpl_free(name_o);
02351     cpl_image_delete(image);
02352     image = NULL;
02353     name_o = NULL;
02354 
02355     /*******************************/
02356     /*  Write the SYNTHETIC        */
02357     /*******************************/
02358     if(detmon_ronbias_config.method_bitmask & PREOVERSCAN) {
02359         /* Set the file name for the table */
02360         if(!flag_sets) {
02361             name_o = cpl_sprintf("%s_synthetic.fits", recipe_name);
02362             assert(name_o != NULL);
02363         } else {
02364             name_o =
02365                 cpl_sprintf("%s_synthetic_set%02d.fits", recipe_name,
02366                             which_set);
02367             assert(name_o != NULL);
02368         }
02369 
02370         if (whichext == 0) {
02371             /* Save the SYNTHETIC image */
02372             cpl_propertylist_append(mypro_synth, qclist);
02373 
02374             skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
02375                                        NULL,synthetic, CPL_BPP_IEEE_DOUBLE,
02376                                        recipe_name, mypro_synth, NULL,
02377                                        package, name_o));
02378         } else
02379             skip_if(cpl_image_save(synthetic, name_o, CPL_BPP_IEEE_FLOAT,
02380                                    xplist, CPL_IO_EXTEND));
02381 
02382         /* Free */
02383         cpl_free(name_o);
02384         name_o = NULL;
02385     }
02386 
02387     /*******************************/
02388     /*  Write the PAF file         */
02389     /*******************************/
02390     if (qclist) {
02391         paflist = cpl_propertylist_new();
02392 
02393         /* Set the file name for the PAF */
02394         if(detmon_ronbias_config.exts >= 0) {
02395             skip_if((plist =
02396                      cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02397                                            detmon_ronbias_config.exts)) == NULL);
02398 
02399             if(!flag_sets) {
02400                 name_o = cpl_sprintf("%s.paf", recipe_name);
02401                 assert(name_o != NULL);
02402             } else {
02403                 name_o = cpl_sprintf("%s_set%02d.paf",
02404                                      recipe_name, which_set);
02405                 assert(name_o != NULL);
02406             }
02407         } else {
02408             skip_if((plist =
02409                      cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02410                                            whichext)) == NULL);
02411 
02412 
02413             if(!flag_sets) {
02414                 name_o = cpl_sprintf("%s_ext%02d.paf",
02415                                      recipe_name, whichext);
02416                 assert(name_o != NULL);
02417             } else {
02418                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf",
02419                                      recipe_name,
02420                                      which_set, whichext);
02421                 assert(name_o != NULL);
02422             }
02423         }
02424 
02425         /* Get the keywords for the paf file */
02426         skip_if(cpl_propertylist_copy_property_regexp(paflist, plist,
02427                                                       pafregexp, 0));
02428         skip_if(cpl_propertylist_copy_property_regexp(paflist, mainplist,
02429                                                       pafregexp, 0));
02430 
02431         skip_if(cpl_propertylist_append(paflist, qclist));
02432 
02433         /* Save the PAF */
02434         skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, paflist, name_o));
02435 
02436     }
02437 
02438     end_skip;
02439 
02440     cpl_propertylist_delete(plist);
02441     cpl_propertylist_delete(paflist);
02442     cpl_propertylist_delete(mainplist);
02443     cpl_propertylist_delete(xplist);
02444     cpl_free(name_o);
02445     cpl_image_delete(image);
02446 
02447     cpl_propertylist_delete(mypro_master);
02448     cpl_propertylist_delete(mypro_synth);
02449     cpl_propertylist_delete(mypro_bpmhot);
02450     cpl_propertylist_delete(mypro_bpmcold);
02451     cpl_propertylist_delete(mypro_bpmdev);
02452 
02453     return cpl_error_get_code();
02454 }
02455 
02456 cpl_propertylist *
02457 detmon_fill_prolist(const char * procatg,
02458                     const char * protype,
02459                     const char * protech,
02460                     cpl_boolean  proscience)
02461 {
02462     cpl_propertylist * prolist = cpl_propertylist_new();
02463 
02464     cpl_propertylist_append_string(prolist, CPL_DFS_PRO_CATG,    procatg);
02465     cpl_propertylist_append_bool(prolist,   CPL_DFS_PRO_SCIENCE, proscience);
02466     if (protype)
02467         cpl_propertylist_append_string(prolist, CPL_DFS_PRO_TYPE,    protype);
02468     if (protech)
02469         cpl_propertylist_append_string(prolist, CPL_DFS_PRO_TECH,    protech);
02470 
02471     return prolist;
02472 }
02473 
02474 /*---------------------------------------------------------------------------*/
02475 
02476 /*
02477  * @brief  Retrieve input parameters
02478  * @param  pipeline_name        Input image
02479  * @param  recipe_name          Input image
02480  * @param  parlist              Shift to apply on the x-axis
02481  * @return CPL_ERROR_NONE on success.
02482  */
02483 
02484 /*---------------------------------------------------------------------------*/
02485 int
02486 detmon_ronbias_dfs_set_groups(cpl_frameset * set, const char *tag)
02487 {
02488     cpl_frame              *cur_frame;
02489     const char             *cur_tag;
02490     int                     nframes;
02491     int                     i;
02492 
02493     /* Check entries */
02494     if(set == NULL)
02495         return -1;
02496 
02497     /* Initialize */
02498     nframes = cpl_frameset_get_size(set);
02499 
02500     /* Loop on frames */
02501     for(i = 0; i < nframes; i++) {
02502         cur_frame = cpl_frameset_get_frame(set, i);
02503         cur_tag = cpl_frame_get_tag(cur_frame);
02504 
02505         /* RAW frames */
02506         if(!strcmp(cur_tag, tag))
02507             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
02508         /* CALIB frames */
02509 
02510         /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
02511                   cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
02512                   */
02513     }
02514     return 0;
02515 }
02516 
02517 /*---------------------------------------------------------------------------*/
02518 
02519 /*
02520  * @brief  Retrieve input parameters
02521  * @param  pipeline_name        Input image
02522  * @param  recipe_name          Input image
02523  * @param  parlist              Shift to apply on the x-axis
02524  * @return CPL_ERROR_NONE on success.
02525  */
02526 
02527 /*---------------------------------------------------------------------------*/
02528 cpl_image *
02529 detmon_build_synthetic(cpl_image * prescan, cpl_image * overscan)
02530 {
02531     cpl_size                     j;
02532 
02533     int distance = detmon_ronbias_config.overscan_urx -
02534         detmon_ronbias_config.prescan_llx + 1;
02535 
02536     double * mean_x = (double *) cpl_malloc(sizeof(double) * distance);
02537 
02538     double * xvalues = (double *) cpl_malloc(sizeof(double) * distance);
02539 
02540     cpl_vector             *x = NULL;
02541     cpl_vector             *y = NULL;
02542 
02543     cpl_polynomial         *poly = NULL;
02544     cpl_polynomial         *poly2 = NULL;
02545 
02546     cpl_matrix     * samppos;
02547 
02548     cpl_size         pows[2] = { 0, 0 };
02549 
02550     cpl_image      * synthetic = NULL;
02551 
02552     double           initial = 0;
02553 
02554     /* Initialize */
02555     for(j = 0; j < distance; j++) {
02556         *(mean_x + j) = 0;
02557         *(xvalues + j) = j;
02558     }
02559 
02560     for(j = 0; j < cpl_image_get_size_x(prescan); j++) {
02561         *(mean_x + j) =
02562             cpl_image_get_mean_window(prescan, j + 1, 1, j + 1,
02563                                       cpl_image_get_size_y(prescan));
02564     }
02565 
02566     for(j = 0; j < cpl_image_get_size_x(overscan); j++) {
02567         *(mean_x + distance - cpl_image_get_size_x(overscan) + j) =
02568             cpl_image_get_mean_window(overscan, j + 1, 1, j + 1,
02569                                       cpl_image_get_size_y(overscan));
02570     }
02571 
02572     x = cpl_vector_wrap(distance, xvalues);
02573     y = cpl_vector_wrap(distance, mean_x);
02574 
02575     poly = cpl_polynomial_new(1);
02576     samppos =
02577         cpl_matrix_wrap(1, cpl_vector_get_size(x), cpl_vector_get_data(x));
02578 
02579     cpl_polynomial_fit(poly, samppos, NULL, y, NULL,
02580                        CPL_FALSE, NULL, &detmon_ronbias_config.preoverscan_degree);
02581 
02582     cpl_matrix_unwrap(samppos);
02583 
02584     cpl_vector_unwrap(x);
02585     cpl_vector_unwrap(y);
02586 
02587     initial = *mean_x;
02588 
02589     cpl_free(xvalues);
02590     cpl_free(mean_x);
02591 
02592     poly2 = cpl_polynomial_new(2);
02593 
02594     j = 0;
02595     cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
02596 
02597     pows[0] = 1;
02598     j = 1;
02599     cpl_polynomial_set_coeff(poly2, pows, cpl_polynomial_get_coeff(poly, &j));
02600 
02601     cpl_polynomial_delete(poly);
02602 
02603     synthetic =
02604         cpl_image_new(distance, cpl_image_get_size_y(prescan),
02605                       CPL_TYPE_DOUBLE);
02606 
02607     if(cpl_image_fill_polynomial(synthetic, poly2, initial, 1, 1, 1)) {
02608         cpl_msg_error(cpl_func, "Error creating the synthetic frame");
02609         cpl_polynomial_delete(poly2);
02610         return NULL;
02611     }
02612 
02613     cpl_polynomial_delete(poly2);
02614 
02615     return synthetic;
02616 }
02617 
02618 /*---------------------------------------------------------------------------*/
02619 
02620 /*
02621  * @brief  Retrieve input parameters
02622  * @param  pipeline_name        Input image
02623  * @param  recipe_name          Input image
02624  * @param  parlist              Shift to apply on the x-axis
02625  * @return CPL_ERROR_NONE on success.
02626  */
02627 
02628 /*---------------------------------------------------------------------------*/
02629 static cpl_error_code
02630 detmon_ronbias_dutycycl(const cpl_frameset * frameset,
02631                         cpl_propertylist * qclist)
02632 {
02633     const cpl_frame        *first = 0;
02634     cpl_propertylist       *plistfirst = 0;
02635     double                  tfirst;
02636     int                     nraws;
02637     const cpl_frame        *last = 0;
02638     cpl_propertylist       *plistlast = 0;
02639     double                  tlast;
02640     double                  dutycycl;
02641     cpl_error_code          error;
02642 
02643     first = cpl_frameset_get_first_const(frameset);
02644     plistfirst = cpl_propertylist_load(cpl_frame_get_filename(first), 0);
02645     tfirst = cpl_propertylist_get_double(plistfirst, "MJD-OBS");
02646     nraws = cpl_frameset_get_size(frameset);
02647     last = cpl_frameset_get_frame_const(frameset, nraws - 1);
02648     plistlast = cpl_propertylist_load(cpl_frame_get_filename(last), 0);
02649     tlast = cpl_propertylist_get_double(plistlast, "MJD-OBS");
02650     dutycycl = (tlast - tfirst) / (nraws - 1);
02651 
02652     error = cpl_error_get_code();
02653     if (error != CPL_ERROR_NONE)
02654     {
02655         goto cleanup;
02656     }
02657     cpl_propertylist_append_double(qclist,DETMON_QC_DUTYCYCL, dutycycl);
02658     error = cpl_propertylist_set_comment(qclist,DETMON_QC_DUTYCYCL,
02659                                          DETMON_QC_DUTYCYCL_C);
02660 
02661 cleanup:
02662 
02663     cpl_propertylist_delete(plistfirst);
02664     cpl_propertylist_delete(plistlast);
02665 
02666     return error;
02667 }
02668 
02669 
02670 /*--------------------------------------------------------------------------*/
02671 
02672 /*
02673  * @brief  Reduce periodic noise
02674  * @param  image         Input image
02675  * @param  freq          Readout frequency, given in Kpixel/s.
02676  *
02677  * @return 1-d image, representing the distribution of noise. NULL if failed.
02678  */
02679 
02680 /*--------------------------------------------------------------------------*/
02681 
02682 
02683 #define HORIZONTAL TRUE
02684 
02685 cpl_table              *
02686 detmon_pernoise_reduce(cpl_image * image)
02687 {
02688     int                     nsamples, nffts;
02689     int                     i, j;
02690 
02691     int status;
02692     float * hanning = 0;
02693     float * power = 0;
02694     cpl_image * power_im = 0;
02695     cpl_image * output = 0;
02696     cpl_image * pos_spec = 0;
02697     cpl_table * table = 0;
02698     cpl_image* fourier_im = 0;
02699     double freq;
02700     cpl_error_code error = CPL_ERROR_NONE;
02701     cpl_image * sub_image = 0;
02702     int nffts_old;
02703 
02704 
02705     if(detmon_pernoise_config.direction == HORIZONTAL) {
02706         error = cpl_image_flip(image, 1);
02707         cpl_ensure(!error, error, NULL);
02708     }
02709 
02710     nsamples = cpl_image_get_size_x(image);
02711     nffts = cpl_image_get_size_y(image);
02712 
02713 
02714     /* Rewrite the previous lines with a better style (: ...) */
02715 
02716     /*
02717      * 1. preprocessing task:
02718      * Estimate the background fitting the image to a
02719      * 2-D polynomial and substract it from the image.
02720      */
02721 
02722     error = detmon_pernoise_rm_bg(image, nsamples, nffts);
02723     cpl_ensure(!error, error, NULL);
02724 
02725     sub_image = cpl_image_extract(image, nsamples/8 + 1, nffts/8+1,
02726                                   nsamples*7/8, nffts*7/8);
02727     nffts_old = nffts;
02728     nsamples = cpl_image_get_size_x(sub_image);
02729     nffts = cpl_image_get_size_y(sub_image);
02730 
02731     /*
02732      * 2. preprocessing task:
02733      * Remove the effect of hot and dark pixels, replacing their values by
02734      * the average value of the neighbouring pixels.
02735      */
02736 
02737     /*
02738      * 3. preprocessing task:
02739      * Apply a Hanning vector
02740      */
02741 
02742     hanning = cpl_malloc(sizeof(float) * nsamples);
02743 
02744     for(i = 0; i < nsamples; i++) {
02745         *(hanning + i) = 0.5 - 0.5 * cos(2 * CPL_MATH_PI * (float) i / nsamples);
02746         for(j = 0; j < nffts; j++) {
02747             double                  value =
02748                 cpl_image_get(sub_image, i + 1, j + 1, &status);
02749             error = cpl_image_set(sub_image, i + 1, j + 1, (*(hanning + i)) * value);
02750         }
02751     }
02752 
02753     cpl_free(hanning);
02754     if (error != CPL_ERROR_NONE)
02755     {
02756         goto cleanup;
02757     }
02758 
02759     power = (float *) cpl_calloc(sizeof(float), nsamples * nffts);
02760 
02761 
02762     fourier_im = cpl_image_new(nsamples,nffts,  CPL_TYPE_FLOAT_COMPLEX);
02763     error = cpl_fft_image(fourier_im, sub_image, CPL_FFT_FORWARD);
02764 
02765     for(i = 1; i <= nffts; i++) {
02766         for(j = 1; j <= nsamples; j++) {
02767             int rej = 0;
02768             double complex cvalue = cpl_image_get_complex(fourier_im,j, i, &rej );
02769             double value = cabs(cvalue);
02770             /*
02771              *(power + j + i * nsamples) = *((float complex *)fourier + j + i * nsamples) *
02772              conjf(*((float complex *)fourier +j + i * nsamples));
02773              */
02774             cpl_image_set(power_im, j, i, value);
02775         }
02776         /*  Is it necessary to divide here by 2 * pi? */
02777     }
02778     cpl_image_delete(fourier_im);
02779 
02780     output   = cpl_image_collapse_create(power_im, 0);
02781     pos_spec = cpl_image_extract(output, 1, 1, nsamples/2, 1);
02782 
02783     cpl_image_delete(power_im);
02784     cpl_free(power);
02785 
02786     cpl_image_delete(output);
02787 
02788     table = cpl_table_new(nsamples/2);
02789     cpl_table_new_column(table, "FREQ", CPL_TYPE_DOUBLE);
02790     cpl_table_new_column(table, "POW", CPL_TYPE_DOUBLE);
02791 
02792     freq = detmon_pernoise_config.speed*1000/nffts_old;
02793 
02794     for(i = 0; i < nsamples/2; i++) {
02795         error = cpl_table_set(table, "FREQ", i, freq/(nsamples/2)*i);
02796         error = cpl_table_set(table, "POW", i, cpl_image_get(pos_spec, i+1, 1, &status));
02797     }
02798 
02799     for(i= 0; i < 5; i++) {
02800         error = cpl_table_set(table, "POW", i, 0.0);
02801     }
02802 
02803 
02804 cleanup:
02805     cpl_image_delete(pos_spec);
02806 
02807     cpl_image_delete(sub_image);
02808     if (error != CPL_ERROR_NONE)
02809     {
02810         cpl_table_delete(table);
02811         table = 0;
02812     }
02813     return table;
02814 }
02815 #undef HORIZONTAL
02816 
02817 
02818 
02819 /*---------------------------------------------------------------------------*/
02820 
02821 /*
02822  * @brief  Retrieve input parameters
02823  * @param  pipeline_name        Input image
02824  * @param  recipe_name          Input image
02825  * @param  parlist              Shift to apply on the x-axis
02826  * @return CPL_ERROR_NONE on success.
02827  */
02828 
02829 /*---------------------------------------------------------------------------*/
02830 
02831 
02832 cpl_error_code
02833 detmon_rm_bpixs(cpl_image ** image,
02834                 const double kappa, int nffts, int nsamples)
02835 {
02836     int                     i, j;
02837 
02838     float                  *data = cpl_image_get_data_float(*image);
02839     int k = 0;
02840     for(i = 0; i < nffts; i++) {
02841         for(j = 0; j < nsamples; j++) {
02842             float                   neighbours = 0;
02843             int                     nneighs = 0;
02844             float                   average = 0;
02845 
02846             /*
02847              * Look for the way to optimize this:
02848              * Some of the points added to neighbours coincide
02849              * in one iteration and the following
02850              */
02851             if(i > 0) {
02852                 neighbours += *(data + (i - 1) * nsamples + j);
02853                 nneighs++;
02854             }
02855             if(i < nffts - 1) {
02856                 neighbours += *(data + (i + 1) * nsamples + j);
02857                 nneighs++;
02858             }
02859             if(j > 0) {
02860                 neighbours += *(data + i * nsamples + (j - 1));
02861                 nneighs++;
02862             }
02863             if(j < nsamples - 1) {
02864                 neighbours += *(data + i * nsamples + (j + 1));
02865                 nneighs++;
02866             }
02867             average = neighbours / nneighs;
02868             if(average > 0) {
02869                 if(*(data + i * nsamples + j) < average * (-1 * kappa) ||
02870                    *(data + i * nsamples + j) > average * (kappa)) {
02871                     k++;
02872                     *(data + i * nsamples + j) = average;
02873                 }
02874             }
02875             if(average < 0) {
02876                 if(*(data + i * nsamples + j) > average * (-1 * kappa) ||
02877                    *(data + i * nsamples + j) < average * (kappa)) {
02878                     k++;
02879                     *(data + i * nsamples + j) = average;
02880                 }
02881             }
02882 
02883         }
02884     }
02885 
02886 
02887     return cpl_error_get_code();
02888 
02889 }
02890 
02891 /* Start duplicated code */
02892 
02893 #define RECT_RON_HS         4
02894 #define RECT_RON_SAMPLES    100
02895 
02896 /*---------------------------------------------------------------------------*/
02897 
02898 /*
02899  * @brief  Retrieve input parameters
02900  * @param  pipeline_name        Input image
02901  * @param  recipe_name          Input image
02902  * @param  parlist              Shift to apply on the x-axis
02903  * @return CPL_ERROR_NONE on success.
02904  */
02905 
02906 /*---------------------------------------------------------------------------*/
02907 cpl_error_code
02908 irplib_flux_get_bias_window(const cpl_image * diff,
02909                             const int *zone_def,
02910                             int ron_hsize,
02911                             int ron_nsamp, double *bias, double *error)
02912 {
02913     const int               hsize = ron_hsize < 0 ? RECT_RON_HS : ron_hsize;
02914     const int               nsamples =
02915         ron_nsamp < 0 ? RECT_RON_SAMPLES : ron_nsamp;
02916     cpl_bivector           *sample_reg;
02917     cpl_vector             *rms_list;
02918     int                     rect[4];
02919     int                     zone[4];
02920     double                 *px;
02921     double                 *py;
02922     double                 *pr;
02923     int                     i;
02924 
02925     /* Test entries */
02926     cpl_ensure_code(diff && bias, CPL_ERROR_NULL_INPUT);
02927 
02928     /* Generate nsamples window centers in the image */
02929     if(zone_def != NULL) {
02930         rect[0] = zone_def[0] + hsize + 1;      /* xmin */
02931         rect[1] = zone_def[1] - hsize - 1;      /* xmax */
02932         rect[2] = zone_def[2] + hsize + 1;      /* ymin */
02933         rect[3] = zone_def[3] - hsize - 1;      /* ymax */
02934     } else {
02935         rect[0] = hsize + 1;    /* xmin */
02936         rect[1] = cpl_image_get_size_x(diff) - hsize - 1;       /* xmax */
02937         rect[2] = hsize + 1;    /* ymin */
02938         rect[3] = cpl_image_get_size_y(diff) - hsize - 1;       /* ymax */
02939     }
02940 
02941     cpl_ensure_code(rect[0] < rect[1] && rect[2] < rect[3],
02942                     CPL_ERROR_ILLEGAL_INPUT);
02943 
02944     /* Generate n+1 regions, because the first region is always at (0,0) */
02945     /* and it would bias the measurement. */
02946     sample_reg =
02947         irplib_bivector_gen_rect_poisson(rect, nsamples + 1, nsamples + 1);
02948     cpl_ensure(sample_reg != NULL, CPL_ERROR_ILLEGAL_INPUT,
02949                CPL_ERROR_ILLEGAL_INPUT);
02950 
02951     px = cpl_bivector_get_x_data(sample_reg);
02952     py = cpl_bivector_get_y_data(sample_reg);
02953 
02954     /* Now, for each window center, extract a vignette and compute the */
02955     /* signal RMS in it. Store this rms into a table. */
02956     rms_list = cpl_vector_new(nsamples);
02957     cpl_ensure(rms_list != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02958     pr = cpl_vector_get_data(rms_list);
02959 
02960     for(i = 0; i < nsamples; i++) {
02961         zone[0] = (int) px[i + 1] - hsize;
02962         zone[1] = (int) px[i + 1] + hsize;
02963         zone[2] = (int) py[i + 1] - hsize;
02964         zone[3] = (int) py[i + 1] + hsize;
02965         pr[i] = cpl_image_get_mean_window(diff,
02966                                           zone[0], zone[2], zone[1], zone[3]);
02967     }
02968     cpl_bivector_delete(sample_reg);
02969 
02970     /* The error is the rms of the rms */
02971     if(error != NULL)
02972         *error = cpl_vector_get_stdev(rms_list);
02973 
02974     /* The final computed RMS is the median of all values.  */
02975     /* This call will modify the rms_list */
02976     *bias = cpl_vector_get_median(rms_list);
02977 
02978     cpl_vector_delete(rms_list);
02979 
02980     return CPL_ERROR_NONE;
02981 }
02982 
02983 #undef RECT_RON_HS
02984 #undef RECT_RON_SAMPLES
02985 
02986 /*---------------------------------------------------------------------------*/
02987 
02988 /*
02989  * @brief  Retrieve input parameters
02990  * @param  pipeline_name        Input image
02991  * @param  recipe_name          Input image
02992  * @param  parlist              Shift to apply on the x-axis
02993  * @return CPL_ERROR_NONE on success.
02994  */
02995 
02996 /*---------------------------------------------------------------------------*/
02997 static cpl_bivector    *
02998 irplib_bivector_gen_rect_poisson(const int *r, const int np, const int homog)
02999 {
03000     double                  min_dist;
03001     int                     i;
03002     int                     gnp;
03003     cpl_bivector           *list;
03004     double                  cand_x, cand_y;
03005     int                     ok;
03006     int                     start_ndx;
03007     int                     xmin, xmax, ymin, ymax;
03008 
03009     /* Corrected Homogeneity factor */
03010     const int               homogc = 0 < homog && homog < np ? homog : np;
03011     double                 *px;
03012     double                 *py;
03013 
03014     /* error handling: test arguments are correct */
03015     cpl_ensure(r, CPL_ERROR_NULL_INPUT, NULL);
03016     cpl_ensure(np > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
03017 
03018     list = cpl_bivector_new(np);
03019     cpl_ensure(list, CPL_ERROR_NULL_INPUT, NULL);
03020     px = cpl_bivector_get_x_data(list);
03021     py = cpl_bivector_get_y_data(list);
03022 
03023     xmin = r[0];
03024     xmax = r[1];
03025     ymin = r[2];
03026     ymax = r[3];
03027 
03028     min_dist =
03029         CPL_MATH_SQRT1_2 * ((xmax - xmin) * (ymax - ymin) / (double) (homogc + 1));
03030     gnp = 1;
03031     px[0] = 0;
03032     py[0] = 0;
03033 
03034     /* First: generate <homog> points */
03035     while(gnp < homogc) {
03036         /* Pick a random point within requested range */
03037         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03038         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03039 
03040         /* Check the candidate obeys the minimal Poisson distance */
03041         ok = 1;
03042         for(i = 0; i < gnp; i++) {
03043             if(pdist(cand_x, cand_y, px[i], py[i]) < min_dist) {
03044                 /* does not check Poisson law: reject point */
03045                 ok = 0;
03046                 break;
03047             }
03048         }
03049         if(ok) {
03050             /* obeys Poisson law: register the point as valid */
03051             px[gnp] = cand_x;
03052             py[gnp] = cand_y;
03053             gnp++;
03054         }
03055     }
03056 
03057     /* Iterative process: */
03058     /* Pick points out of Poisson distance of the last <homogc-1> points. */
03059     start_ndx = 0;
03060     while(gnp < np) {
03061         /* Pick a random point within requested range */
03062         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03063         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03064 
03065         /* Check the candidate obeys the minimal Poisson distance */
03066         ok = 1;
03067         for(i = 0; i < homogc; i++) {
03068             if(pdist(cand_x,
03069                      cand_y,
03070                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
03071                 /* does not check Poisson law: reject point */
03072                 ok = 0;
03073                 break;
03074             }
03075         }
03076         if(ok) {
03077             /* obeys Poisson law: register the point as valid */
03078             px[gnp] = cand_x;
03079             py[gnp] = cand_y;
03080             gnp++;
03081         }
03082     }
03083 
03084     /* Iterative process: */
03085     /* Pick points out of Poisson distance of the last <homogc-1> points. */
03086     start_ndx = 0;
03087     while(gnp < np) {
03088         /* Pick a random point within requested range */
03089         cand_x = cpl_drand() * (xmax - xmin) + xmin;
03090         cand_y = cpl_drand() * (ymax - ymin) + ymin;
03091 
03092         /* Check the candidate obeys the minimal Poisson distance */
03093         ok = 1;
03094         for(i = 0; i < homogc; i++) {
03095             if(pdist(cand_x,
03096                      cand_y,
03097                      px[start_ndx + i], py[start_ndx + i]) < min_dist) {
03098                 /* does not check Poisson law: reject point */
03099                 ok = 0;
03100                 break;
03101             }
03102         }
03103         if(ok) {
03104             /* obeys Poisson law: register the point as valid */
03105             px[gnp] = cand_x;
03106             py[gnp] = cand_y;
03107             gnp++;
03108             start_ndx++;
03109         }
03110     }
03111     return list;
03112 }
03113 
03114 /* End of duplicated code */
03115 
03116 /*---------------------------------------------------------------------------*/
03117 
03118 /*
03119  * @brief  Retrieve input parameters
03120  * @param  pipeline_name        Input image
03121  * @param  recipe_name          Input image
03122  * @param  parlist              Shift to apply on the x-axis
03123  * @return CPL_ERROR_NONE on success.
03124  */
03125 
03126 /*---------------------------------------------------------------------------*/
03127 cpl_error_code
03128 detmon_pernoise(cpl_frameset      * frameset,
03129                 const cpl_parameterlist * parlist,
03130                 const char        * tag,
03131                 const char        * recipe_name,
03132                 const char        * pipeline_name,
03133                 const char        * procatg_tbl,
03134                 const char        * package,
03135                 int              (*compare)(const cpl_frame *,
03136                                             const cpl_frame *))
03137 {
03138     cpl_size                     nsets;
03139     cpl_size                    *selection = NULL;
03140     int                     i;
03141     cpl_error_code          error;
03142 
03143     if(detmon_pernoise_dfs_set_groups(frameset, tag)) {
03144         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
03145     }
03146 
03147     /*
03148      * This function reads all inputs parameters from parlist
03149      * and stores them in a global variable detmon_ronbias_config.
03150      * Similar to detmon_lg_retrieve_parlist(). See detmon.c
03151      */
03152     error = detmon_pernoise_retrieve_parlist(pipeline_name,
03153                                              recipe_name, parlist);
03154     cpl_ensure_code(!error, error);
03155 
03156     /* Labelise all input frames */
03157     if(compare == NULL)
03158         nsets = 1;
03159     else {
03160         cpl_msg_info(cpl_func, "Identify the different settings");
03161         selection = cpl_frameset_labelise(frameset, compare, &nsets);
03162         if(selection == NULL)
03163             cpl_msg_error(cpl_func, "Cannot labelise input frames");
03164     }
03165 
03166     detmon_pernoise_config.nb_extensions = 1;
03167     if(detmon_pernoise_config.exts < 0) {
03168         const cpl_frame        *cur_frame =
03169             cpl_frameset_get_first_const(frameset);
03170         /* Get the nb of extensions */
03171         detmon_pernoise_config.nb_extensions =
03172             cpl_frame_get_nextensions(cur_frame);
03173     }
03174 
03175     /* Extract settings and reduce each of them */
03176     for(i = 0; i < nsets; i++)
03177     {
03178         int j;
03179         cpl_table ** freq_table;
03180         cpl_propertylist ** qclist =
03181             (cpl_propertylist **)
03182             cpl_malloc(detmon_pernoise_config.nb_extensions *
03183                        sizeof(cpl_propertylist *));
03184 
03185         cpl_imagelist ** raws = (cpl_imagelist **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_imagelist *));
03186         cpl_image ** input = (cpl_image **) cpl_malloc(detmon_pernoise_config.nb_extensions * sizeof(cpl_image *));
03187 
03188         /* Initialise memory for products */
03189         if(detmon_pernoise_config.mode == 1)
03190         {
03191             freq_table =
03192                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03193                                           4 * sizeof(cpl_table *));
03194         } else
03195         {
03196             freq_table =
03197                 (cpl_table **) cpl_malloc(detmon_pernoise_config.nb_extensions *
03198                                           sizeof(cpl_table *));
03199         }
03200 
03201         if(detmon_pernoise_config.exts >= 0)
03202         {
03203             *raws =
03204                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03205                                             detmon_pernoise_config.exts);
03206             *input = cpl_image_subtract_create(cpl_imagelist_get(*raws,0),
03207                                                cpl_imagelist_get(*raws,1));
03208         } else
03209         {
03210             cpl_imagelist          *raws_all_exts =
03211                 cpl_imagelist_load_frameset(frameset, CPL_TYPE_FLOAT, 1,
03212                                             -1);
03213             for(j = 0; j < detmon_pernoise_config.nb_extensions; j++)
03214             {
03215                 int nframes = cpl_frameset_get_size(frameset);
03216                 int                     k;
03217                 for(k = 0; k < nframes; k++)
03218                 {
03219                     cpl_image              *image =
03220                         cpl_imagelist_unset(raws_all_exts,
03221                                             (detmon_pernoise_config.
03222                                              nb_extensions - 1 - j) * k);
03223                     cpl_imagelist_set(raws[j], image, k);
03224                 }
03225                 input[j] =
03226                     cpl_image_subtract_create(cpl_imagelist_get(raws[j],0),
03227                                               cpl_imagelist_get(raws[j],1));
03228             }
03229         }
03230 
03231         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++) {
03232             cpl_msg_info(cpl_func, "Starting reduction");
03233             qclist[j] = cpl_propertylist_new();
03234             if(detmon_pernoise_config.mode == 1)
03235             {
03236                 int nx = cpl_image_get_size_x(input[j]);
03237                 int ny = cpl_image_get_size_y(input[j]);
03238                 int k = 0;
03239                 cpl_image* quad[4];
03240 
03241                 quad[0] = cpl_image_extract(input[j], 1, 1, nx/2, ny/2);
03242                 quad[1] = cpl_image_extract(input[j], 1, ny/2+1, nx/2, ny);
03243                 quad[2] = cpl_image_extract(input[j], nx/2+1, 1, nx, ny/2);
03244                 quad[3] = cpl_image_extract(input[j], nx/2+1, ny/2+1, nx, ny);
03245 
03246                 for (k = 0; k < 4; k++)
03247                 {
03248                     freq_table[j * 4 + k] = detmon_pernoise_reduce(quad[k]);
03249                 }
03250                 for(k = 0; k < 4; k++)
03251                 {
03252                     error = detmon_pernoise_qc(qclist[j], freq_table[j + k], k+1);
03253                     if (error != CPL_ERROR_NONE)
03254                         break;
03255                 }
03256                 for (k = 0; k < 4; k++)
03257                 {
03258                     cpl_image_delete(quad[k]);
03259                 }
03260             } else
03261             {
03262                 freq_table[j] = detmon_pernoise_reduce(input[j]);
03263                 if(freq_table[j] != NULL)
03264                 {
03265                     error = detmon_pernoise_qc(qclist[j], freq_table[j], 0);
03266                 }
03267             }
03268             if (error != CPL_ERROR_NONE)
03269             {
03270                 break;
03271             }
03272         }
03273         if (error == CPL_ERROR_NONE)
03274         {
03275             error = detmon_pernoise_save(parlist, frameset, recipe_name,
03276                                          pipeline_name, procatg_tbl,
03277                                          package, freq_table, qclist, 0,
03278                                          0, frameset);
03279         }
03280 
03281         for(j = 0; j < detmon_pernoise_config.nb_extensions; j++)
03282         {
03283             cpl_propertylist_delete(qclist[j]);
03284             cpl_imagelist_delete(raws[j]);
03285             cpl_image_delete(input[j]);
03286         }
03287         cpl_free(qclist);
03288         cpl_free(raws);
03289         cpl_free(input);
03290         if(detmon_pernoise_config.mode == 1)
03291         {
03292             for(j= 0; j < detmon_pernoise_config.nb_extensions * 4; j++) {
03293                 cpl_table_delete(freq_table[j]);
03294             }
03295         } else {
03296             for(j= 0; j < detmon_pernoise_config.nb_extensions; j++) {
03297                 cpl_table_delete(freq_table[j]);
03298             }
03299         }
03300         cpl_free(freq_table);
03301         if (error != CPL_ERROR_NONE)
03302         {
03303             break;
03304         }
03305     }
03306 
03307     return cpl_error_get_code();
03308 }
03309 
03310 /*---------------------------------------------------------------------------*/
03311 
03312 /*
03313  * @brief  Retrieve input parameters
03314  * @param  pipeline_name        Input image
03315  * @param  recipe_name          Input image
03316  * @param  parlist              Shift to apply on the x-axis
03317  * @return CPL_ERROR_NONE on success.
03318  */
03319 
03320 /*---------------------------------------------------------------------------*/
03321 int
03322 detmon_pernoise_dfs_set_groups(cpl_frameset * set, const char *tag)
03323 {
03324     cpl_frame              *cur_frame;
03325     const char             *cur_tag;
03326     int                     nframes;
03327     int                     i;
03328 
03329     /* Check entries */
03330     if(set == NULL)
03331         return -1;
03332 
03333     /* Initialize */
03334     nframes = cpl_frameset_get_size(set);
03335 
03336     /* Loop on frames */
03337     for(i = 0; i < nframes; i++) {
03338         cur_frame = cpl_frameset_get_frame(set, i);
03339         cur_tag = cpl_frame_get_tag(cur_frame);
03340 
03341         /* RAW frames */
03342         if(!strcmp(cur_tag, tag))
03343             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
03344         /* CALIB frames */
03345 
03346         /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
03347                   cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
03348                   */
03349     }
03350     return 0;
03351 }
03352 
03353 /*---------------------------------------------------------------------------*/
03354 
03355 /*
03356  * @brief  Retrieve input parameters
03357  * @param  pipeline_name        Input image
03358  * @param  recipe_name          Input image
03359  * @param  parlist              Shift to apply on the x-axis
03360  * @return CPL_ERROR_NONE on success.
03361  */
03362 
03363 /*---------------------------------------------------------------------------*/
03364     cpl_error_code
03365 detmon_fill_pernoise_params(cpl_parameterlist * parlist,
03366                             const char *recipe_name,
03367                             const char *pipeline_name,
03368                             int mode,
03369                             const char * direction,
03370                             double speed,
03371                             int llx,
03372                             int lly,
03373                             int urx,
03374                             int ury,
03375                             double kappa,
03376                             int exts)
03377 {
03378     detmon_fill_parlist(parlist, recipe_name, pipeline_name, 9,
03379 
03380                         "mode",
03381                         "Mode",
03382                         "CPL_TYPE_INT", mode,
03383 
03384                         "direction",
03385                         "Readout direction",
03386                         "CPL_TYPE_BOOL", direction,
03387 
03388                         "speed",
03389                         "Readout speed",
03390                         "CPL_TYPE_DOUBLE", speed,
03391 
03392                         "llx",
03393                         "(yet unsupported) x coordinate of the lower-left "
03394                         "point of the region of interest. If not modified, default value will be 1.",
03395                         "CPL_TYPE_INT", llx,
03396                         "lly",
03397                         "(yet unsupported) y coordinate of the lower-left "
03398                         "point of the region of interest. If not modified, default value will be 1.",
03399                         "CPL_TYPE_INT", lly,
03400                         "urx",
03401                         "(yet unsupported) x coordinate of the upper-right "
03402                             "point of the region of interest. If not modified, default value will be X dimension of the input image.",
03403                         "CPL_TYPE_INT", urx,
03404                         "ury",
03405                         "(yet unsupported) y coordinate of the upper-right "
03406                             "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
03407                         "CPL_TYPE_INT", ury,
03408 
03409                         "kappa",
03410                         "Kappa used for determining threshold of bad (hot, cold) pixels",
03411                         "CPL_TYPE_DOUBLE", kappa,
03412 
03413                         "exts",
03414                         "Activate the multi-exts option",
03415                         "CPL_TYPE_INT", exts);
03416 
03417     return 0;
03418 }
03419 
03420 /*---------------------------------------------------------------------------*/
03421 
03422 /*
03423  * @brief  Retrieve input parameters
03424  * @param  pipeline_name        Input image
03425  * @param  recipe_name          Input image
03426  * @param  parlist              Shift to apply on the x-axis
03427  * @return CPL_ERROR_NONE on success.
03428  */
03429 
03430 /*---------------------------------------------------------------------------*/
03431 int
03432 detmon_fill_pernoise_params_default(cpl_parameterlist * parlist,
03433                                     const char *recipe_name,
03434                                     const char *pipeline_name)
03435 {
03436     detmon_fill_pernoise_params(parlist, recipe_name, pipeline_name,
03437                                 1,           /* --mode      */
03438                                 "CPL_TRUE",  /* --direction */
03439                                 84.5,        /* --speed     */
03440                                 -1,          /* --llx       */
03441                                 -1,          /* --lly       */
03442                                 -1,          /* --urx       */
03443                                 -1,          /* --ury       */
03444                                 100,          /* --kappa     */
03445                                 0);          /* --exts      */
03446 
03447     return 0;
03448 
03449 }
03450 
03451 
03452 static cpl_error_code
03453 detmon_pernoise_retrieve_parlist(const char *pipeline_name,
03454                                  const char *recipe_name,
03455                                  const cpl_parameterlist * parlist)
03456 {
03457     char                   *par_name;
03458     cpl_parameter          *par;
03459 
03460     /* --mode */
03461     detmon_pernoise_config.mode =
03462         detmon_retrieve_par_int("mode", pipeline_name, recipe_name,
03463                                 parlist);
03464 
03465     /* --direction */
03466     par_name = cpl_sprintf("%s.%s.direction", pipeline_name, recipe_name);
03467     assert(par_name != NULL);
03468     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03469     detmon_pernoise_config.direction = cpl_parameter_get_bool(par);
03470     cpl_free(par_name);
03471 
03472     /* --speed */
03473     par_name = cpl_sprintf("%s.%s.speed", pipeline_name, recipe_name);
03474     assert(par_name != NULL);
03475     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
03476     detmon_pernoise_config.speed = cpl_parameter_get_double(par);
03477     cpl_free(par_name);
03478 
03479     /* --llx */
03480     detmon_pernoise_config.llx =
03481         detmon_retrieve_par_int("llx", pipeline_name, recipe_name,
03482                                 parlist);
03483 
03484     /* --lly */
03485     detmon_pernoise_config.lly =
03486         detmon_retrieve_par_int("lly", pipeline_name, recipe_name,
03487                                 parlist);
03488     /* --urx */
03489     detmon_pernoise_config.urx =
03490         detmon_retrieve_par_int("urx", pipeline_name, recipe_name,
03491                                 parlist);
03492     /* --ury */
03493     detmon_pernoise_config.ury =
03494         detmon_retrieve_par_int("ury", pipeline_name, recipe_name,
03495                                 parlist);
03496     /* --kappa */
03497     detmon_pernoise_config.kappa =
03498         detmon_retrieve_par_double("kappa", pipeline_name, recipe_name,
03499                                    parlist);
03500 
03501     /* --exts */
03502     detmon_pernoise_config.exts =
03503         detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
03504                                 parlist);
03505 
03506     if(cpl_error_get_code()) {
03507         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
03508         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
03509     }
03510 
03511     return cpl_error_get_code();
03512 }
03513 
03514 /*---------------------------------------------------------------------------*/
03515 
03516 /*
03517  * @brief  Retrieve input parameters
03518  * @param  pipeline_name        Input image
03519  * @param  recipe_name          Input image
03520  * @param  parlist              Shift to apply on the x-axis
03521  * @return CPL_ERROR_NONE on success.
03522  */
03523 
03524 /*---------------------------------------------------------------------------*/
03525 static                  cpl_error_code
03526 detmon_pernoise_save(const cpl_parameterlist * parlist,
03527                      cpl_frameset * frameset,
03528                      const char *recipe_name,
03529                      const char *pipeline_name,
03530                      const char *procatg_tbl,
03531                      const char *package,
03532                      cpl_table ** freq_table,
03533                      cpl_propertylist ** qclist,
03534                      const int flag_sets,
03535                      const int which_set,
03536                      const cpl_frameset * usedframes)
03537 {
03538 
03539     cpl_frame              *ref_frame;
03540     cpl_propertylist       *plist;
03541     char                   *name_o = NULL; /* Avoid (false) uninit warning */
03542     int                     i, j;
03543     cpl_propertylist       *paflist;
03544     cpl_error_code          error;
03545 
03546     cpl_propertylist * pro_tbl = cpl_propertylist_new();
03547 
03548     cpl_propertylist_append_string(pro_tbl,
03549                                    CPL_DFS_PRO_CATG, procatg_tbl);
03550 
03551     cpl_propertylist_append(pro_tbl, qclist[0]);
03552 
03553     /*******************************/
03554     /*  Write the FREQ TABLE  */
03555 
03556     /*******************************/
03557 
03558     if(detmon_pernoise_config.mode != 1) {
03559         /* Set the file name for the table */
03560         if(!flag_sets) {
03561             name_o = cpl_sprintf("%s_freq_table.fits", recipe_name);
03562             assert(name_o != NULL);
03563         } else {
03564             name_o =
03565                 cpl_sprintf("%s_freq_table_set%02d.fits", recipe_name,
03566                             which_set);
03567             assert(name_o != NULL);
03568         }
03569 
03570         /* Save the table */
03571         if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, freq_table[0],
03572                               NULL, recipe_name, pro_tbl, NULL,
03573                               package, name_o)) {
03574             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03575             cpl_free(name_o);
03576             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03577         }
03578 
03579         if(detmon_pernoise_config.exts < 0) {
03580 
03581             for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03582                 error =
03583                     cpl_table_save(freq_table[i], NULL, qclist[i], name_o,
03584                                    CPL_IO_EXTEND);
03585                 cpl_ensure_code(!error, error);
03586             }
03587         }
03588 
03589         /* Free */
03590         cpl_free(name_o);
03591 
03592     } else {
03593         for (j = 1; j <= 4; j++) {
03594             /* Set the file name for the table */
03595             if(!flag_sets) {
03596                 name_o = cpl_sprintf("%s_freq_table_quad%02d.fits",
03597                                      recipe_name, j);
03598                 assert(name_o != NULL);
03599             } else {
03600                 name_o =
03601                     cpl_sprintf("%s_freq_table_quad%02d_set%02d.fits",
03602                                 recipe_name, j, which_set);
03603                 assert(name_o != NULL);
03604             }
03605 
03606             /* Save the table */
03607             if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
03608                                   freq_table[j - 1],
03609                                   NULL, recipe_name, pro_tbl, NULL,
03610                                   package, name_o)) {
03611                 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03612                 cpl_free(name_o);
03613                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03614             }
03615 
03616             if(detmon_pernoise_config.exts < 0) {
03617                 for(i = 1; i < detmon_pernoise_config.nb_extensions; i++) {
03618                     error = cpl_table_save(freq_table[(j-1) + 4 * i],
03619                                            NULL, qclist[i], name_o,
03620                                            CPL_IO_EXTEND);
03621                     cpl_ensure_code(!error, error);
03622                 }
03623             }
03624 
03625             /* Free */
03626             cpl_free(name_o);
03627         }
03628 
03629     }
03630     /*******************************/
03631     /*  Write the PAF file(s)      */
03632     /*******************************/
03633 
03634     /* Get FITS header from reference file */
03635     ref_frame = cpl_frameset_get_first(frameset);
03636     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03637                                       0)) == NULL) {
03638         cpl_msg_error(cpl_func, "getting header from reference frame");
03639         cpl_ensure_code(0, cpl_error_get_code());
03640     }
03641 
03642     /* Get the keywords for the paf file */
03643     paflist = cpl_propertylist_new();
03644     cpl_propertylist_copy_property_regexp(paflist, plist,
03645                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
03646                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
03647                                           "ESO DET NCORRS|"
03648                                           "ESO DET MODE NAME)$", 0);
03649 
03650     for(i = 0; i < detmon_pernoise_config.nb_extensions; i++) {
03651         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
03652         error = cpl_propertylist_append(c_paflist, qclist[i]);
03653         cpl_ensure_code(!error, error);
03654 
03655         /* Set the file name for the bpm */
03656         if(detmon_pernoise_config.exts >= 0) {
03657             if(!flag_sets) {
03658                 name_o = cpl_sprintf("%s.paf", recipe_name);
03659                 assert(name_o != NULL);
03660             } else {
03661                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
03662                 assert(name_o != NULL);
03663             }
03664         } else {
03665             if(!flag_sets) {
03666                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
03667                 assert(name_o != NULL);
03668             } else {
03669                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
03670                 assert(name_o != NULL);
03671             }
03672         }
03673         /* Save the PAF */
03674         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
03675             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
03676             cpl_free(name_o);
03677             cpl_propertylist_delete(paflist);
03678             cpl_propertylist_delete(plist);
03679             cpl_free(name_o);
03680             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
03681         }
03682         cpl_propertylist_delete(c_paflist);
03683         cpl_free(name_o);
03684     }
03685 
03686     cpl_propertylist_delete(plist);
03687     cpl_propertylist_delete(paflist);
03688     cpl_propertylist_delete(pro_tbl);
03689     return cpl_error_get_code();
03690 }
03691 
03692 static cpl_error_code
03693 detmon_pernoise_qc(cpl_propertylist * qclist,
03694                    cpl_table * table,
03695                    int iquad)
03696 {
03697     cpl_error_code error;
03698     char * propname;
03699 
03700     double freqs[3] = {0, 0, 0};
03701     double pows[3] = {0, 0, 0};
03702 
03703     /*    error = cpl_propertylist_append_bool(reflist, "POW", TRUE);
03704           cpl_ensure_code(!error, error);
03705 
03706           error = cpl_table_sort(table, reflist);
03707           cpl_ensure_code(!error, error);
03708           */
03709 
03710     int nrows = cpl_table_get_nrow(table);
03711     int i;
03712 
03713     double * all_freqs = cpl_table_get_data_double(table, "FREQ");
03714     double * all_pows  = cpl_table_get_data_double(table, "POW");
03715 
03716     for ( i= 1; i< nrows-1; i++){
03717         if (all_pows[i] > pows[0]) {
03718             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03719                 pows[2]=pows[1];
03720                 pows[1]=pows[0];
03721                 pows[0]=all_pows[i];
03722 
03723                 freqs[2]=freqs[1];
03724                 freqs[1]=freqs[0];
03725                 freqs[0]=all_freqs[i];
03726             }
03727         } else if (all_pows[i] > pows[1]) {
03728             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03729                 pows[2]=pows[1];
03730                 pows[1]=all_pows[i];
03731 
03732                 freqs[2]=freqs[1];
03733                 freqs[1]=all_freqs[i];
03734             }
03735 
03736         } else if(all_pows[i] > pows[2]) {
03737             if(all_pows[i-1] < all_pows[i] && all_pows[i] > all_pows[i+1]){
03738                 pows[2]=all_pows[i];
03739 
03740                 freqs[2]=all_freqs[i];
03741             }
03742 
03743         }
03744     }
03745 
03746     if (detmon_pernoise_config.mode == 1) {
03747         propname = cpl_sprintf("ESO QC FREQ1 %d", iquad);
03748         assert(propname != NULL);
03749     } else {
03750         propname = cpl_sprintf("ESO QC FREQ1");
03751     }
03752 
03753     error = cpl_propertylist_append_double(qclist, propname, freqs[0]);
03754     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
03755     cpl_ensure_code(!error, error);
03756 
03757     cpl_free(propname);
03758 
03759     if (detmon_pernoise_config.mode == 1) {
03760         propname = cpl_sprintf("ESO QC FREQ2 %d", iquad);
03761         assert(propname != NULL);
03762     } else {
03763         propname = cpl_sprintf("ESO QC FREQ2");
03764     }
03765 
03766     error = cpl_propertylist_append_double(qclist, propname, freqs[1]);
03767     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
03768     cpl_ensure_code(!error, error);
03769 
03770     cpl_free(propname);
03771 
03772     if (detmon_pernoise_config.mode == 1) {
03773         propname = cpl_sprintf("ESO QC FREQ3 %d", iquad);
03774         assert(propname != NULL);
03775     } else {
03776         propname = cpl_sprintf("ESO QC FREQ3");
03777     }
03778 
03779     error = cpl_propertylist_append_double(qclist, propname, freqs[2]);
03780     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_FREQ_C);
03781     cpl_ensure_code(!error, error);
03782 
03783     cpl_free(propname);
03784 
03785     if (detmon_pernoise_config.mode == 1) {
03786         propname = cpl_sprintf("ESO QC POW1 %d", iquad);
03787         assert(propname != NULL);
03788     } else {
03789         propname = cpl_sprintf("ESO QC POW1");
03790     }
03791 
03792     error = cpl_propertylist_append_double(qclist, propname, pows[0]);
03793     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
03794     cpl_ensure_code(!error, error);
03795 
03796     cpl_free(propname);
03797 
03798     if (detmon_pernoise_config.mode == 1) {
03799         propname = cpl_sprintf("ESO QC POW2 %d", iquad);
03800         assert(propname != NULL);
03801     } else {
03802         propname = cpl_sprintf("ESO QC POW2");
03803     }
03804 
03805     error = cpl_propertylist_append_double(qclist, propname, pows[1]);
03806     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
03807     cpl_ensure_code(!error, error);
03808 
03809     cpl_free(propname);
03810 
03811     if (detmon_pernoise_config.mode == 1) {
03812         propname = cpl_sprintf("ESO QC POW3 %d", iquad);
03813         assert(propname != NULL);
03814     } else {
03815         propname = cpl_sprintf("ESO QC POW3");
03816     }
03817 
03818     error = cpl_propertylist_append_double(qclist, propname, pows[2]);
03819     error = cpl_propertylist_set_comment(qclist,propname,DETMON_QC_POW_C);
03820     cpl_ensure_code(!error, error);
03821 
03822 
03823     cpl_free(propname);
03824 
03825     return cpl_error_get_code();
03826 }
03827 
03828 /*---------------------------------------------------------------------------*/
03829 
03830 /*
03831  * @brief  Retrieve input parameters
03832  * @param  pipeline_name        Input image
03833  * @param  recipe_name          Input image
03834  * @param  parlist              Shift to apply on the x-axis
03835  * @return CPL_ERROR_NONE on success.
03836  */
03837 
03838 /*---------------------------------------------------------------------------*/
03839 cpl_error_code
03840 detmon_pernoise_rm_bg(cpl_image * image, int nsamples, int nffts)
03841 {
03842     cpl_vector             *values = cpl_vector_new(nsamples * nffts);
03843 
03844     int                     rejected;
03845     int i, j;
03846     cpl_vector *xy_pos = cpl_vector_new(nsamples * nffts * 2);
03847     cpl_polynomial * poly_2d = 0;
03848     cpl_image * poly_ima = 0;
03849     cpl_size degree = 3;
03850     cpl_error_code error = CPL_ERROR_NONE;
03851     cpl_matrix * samppos = 0;
03852 
03853     for(i = 1; i <= nffts; i++) {
03854         for(j = 1; j <= nsamples; j++) {
03855             cpl_vector_set(xy_pos, (i - 1) * nsamples + (j - 1), j);
03856             cpl_vector_set(xy_pos, (i - 1) * nsamples + (j - 1) + nsamples * nffts, i);
03857             cpl_vector_set(values, (i - 1) * nsamples + (j - 1),
03858                            cpl_image_get(image, j, i, &rejected));
03859             error = cpl_error_get_code();
03860             if (error != CPL_ERROR_NONE)
03861             {
03862                 break;
03863             }
03864         }
03865         if (error != CPL_ERROR_NONE)
03866         {
03867             break;
03868         }
03869     }
03870     if (error != CPL_ERROR_NONE)
03871     {
03872         goto cleanup;
03873     }
03874 
03875     poly_2d = cpl_polynomial_new(2);
03876     samppos =
03877         cpl_matrix_wrap(2, nsamples * nffts, cpl_vector_get_data(xy_pos));
03878 
03879     cpl_polynomial_fit(poly_2d, samppos, NULL, values, NULL,
03880                        CPL_FALSE, NULL, &degree);
03881 
03882     cpl_matrix_unwrap(samppos);
03883 
03884     poly_ima = cpl_image_new(nsamples, nffts, CPL_TYPE_FLOAT);
03885 
03886     cpl_image_fill_polynomial(poly_ima, poly_2d, 1, 1, 1, 1);
03887 
03888     cpl_image_subtract(image, poly_ima);
03889 
03890 cleanup:
03891     cpl_polynomial_delete(poly_2d);
03892     cpl_image_delete(poly_ima);
03893     cpl_vector_delete(xy_pos);
03894     cpl_vector_delete(values);
03895 
03896     return cpl_error_get_code();
03897 }
03898 
03899 /*---------------------------------------------------------------------------*/
03900 
03901 /*
03902  * @brief  Retrieve input parameters
03903  * @param  pipeline_name        Input image
03904  * @param  recipe_name          Input image
03905  * @param  parlist              Shift to apply on the x-axis
03906  * @return CPL_ERROR_NONE on success.
03907  */
03908 
03909 /*---------------------------------------------------------------------------*/
03910 cpl_error_code
03911 detmon_dark(cpl_frameset      * frameset,
03912             const cpl_parameterlist * parlist,
03913             const char        * tag,
03914             const char        * recipe_name,
03915             const char        * pipeline_name,
03916             const char        * procatg_master,
03917             const char        * procatg_dsnu,
03918             const char        * procatg_tbl,
03919             const char        * package,
03920             int              (*compare)(const cpl_frame *,
03921                                         const cpl_frame *))
03922 {
03923     cpl_size                     nsets;
03924     cpl_size                    *selection = NULL;
03925     int                     i;
03926     cpl_error_code          error;
03927 
03928     if(detmon_dark_dfs_set_groups(frameset, tag)) {
03929         cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
03930     }
03931 
03932     /*
03933      * This function reads all inputs parameters from parlist
03934      * and stores them in a global variable detmon_ronbias_config.
03935      * Similar to detmon_lg_retrieve_parlist(). See detmon.c
03936      */
03937     error = detmon_retrieve_dark_params(pipeline_name,
03938                                         recipe_name, parlist);
03939     cpl_ensure_code(!error, error);
03940 
03941     /* Labelise all input frames */
03942     if(compare == NULL)
03943         nsets = 1;
03944     else {
03945         cpl_msg_info(cpl_func, "Identify the different settings");
03946         selection = cpl_frameset_labelise(frameset, compare, &nsets);
03947         if(selection == NULL)
03948             cpl_msg_error(cpl_func, "Cannot labelise input frames");
03949     }
03950 
03951     detmon_dark_config.nb_extensions = 1;
03952     if(detmon_dark_config.exts < 0) {
03953         const cpl_frame        *cur_frame =
03954             cpl_frameset_get_first_const(frameset);
03955         /* Get the nb of extensions */
03956         detmon_dark_config.nb_extensions =
03957             cpl_frame_get_nextensions(cur_frame);
03958     }
03959 
03960     /* Extract settings and reduce each of them */
03961     for(i = 0; i < nsets; i++) {
03962         cpl_size                    *select_dits = NULL;
03963         cpl_frameset           *cur_fset =
03964             nsets == 1 ? cpl_frameset_duplicate(frameset) :
03965             cpl_frameset_extract(frameset, selection, i);
03966 
03967         cpl_size                     ndits = 0;
03968         int                     j, k;
03969         cpl_table ** dsnu_table = NULL;
03970         cpl_imagelist ** dsnu = NULL;
03971 
03972         cpl_propertylist ** qclist =
03973             (cpl_propertylist **)
03974             cpl_malloc(detmon_dark_config.nb_extensions *
03975                        sizeof(cpl_propertylist *));
03976 
03977 
03978         cpl_imagelist ** masters =
03979             (cpl_imagelist **)
03980             cpl_malloc(detmon_dark_config.nb_extensions *
03981                        sizeof(cpl_imagelist *));
03982 
03983         /* Initialise memory for products */
03984         if(detmon_dark_config.opt_nir == OPT) {
03985             dsnu_table =
03986                 (cpl_table **) cpl_malloc(detmon_dark_config.nb_extensions *
03987                                           sizeof(cpl_table *));
03988             dsnu =
03989                 (cpl_imagelist **)
03990                 cpl_malloc(detmon_dark_config.nb_extensions *
03991                            sizeof(cpl_imagelist *));
03992         }
03993 
03994         select_dits = cpl_frameset_labelise(cur_fset,
03995                                             detmon_compare_dits,
03996                                             &ndits);
03997 
03998         if(detmon_dark_config.exts >= 0) {
03999             *masters = cpl_imagelist_new();
04000             if(detmon_dark_config.opt_nir == OPT) {
04001                 *dsnu = cpl_imagelist_new();
04002                 *dsnu_table = cpl_table_new(ndits);
04003             }
04004             *qclist = cpl_propertylist_new();
04005             cpl_table_new_column(*dsnu_table, "DIT", CPL_TYPE_DOUBLE);
04006             cpl_table_new_column(*dsnu_table, "STDEV", CPL_TYPE_DOUBLE);
04007         } else {
04008             for ( j = 0; j < detmon_dark_config.nb_extensions; j ++) {
04009                 masters[j] = cpl_imagelist_new();
04010                 if(detmon_dark_config.opt_nir == OPT) {
04011                     dsnu[j] = cpl_imagelist_new();
04012                     dsnu_table[j] = cpl_table_new(ndits);
04013                 }
04014                 qclist[j] = cpl_propertylist_new();
04015                 cpl_table_new_column(dsnu_table[j], "DIT", CPL_TYPE_DOUBLE);
04016                 cpl_table_new_column(dsnu_table[j], "STDEV", CPL_TYPE_DOUBLE);
04017             }
04018         }
04019 
04020         for(j = 0; j < ndits; j++) {
04021             cpl_frameset  * cur_fdit = cpl_frameset_extract(cur_fset,
04022                                                             select_dits, j);
04023             cpl_imagelist ** raws =
04024                 (cpl_imagelist **)
04025                 cpl_malloc(detmon_dark_config.nb_extensions *
04026                            sizeof(cpl_imagelist *));
04027 
04028             if(detmon_dark_config.exts >= 0) {
04029                 cpl_image * collapsed;
04030                 *raws =
04031                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
04032                                                 detmon_dark_config.exts);
04033                 collapsed = cpl_imagelist_collapse_create(*raws);
04034                 cpl_imagelist_set(*masters, collapsed, j);
04035                 if(detmon_dark_config.opt_nir == OPT) {
04036                     detmon_dark_dsnu(cur_fdit, *dsnu, *dsnu_table,
04037                                      collapsed, j);
04038                 }
04039                 detmon_dark_qc(*qclist, collapsed);
04040             } else {
04041                 cpl_imagelist          *raws_all_exts =
04042                     cpl_imagelist_load_frameset(cur_fdit, CPL_TYPE_FLOAT, 1,
04043                                                 -1);
04044                 for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
04045                     int nframes = cpl_frameset_get_size(cur_fdit);
04046                     int h;
04047                     cpl_image * collapsed;
04048                     for(h = 0; h < nframes; h++) {
04049                         cpl_image              *image =
04050                             cpl_imagelist_unset(raws_all_exts,
04051                                                 (detmon_dark_config.
04052                                                  nb_extensions - 1 - k) * h);
04053                         cpl_imagelist_set(raws[k], image, h);
04054                     }
04055                     collapsed = cpl_imagelist_collapse_create(raws[k]);
04056                     cpl_imagelist_set(masters[k],collapsed, j);
04057                     if(detmon_dark_config.opt_nir == OPT) {
04058                         detmon_dark_dsnu(cur_fdit, dsnu[k],
04059                                          dsnu_table[j], collapsed, j);
04060                     }
04061                     detmon_dark_qc(qclist[k], collapsed);
04062                 }
04063             }
04064 
04065             cpl_frameset_delete(cur_fdit);
04066             for(k = 0; k < detmon_dark_config.nb_extensions; k++) {
04067                 cpl_imagelist_delete(raws[k]);
04068             }
04069             cpl_free(raws);
04070         } /* end of loop (for) around different DIT values */
04071 
04072         cpl_frameset_delete(cur_fset);
04073 
04074         detmon_dark_save(parlist, frameset, recipe_name, pipeline_name,
04075                          procatg_master, procatg_tbl, procatg_dsnu,
04076                          package, masters, dsnu_table, dsnu, qclist,
04077                          0, 0, frameset);
04078 
04079         if(detmon_dark_config.opt_nir == OPT) {
04080             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04081                 cpl_table_delete(dsnu_table[j]);
04082                 cpl_imagelist_delete(dsnu[j]);
04083             }
04084             cpl_free(dsnu_table);
04085             cpl_free(dsnu);
04086         }
04087 
04088         for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04089             cpl_propertylist_delete(qclist[j]);
04090             cpl_imagelist_delete(masters[j]);
04091         }
04092         cpl_free(qclist);
04093         cpl_free(masters);
04094         cpl_free(select_dits);
04095 
04096     } /* end of loop (for) around different setting */
04097 
04098     cpl_free(selection);
04099 
04100     return cpl_error_get_code();
04101 }
04102 
04103 
04104 /*---------------------------------------------------------------------------*/
04105 
04106 /*
04107  * @brief  Retrieve input parameters
04108  * @param  pipeline_name        Input image
04109  * @param  recipe_name          Input image
04110  * @param  parlist              Shift to apply on the x-axis
04111  * @return CPL_ERROR_NONE on success.
04112  */
04113 
04114 /*---------------------------------------------------------------------------*/
04115 int
04116 detmon_dark_dfs_set_groups(cpl_frameset * set, const char *tag)
04117 {
04118     cpl_frame              *cur_frame;
04119     const char             *cur_tag;
04120     int                     nframes;
04121     int                     i;
04122 
04123     /* Check entries */
04124     if(set == NULL)
04125         return -1;
04126 
04127     /* Initialize */
04128     nframes = cpl_frameset_get_size(set);
04129 
04130     /* Loop on frames */
04131     for(i = 0; i < nframes; i++) {
04132         cur_frame = cpl_frameset_get_frame(set, i);
04133         cur_tag = cpl_frame_get_tag(cur_frame);
04134 
04135         /* RAW frames */
04136         if(!strcmp(cur_tag, tag))
04137             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
04138         /* CALIB frames */
04139 
04140         /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
04141                   cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB) ;
04142                   */
04143     }
04144     return 0;
04145 }
04146 
04147 /*---------------------------------------------------------------------------*/
04148 
04149 /*
04150  * @brief  Retrieve input parameters
04151  * @param  pipeline_name        Input image
04152  * @param  recipe_name          Input image
04153  * @param  parlist              Shift to apply on the x-axis
04154  * @return CPL_ERROR_NONE on success.
04155  */
04156 
04157 /*---------------------------------------------------------------------------*/
04158 static                  cpl_error_code
04159 detmon_retrieve_dark_params(const char *pipeline_name,
04160                             const char *recipe_name,
04161                             const cpl_parameterlist * parlist)
04162 {
04163     char                   *par_name;
04164     cpl_parameter          *par;
04165 
04166     /* --ron.method */
04167     par_name = cpl_sprintf("%s.%s.ron.method", pipeline_name, recipe_name);
04168     assert(par_name != NULL);
04169     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04170     detmon_dark_config.ron_method = cpl_parameter_get_string(par);
04171     cpl_free(par_name);
04172 
04173     /* --dsnu.method */
04174     par_name = cpl_sprintf("%s.%s.dsnu.method", pipeline_name, recipe_name);
04175     assert(par_name != NULL);
04176     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04177     detmon_dark_config.dsnu_method = cpl_parameter_get_string(par);
04178     cpl_free(par_name);
04179 
04180     /* --opt_nir */
04181     par_name = cpl_sprintf("%s.%s.opt_nir", pipeline_name, recipe_name);
04182     assert(par_name != NULL);
04183     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
04184     detmon_dark_config.opt_nir = cpl_parameter_get_bool(par);
04185     cpl_free(par_name);
04186 
04187     /* --exts */
04188     detmon_dark_config.exts =
04189         detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
04190                                 parlist);
04191 
04192     if(cpl_error_get_code()) {
04193         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
04194         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
04195     }
04196 
04197 
04198     return CPL_ERROR_NONE;
04199 }
04200 
04201 
04202 /*---------------------------------------------------------------------------*/
04203 
04204 /*
04205  * @brief  Retrieve input parameters
04206  * @param  pipeline_name        Input image
04207  * @param  recipe_name          Input image
04208  * @param  parlist              Shift to apply on the x-axis
04209  * @return CPL_ERROR_NONE on success.
04210  */
04211 
04212 /*---------------------------------------------------------------------------*/
04213     cpl_error_code
04214 detmon_fill_dark_params(cpl_parameterlist * parlist,
04215                         const char *recipe_name,
04216                         const char *pipeline_name,
04217                         const char * ron_method,
04218                         const char * dsnu_method,
04219                         const char * opt_nir,
04220                         int exts)
04221 {
04222     detmon_fill_parlist(parlist, recipe_name, pipeline_name, 4,
04223 
04224                         "ron.method",
04225                         "Method used to compute RON. Currently no "
04226                         "change is possible, RMS computed",
04227                         "CPL_TYPE_STRING", ron_method,
04228 
04229                         "dsnu.method",
04230                         "Method used to compute DSNU map. Currently no "
04231                         "change is possible. Method used STDEV",
04232                         "CPL_TYPE_STRING", dsnu_method,
04233 
04234                         "opt_nir",
04235                         "Boolean, OPT (FALSE) or NIR(TRUE)",
04236                         "CPL_TYPE_BOOL", opt_nir,
04237 
04238                         "exts",
04239                         "Activate the multi-exts option. Default 0"
04240                         "(primary unit), -1 (all exts)",
04241                         "CPL_TYPE_INT", exts);
04242 
04243     return cpl_error_get_code();
04244 }
04245 
04246 /*---------------------------------------------------------------------------*/
04247 
04248 /*
04249  * @brief  Retrieve input parameters
04250  * @param  pipeline_name        Input image
04251  * @param  recipe_name          Input image
04252  * @param  parlist              Shift to apply on the x-axis
04253  * @return CPL_ERROR_NONE on success.
04254  */
04255 
04256 /*---------------------------------------------------------------------------*/
04257 int
04258 detmon_fill_dark_params_default(cpl_parameterlist * parlist,
04259                                 const char *recipe_name,
04260                                 const char *pipeline_name)
04261 {
04262     detmon_fill_dark_params(parlist, recipe_name, pipeline_name,
04263                             "SIMPLE", /* --ron.method  */
04264                             "STDEV",  /* --dsnu.method */
04265                             "CPL_FALSE",  /* OPT*/
04266                             0);       /* --exts        */
04267     return cpl_error_get_code();
04268 }
04269 
04270 /*---------------------------------------------------------------------------*/
04271 
04272 /*
04273  * @brief  Retrieve input parameters
04274  * @param  pipeline_name        Input image
04275  * @param  recipe_name          Input image
04276  * @param  parlist              Shift to apply on the x-axis
04277  * @return CPL_ERROR_NONE on success.
04278  */
04279 
04280 /*---------------------------------------------------------------------------*/
04281 cpl_error_code
04282 detmon_dark_dsnu(cpl_frameset * cur_fdit,
04283                  cpl_imagelist * dsnu,
04284                  cpl_table * dsnu_table,
04285                  cpl_image * collapsed,
04286                  int pos)
04287 {
04288     cpl_frame * first = cpl_frameset_get_first(cur_fdit);
04289     cpl_propertylist * plist =
04290         cpl_propertylist_load(cpl_frame_get_filename(first), 0);
04291     double dit = irplib_pfits_get_exptime(plist);
04292     double mean = cpl_image_get_mean(collapsed);
04293 
04294     cpl_image * dsnu_map =
04295         cpl_image_subtract_scalar_create(collapsed, mean);
04296     double stdev;
04297     cpl_image_divide_scalar(dsnu_map, mean);
04298     stdev = cpl_image_get_stdev(dsnu_map);
04299 
04300     cpl_imagelist_set(dsnu, dsnu_map, pos);
04301 
04302     cpl_table_set(dsnu_table, "DIT", pos, dit);
04303     cpl_table_set(dsnu_table, "STDEV", pos, stdev);
04304 
04305     cpl_propertylist_delete(plist);
04306 
04307     return cpl_error_get_code();
04308 
04309 }
04310 
04311 /*---------------------------------------------------------------------------*/
04312 
04313 /*
04314  * @brief  Retrieve input parameters
04315  * @param  pipeline_name        Input image
04316  * @param  recipe_name          Input image
04317  * @param  parlist              Shift to apply on the x-axis
04318  * @return CPL_ERROR_NONE on success.
04319  */
04320 
04321 /*---------------------------------------------------------------------------*/
04322 static                  cpl_error_code
04323 detmon_dark_save(const cpl_parameterlist * parlist,
04324                  cpl_frameset * frameset,
04325                  const char *recipe_name,
04326                  const char *pipeline_name,
04327                  const char *procatg_master,
04328                  const char *procatg_tbl,
04329                  const char *procatg_dsnu,
04330                  const char *package,
04331                  cpl_imagelist ** masters,
04332                  cpl_table ** dsnu_table,
04333                  cpl_imagelist ** dsnu,
04334                  cpl_propertylist ** qclist,
04335                  const int flag_sets,
04336                  const int which_set,
04337                  const cpl_frameset * usedframes)
04338 {
04339 
04340     cpl_frame              *ref_frame;
04341     cpl_propertylist       *plist;
04342     char                   *name_o = NULL; /* Avoid (false) uninit warning */
04343     int                     i, j;
04344     cpl_propertylist       *paflist;
04345     cpl_error_code          error;
04346     int nb_images;
04347 
04348     /***************************/
04349     /*  Write the MASTER FITS  */
04350     /***************************/
04351 
04352     nb_images = cpl_imagelist_get_size(masters[0]);
04353     cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
04354 
04355 
04356     for(i = 0; i < nb_images; i++) {
04357         /* Set the file name for each image */
04358         if(!flag_sets) {
04359             name_o =
04360                 cpl_sprintf("%s_master_dit_%d.fits", recipe_name, i+1);
04361             assert(name_o != NULL);
04362         } else {
04363             name_o =
04364                 cpl_sprintf("%s_master_dit_%d_set%02d.fits",
04365                             recipe_name, i, which_set);
04366             assert(name_o != NULL);
04367         }
04368 
04369 
04370         /* Save the image */
04371         if(detmon_dark_config.exts >= 0) {
04372             cpl_propertylist * pro_master = cpl_propertylist_new();
04373 
04374             cpl_propertylist_append_string(pro_master,
04375                                            CPL_DFS_PRO_CATG, procatg_master);
04376 
04377             cpl_propertylist_append(pro_master, qclist[0]);
04378 
04379             if(cpl_dfs_save_image
04380                (frameset, NULL, parlist, usedframes, NULL,
04381                 cpl_imagelist_get(*masters, i), CPL_BPP_IEEE_FLOAT,
04382                 recipe_name, pro_master, NULL, package,
04383                 name_o)) {
04384                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04385                               name_o);
04386                 cpl_free(name_o);
04387                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04388 
04389             }
04390 
04391             cpl_propertylist_delete(pro_master);
04392         } else {
04393             cpl_propertylist * pro_master = cpl_propertylist_new();
04394 
04395             cpl_propertylist_append_string(pro_master,
04396                                            CPL_DFS_PRO_CATG, procatg_master);
04397 
04398             cpl_propertylist_append(pro_master, qclist[0]);
04399 
04400             if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
04401                                   NULL, CPL_BPP_IEEE_FLOAT, recipe_name,
04402                                   pro_master, NULL,
04403                                   package, name_o)) {
04404                 cpl_msg_error(cpl_func, "Cannot save the product: %s",
04405                               name_o);
04406                 cpl_free(name_o);
04407                 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04408             }
04409 
04410             cpl_propertylist_delete(pro_master);
04411             for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04412                 error =
04413                     cpl_image_save(cpl_imagelist_get(masters[j], i),
04414                                    name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04415                                    CPL_IO_EXTEND);
04416                 cpl_ensure_code(!error, error);
04417             }
04418         }
04419         cpl_free(name_o);
04420     }
04421 
04422     if (detmon_dark_config.opt_nir == OPT) {
04423         cpl_propertylist * pro_tbl = cpl_propertylist_new();
04424 
04425         cpl_propertylist_append_string(pro_tbl,
04426                                        CPL_DFS_PRO_CATG, procatg_tbl);
04427 
04428         cpl_propertylist_append(pro_tbl, qclist[0]);
04429         /*******************************/
04430         /*  Write the LINEARITY TABLE  */
04431         /*******************************/
04432 
04433         /* Set the file name for the table */
04434         if(!flag_sets) {
04435             name_o = cpl_sprintf("%s_dsnu_table.fits", recipe_name);
04436             assert(name_o != NULL);
04437         } else {
04438             name_o =
04439                 cpl_sprintf("%s_dsnu_table_set%02d.fits", recipe_name,
04440                             which_set);
04441             assert(name_o != NULL);
04442         }
04443         /* Save the table */
04444         if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
04445                               dsnu_table[0], NULL, recipe_name, pro_tbl, NULL,
04446                               package, name_o)) {
04447             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04448             cpl_free(name_o);
04449             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04450         }
04451 
04452         cpl_propertylist_delete(pro_tbl);
04453 
04454         if(detmon_dark_config.exts < 0) {
04455 
04456             for(i = 1; i < detmon_dark_config.nb_extensions; i++) {
04457                 error =
04458                     cpl_table_save(dsnu_table[i], NULL, qclist[i], name_o,
04459                                    CPL_IO_EXTEND);
04460                 cpl_ensure_code(!error, error);
04461             }
04462         }
04463 
04464         /* Free */
04465         cpl_free(name_o);
04466 
04467         /***************************/
04468         /*  Write the DSNU_MAP FITS  */
04469         /***************************/
04470 
04471         for(i = 0; i < nb_images; i++) {
04472             /* Set the file name for each image */
04473             if(!flag_sets) {
04474                 name_o =
04475                     cpl_sprintf("%s_dsnu_map_dit_%d.fits", recipe_name, i+1);
04476                 assert(name_o != NULL);
04477             } else {
04478                 name_o =
04479                     cpl_sprintf("%s_dsnu_map_dit_%d_set%02d.fits",
04480                                 recipe_name, i, which_set);
04481                 assert(name_o != NULL);
04482             }
04483 
04484 
04485             /* Save the image */
04486             if(detmon_dark_config.exts >= 0) {
04487                 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
04488 
04489                 cpl_propertylist_append_string(pro_dsnu,
04490                                                CPL_DFS_PRO_CATG, procatg_dsnu);
04491 
04492                 cpl_propertylist_append(pro_dsnu, qclist[0]);
04493 
04494                 if(cpl_dfs_save_image
04495                    (frameset, NULL, parlist, usedframes, NULL,
04496                     cpl_imagelist_get(*dsnu, i), CPL_BPP_IEEE_FLOAT,
04497                     recipe_name, pro_dsnu, NULL, package,
04498                     name_o)) {
04499                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04500                                   name_o);
04501                     cpl_free(name_o);
04502                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04503 
04504                 }
04505 
04506                 cpl_propertylist_delete(pro_dsnu);
04507             } else {
04508                 cpl_propertylist * pro_dsnu = cpl_propertylist_new();
04509 
04510                 cpl_propertylist_append_string(pro_dsnu,
04511                                                CPL_DFS_PRO_CATG, procatg_dsnu);
04512 
04513                 cpl_propertylist_append(pro_dsnu, qclist[0]);
04514 
04515                 if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
04516                                       NULL, NULL,
04517                                       CPL_BPP_IEEE_FLOAT, recipe_name,
04518                                       pro_dsnu, NULL,
04519                                       package, name_o)) {
04520                     cpl_msg_error(cpl_func, "Cannot save the product: %s",
04521                                   name_o);
04522                     cpl_free(name_o);
04523                     cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04524                 }
04525 
04526                 cpl_propertylist_delete(pro_dsnu);
04527                 for(j = 0; j < detmon_dark_config.nb_extensions; j++) {
04528                     error =
04529                         cpl_image_save(cpl_imagelist_get(dsnu[j], i),
04530                                        name_o, CPL_BPP_IEEE_FLOAT, qclist[j],
04531                                        CPL_IO_EXTEND);
04532                     cpl_ensure_code(!error, error);
04533                 }
04534             }
04535             cpl_free(name_o);
04536         }
04537 
04538 
04539 
04540     } /* End of if(OPT) */
04541 
04542     /*******************************/
04543     /*  Write the PAF file(s)      */
04544     /*******************************/
04545 
04546     /* Get FITS header from reference file */
04547     ref_frame = cpl_frameset_get_first(frameset);
04548     if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04549                                       0)) == NULL) {
04550         cpl_msg_error(cpl_func, "getting header from reference frame");
04551         cpl_ensure_code(0, cpl_error_get_code());
04552     }
04553 
04554     /* Get the keywords for the paf file */
04555     paflist = cpl_propertylist_new();
04556     cpl_propertylist_copy_property_regexp(paflist, plist,
04557                                           "^(ARCFILE|MJD-OBS|ESO TPL ID|"
04558                                           "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
04559                                           "ESO DET NCORRS|"
04560                                           "ESO DET MODE NAME)$", 0);
04561 
04562     for(i = 0; i < detmon_dark_config.nb_extensions; i++) {
04563         cpl_propertylist * c_paflist = cpl_propertylist_duplicate(paflist);
04564         error = cpl_propertylist_append(c_paflist, qclist[i]);
04565         cpl_ensure_code(!error, error);
04566 
04567         /* Set the file name for the bpm */
04568         if(detmon_dark_config.exts >= 0) {
04569             if(!flag_sets) {
04570                 name_o = cpl_sprintf("%s.paf", recipe_name);
04571                 assert(name_o != NULL);
04572             } else {
04573                 name_o = cpl_sprintf("%s_set%02d.paf", recipe_name, which_set);
04574                 assert(name_o != NULL);
04575             }
04576         } else {
04577             if(!flag_sets) {
04578                 name_o = cpl_sprintf("%s_ext%02d.paf", recipe_name, i+1);
04579                 assert(name_o != NULL);
04580             } else {
04581                 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf", recipe_name, which_set, i+1);
04582                 assert(name_o != NULL);
04583             }
04584         }
04585         /* Save the PAF */
04586         if(cpl_dfs_save_paf(pipeline_name, recipe_name, c_paflist, name_o)) {
04587             cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
04588             cpl_free(name_o);
04589             cpl_propertylist_delete(paflist);
04590             cpl_propertylist_delete(plist);
04591             cpl_free(name_o);
04592             cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
04593         }
04594         cpl_propertylist_delete(c_paflist);
04595         cpl_free(name_o);
04596     }
04597 
04598     cpl_propertylist_delete(plist);
04599     cpl_propertylist_delete(paflist);
04600 
04601     return cpl_error_get_code();
04602 }
04603 
04604 cpl_error_code
04605 detmon_dark_qc(cpl_propertylist * qclist,
04606                cpl_image * collapsed)
04607 {
04608     double mean = cpl_image_get_mean(collapsed);
04609     double stdev = cpl_image_get_stdev(collapsed);
04610 
04611     cpl_error_code error;
04612 
04613     error = cpl_propertylist_append_double(qclist,DETMON_QC_DARK, mean);
04614     error = cpl_propertylist_set_comment(qclist,DETMON_QC_DARK,
04615                                          DETMON_QC_DARK_C);
04616     cpl_ensure_code(!error, error);
04617 
04618     error = cpl_propertylist_append_double(qclist,DETMON_QC_DARK_STDEV, stdev);
04619     error = cpl_propertylist_set_comment(qclist,DETMON_QC_DARK_STDEV,
04620                                          DETMON_QC_DARK_STDEV_C);
04621     cpl_ensure_code(!error, error);
04622 
04623     return cpl_error_get_code();
04624 }
04625 
04626 
04627 /*---------------------------------------------------------------------------*/
04644 /*---------------------------------------------------------------------------*/
04645 cpl_image *
04646 irplib_imagelist_collapse_stdev_create(const cpl_imagelist * imlist)
04647 {
04648     cpl_image          *    mean;
04649     cpl_image          *    delta;
04650     cpl_image          *    sq_delta;
04651     cpl_image          *    stdev;
04652 
04653     int                     i;
04654 
04655     /* Check inputs */
04656     cpl_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
04657     cpl_ensure(cpl_imagelist_is_uniform(imlist) == 0, CPL_ERROR_ILLEGAL_INPUT,
04658                NULL);
04659 
04660     /* Create mean image with its first iterative value = first image */
04661     mean = cpl_image_duplicate(cpl_imagelist_get_const(imlist, 0));
04662     cpl_image_fill_rejected(mean, 0.0);
04663     cpl_image_accept_all(mean);
04664 
04665     stdev = cpl_image_new(cpl_image_get_size_x(mean),
04666                           cpl_image_get_size_y(mean),
04667                           CPL_TYPE_FLOAT);
04668 
04669     for (i = 1; i < cpl_imagelist_get_size(imlist); i++) {
04670         delta = cpl_image_subtract_create(cpl_imagelist_get_const(imlist, i),
04671                                           mean);
04672         cpl_image_fill_rejected(delta, 0.0);
04673         cpl_image_accept_all(delta);
04674 
04675         sq_delta = cpl_image_multiply_create(delta, delta);
04676 
04677         cpl_image_multiply_scalar(sq_delta, ((double) i / (double)(i+1)));
04678         cpl_image_add(stdev, sq_delta);
04679 
04680         cpl_image_divide_scalar(delta, i + 1);
04681         cpl_image_add(mean, delta);
04682 
04683         cpl_image_delete(delta);
04684         cpl_image_delete(sq_delta);
04685     }
04686 
04687     cpl_image_divide_scalar(stdev, cpl_imagelist_get_size(imlist) - 1);
04688     cpl_image_power(stdev, 0.5);
04689 
04690     cpl_image_delete(mean);
04691 
04692     return stdev;
04693 }

Generated on 3 Mar 2013 for DETMON Pipeline Reference Manual by  doxygen 1.6.1