irplib_detmon.c

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

Generated on Mon Apr 21 10:56:53 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1