detmon_lg.c

00001 /* $Id: detmon_lg.c,v 1.9 2012/03/07 08:22:46 amodigli Exp $
00002  *
00003  * This file is part of the irplib package
00004  * Copyright (C) 2002, 2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
00019  */
00020 
00021 
00022 /*
00023  * $Author: amodigli $
00024  * $Date: 2012/03/07 08:22:46 $
00025  * $Revision: 1.9 $
00026  * $Name: detmon-1_2_0 $
00027  *
00028  */
00029 
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033 
00034 /*---------------------------------------------------------------------------
00035                                   Includes
00036  ---------------------------------------------------------------------------*/
00037 
00038 #include <complex.h>
00039 
00040 
00041 #include <math.h>
00042 #include <string.h>
00043 #include <assert.h>
00044 
00045 #include <cpl.h>
00046 #include <cpl_fft.h>
00047 #include "detmon.h"
00048 #include "detmon_lg.h"
00049 #include "detmon_lg_impl.h"
00050 #include "detmon_dfs.h"
00051 
00052 #include "irplib_ksigma_clip.h"
00053 #include "irplib_utils.h"
00054 #include "irplib_hist.h"
00056 /*
00057  * @defgroup irplib_detmon        Detector monitoring functions
00058  */
00059 
00060 /*--------------------------------------------------------------------------*/
00061 
00062 /*---------------------------------------------------------------------------
00063                                   Defines
00064  ---------------------------------------------------------------------------*/
00065 /*method for calculating Fixed Pattern Noise (FPN)*/
00066 enum _FPN_METHOD
00067 {
00068     FPN_UNKNOWN,
00069     FPN_HISTOGRAM, /*default*/
00070     FPN_SMOOTH,
00071 };
00072 typedef enum _FPN_METHOD FPN_METHOD;
00073 static struct
00074 {
00075     const char            * method;
00076     /* Inputs */
00077     int                     order;
00078     double                     kappa;
00079     int                     niter;
00080     int                     threshold_min;
00081     int                     threshold_max;
00082     int                     llx;
00083     int                     lly;
00084     int                     urx;
00085     int                     ury;
00086     int                     ref_level;
00087     int                     threshold;
00088     int                     m;
00089     int                     n;
00090     int                     llx1;
00091     int                     lly1;
00092     int                     urx1;
00093     int                     ury1;
00094     int                     llx2;
00095     int                     lly2;
00096     int                     urx2;
00097     int                     ury2;
00098     int                     llx3;
00099     int                     lly3;
00100     int                     urx3;
00101     int                     ury3;
00102     int                     llx4;
00103     int                     lly4;
00104     int                     urx4;
00105     int                     ury4;
00106     int                     llx5;
00107     int                     lly5;
00108     int                     urx5;
00109     int                     ury5;
00110     int                     nx;
00111     int                     ny;
00112     cpl_boolean             wholechip;
00113     cpl_boolean             autocorr;
00114     cpl_boolean             intermediate;
00115     cpl_boolean             collapse;
00116     cpl_boolean             rescale;
00117     cpl_boolean             pix2pix;
00118     cpl_boolean             bpmbin;
00119     int                     filter;
00120     double                  tolerance;
00121     cpl_boolean             pafgen;
00122     const char            * pafname;
00123     /* Outputs */
00124     double                  cr;
00125     int                     exts;
00126     int                     nb_extensions;
00127     double                  lamp_stability;
00128     cpl_boolean             lamp_ok;
00129     /* by kmirny */
00130     int                    (* load_fset) (
00131             const cpl_frameset *, cpl_type, cpl_imagelist *
00132             );
00133     cpl_imagelist *                    (* load_fset_wrp) (
00134             const cpl_frameset *, cpl_type, int
00135             );
00136     FPN_METHOD fpn_method;
00137     int fpn_smooth;
00138     double saturation_limit;
00139     cpl_boolean            split_coeffs;
00140 } detmon_lg_config;
00141 
00142 /* static const char* COL_NAME_DET1_WIN1_UIT1 = "DET1_WIN1_UIT1"; */
00143 /*---------------------------------------------------------------------------
00144                                   Private function prototypes
00145  ---------------------------------------------------------------------------*/
00146 /*  Functions for the Linearity/Gain recipe, detmon_lg() */
00147 
00148 /*  Parameters */
00149 static cpl_error_code
00150 detmon_lg_retrieve_parlist(const char *,
00151                   const char *, const cpl_parameterlist *,
00152                                   cpl_boolean);
00153 
00154 
00155 static cpl_error_code
00156 detmon_lg_split_onoff(const cpl_frameset *,
00157                              cpl_frameset *,
00158                              cpl_frameset *,
00159                              const char *, const char * /*, cpl_boolean*/);
00160 
00161 static cpl_error_code
00162 detmon_lg_reduce(const cpl_frameset *,
00163                         const cpl_frameset *,
00164 /*                        int *,
00165                           int *, */
00166                         int* index_on, int* index_off, double* exptime_on, double* exptime_off,
00167                         int *next_index_on, int* next_index_off,
00168                         cpl_imagelist **,
00169                         cpl_table *,
00170                         cpl_table *,
00171                         cpl_image **,
00172                         cpl_imagelist *,
00173                         cpl_imagelist *,
00174                         cpl_propertylist *,
00175                         cpl_propertylist *,
00176                         cpl_propertylist *,
00177                         cpl_propertylist *,
00178          int                    (* load_fset) (const cpl_frameset *,
00179                                cpl_type,
00180                                                cpl_imagelist *),
00181                         const cpl_boolean, int);
00182 
00183 static cpl_error_code
00184 detmon_lin_table_fill_row(cpl_table *, double,
00185                  cpl_imagelist *,
00186                  const cpl_imagelist *,
00187                  const cpl_imagelist *,
00188                  int, int, int, int,
00189                  const int,
00190                                  const int,
00191                  unsigned);
00192 
00193 static cpl_error_code
00194 detmon_gain_table_fill_row(cpl_table * gain_table,
00195                   double c_dit,int c_ndit,
00196           cpl_imagelist * autocorr_images,
00197           cpl_imagelist * diff_flats,
00198           const cpl_imagelist * ons,
00199                         const cpl_imagelist * offs,
00200                         double kappa, int nclip,
00201                         int llx, int lly, int urx, int ury,
00202                         int m, int n,
00203                         double saturation_limit,
00204           const int pos, unsigned mode, int* rows_affected);
00205 
00206 static                  cpl_error_code
00207 detmon_lg_save(const cpl_parameterlist *,
00208                       cpl_frameset *,
00209                       const char *,
00210                       const char *,
00211                       const char *,
00212               const cpl_propertylist  *,
00213               const cpl_propertylist  *,
00214               const cpl_propertylist  *,
00215               const cpl_propertylist  *,
00216               const cpl_propertylist  *,
00217               const cpl_propertylist  *,
00218                       const char *,
00219                       cpl_imagelist *,
00220                       cpl_table *,
00221                       cpl_table *,
00222                       cpl_image *,
00223                       cpl_imagelist *,
00224                       cpl_imagelist *,
00225                       cpl_propertylist *,
00226                       cpl_propertylist *,
00227                       cpl_propertylist *,
00228                       cpl_propertylist *,
00229                       const int, const int, const cpl_frameset *,
00230                       int);
00231 
00232 static cpl_error_code
00233 detmon_lg_qc_ptc(const cpl_table  *,
00234             cpl_propertylist *, unsigned, int);
00235 
00236 static cpl_error_code
00237 detmon_lg_qc_med(const cpl_table  *,
00238             cpl_propertylist *, int);
00239 
00240 
00241 static double
00242 irplib_pfits_get_dit(const cpl_propertylist *);
00243 
00244 static double
00245 irplib_pfits_get_dit_opt(const cpl_propertylist *);
00246 static double
00247 irplib_pfits_get_prop_double(const cpl_propertylist * plist, const char* prop_name);
00248 
00249 static cpl_image       *detmon_bpixs(const cpl_imagelist *, cpl_boolean, const double, int *);
00250 
00251 static double
00252 detmon_autocorr_factor(const cpl_image *,
00253                               cpl_image **, int, int);
00254 
00255 
00256 
00257 static                  cpl_error_code
00258 detmon_opt_contamination(const cpl_imagelist *,
00259                 const cpl_imagelist *,
00260                 unsigned mode, cpl_propertylist *);
00261 
00262 #if 0
00263 detmon_opt_lampcr(cpl_frameset *, int);
00264 #endif
00265 
00266 int
00267 detmon_lg_dfs_set_groups(cpl_frameset *, const char *, const char *);
00268 
00269 static cpl_error_code
00270 detmon_lg_reduce_all(const cpl_table *,
00271                 cpl_propertylist *,
00272                 cpl_propertylist *
00273 ,               cpl_propertylist *,
00274                 cpl_propertylist *,
00275                 cpl_imagelist **,
00276                 cpl_image **,
00277                             const cpl_imagelist *,
00278                 const cpl_table *, int, cpl_boolean);
00279 
00280 static cpl_error_code
00281 detmon_lg_check_defaults(const cpl_image *);
00282 
00283 static cpl_error_code
00284 detmon_lg_rescale(cpl_imagelist *);
00285 
00286 static cpl_error_code
00287 detmon_lg_reduce_init(cpl_table *,
00288                              cpl_table *,
00289                              cpl_imagelist **,
00290                              const cpl_boolean);
00291 
00292 
00293 
00294 static cpl_error_code
00295 detmon_add_adl_column(cpl_table *, cpl_boolean);
00296 
00297 static cpl_error_code
00298 detmon_lg_lamp_stab(const cpl_frameset *,
00299                const cpl_frameset *,
00300                            cpl_boolean, int);
00301 
00302 
00303 static cpl_error_code
00304 detmon_lg_reduce_dit(const cpl_frameset * set_on,
00305                 int* index_on, double* exptime_on,
00306                 const int dit_nb,
00307                 int * dit_nskip,
00308                 const cpl_frameset * set_off,
00309                 int * index_off, double* exptime_off,
00310                 int* next_on, int* next_off,
00311                 cpl_table * linear_table,
00312                 cpl_table * gain_table,
00313                 cpl_imagelist * linearity_inputs,
00314                 cpl_propertylist * qclist,
00315                 cpl_boolean opt_nir,
00316                 cpl_imagelist * autocorr_images,
00317                 cpl_imagelist * diff_flats,
00318                 cpl_imagelist * opt_offs,
00319                 int whichext,
00320                 int * rows_affected);
00321 
00322 static cpl_error_code
00323 detmon_lg_core(cpl_frameset * cur_fset_on,
00324               cpl_frameset * cur_fset_off,
00325               int * index_on,
00326               int * index_off,
00327               double * exptime_on,
00328               double * exptime_off,
00329               int whichext,
00330                       int whichset,
00331               const char              * recipe_name,
00332               const char              * pipeline_name,
00333               const char              * pafregexp,
00334               const cpl_propertylist  * pro_lintbl,
00335               const cpl_propertylist  * pro_gaintbl,
00336               const cpl_propertylist  * pro_coeffscube,
00337               const cpl_propertylist  * pro_bpm,
00338               const cpl_propertylist  * pro_corr,
00339               const cpl_propertylist  * pro_diff,
00340               const char              * package,
00341               int                    (* load_fset) (const cpl_frameset *,
00342                                 cpl_type,
00343                                 cpl_imagelist *),
00344               int nsets, cpl_boolean opt_nir,
00345                       cpl_frameset * frameset, const cpl_parameterlist * parlist,
00346                       cpl_frameset * cur_fset);
00347 
00348 static cpl_error_code
00349 detmon_lg_lineff(double *, cpl_propertylist *, int, int);
00350 
00351 /*
00352 static int
00353 detmon_lg_compare_pairs(const cpl_frame *,
00354                    const cpl_frame *);
00355 */
00356 static cpl_error_code
00357 detmon_gain_table_create(cpl_table *,
00358                                 const cpl_boolean);
00359 
00360 
00361 static cpl_error_code
00362 detmon_lin_table_create(cpl_table *,
00363                                const cpl_boolean);
00364 
00365 static cpl_vector *
00366 detmon_lg_find_dits(const cpl_vector *,
00367                            double            );
00368 
00369 static cpl_error_code
00370 detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
00371                const cpl_vector * vec_ndits,
00372                            double             tolerance,
00373                            cpl_vector** diff_dits,
00374                  cpl_vector** diff_ndits);
00375 
00376 static cpl_error_code
00377 detmon_fpn_compute(const cpl_frameset *set_on,
00378         int * index_on,
00379         int last_best,
00380         cpl_propertylist *lint_qclist,
00381         int llx,
00382         int lly,
00383         int urx,
00384         int ury,
00385         double gain,
00386         int whichext,
00387         FPN_METHOD fpn_method,
00388         int smooth_size);
00389 static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain,
00390         FPN_METHOD fpn_method, int, double* mse);
00391 static double irplib_calculate_total_noise(const cpl_image* pimage);
00392 
00393 static cpl_imagelist* irplib_load_fset_wrp(const cpl_frameset *, cpl_type, int whichext);
00394 static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset *, cpl_type, int);
00395 
00396 static cpl_error_code irplib_table_create_column(cpl_table* ptable, cpl_propertylist* plist);
00397 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable, cpl_propertylist* plist, int row);
00398 
00399 static cpl_error_code
00400 detmon_pair_extract_next(const cpl_frameset * set,
00401                            int* index,
00402                            int* next_element,
00403                           double* dit_array,
00404 /*                           int * with_equal_dit,
00405                              int onoff, */
00406                            cpl_frameset ** pair,
00407                            double tolerance);
00408 static cpl_error_code
00409 detmon_single_extract_next(const cpl_frameset * set,
00410                            int* index,
00411                            int* next_element,
00412                            double* dit_array,
00413                            cpl_frameset ** pair);
00414 
00415 /*
00416 static int frame_get_ndit(const cpl_frame * pframe);
00417 static cpl_error_code
00418 irplib_frameset_get_ndit(const cpl_frameset *  self, int* ndit);
00419 */
00420 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable, double code);
00421 static void detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos);
00422 static int detmon_lg_check_before_gain(const cpl_vector* x, const cpl_vector* y);
00423 /*---------------------------------------------------------------------------*/
00430 /*---------------------------------------------------------------------------*/
00431 static int irplib_pfits_get_ndit(const cpl_propertylist * plist)
00432 {
00433     return cpl_propertylist_get_int(plist,"ESO DET NDIT");
00434 }
00435 
00436 
00437 /*
00438 static int frame_get_ndit(const cpl_frame * pframe)
00439 {
00440     cpl_propertylist       *plist = 0;
00441     int                  ival = 0;
00442 
00443     plist = cpl_propertylist_load(cpl_frame_get_filename(pframe),0);
00444     if(plist)
00445     {
00446         ival = cpl_propertylist_get_int(plist, "NDIT");
00447     }
00448 
00449     cpl_propertylist_delete(plist);
00450     return ival;
00451 }
00452 */
00453 
00454 /*
00455 static cpl_error_code
00456 irplib_frameset_get_ndit(const cpl_frameset *  self, int* ndit)
00457 {
00458     int sz = 0;
00459     int i = 0;
00460     const cpl_frame* tmp_frame = 0;
00461     cpl_error_code error = CPL_ERROR_NONE;
00462     sz = cpl_frameset_get_size(self);
00463 
00464     tmp_frame = cpl_frameset_get_first_const(self);
00465     while(tmp_frame)
00466     {
00467         ndit[i] = frame_get_ndit(tmp_frame);
00468         tmp_frame = cpl_frameset_get_next_const(self);
00469         i++;
00470     }
00471 
00472     return error;
00473 }
00474 */
00475 
00476 static cpl_error_code detmon_lg_reduce_set(int i, cpl_frameset * frameset, int nsets,
00477         const char              * tag_on,
00478         const char              * tag_off,
00479         const char              * recipe_name,
00480         const char              * pipeline_name,
00481         const char              * pafregexp,
00482         const cpl_propertylist  * pro_lintbl,
00483         const cpl_propertylist  * pro_gaintbl,
00484         const cpl_propertylist  * pro_coeffscube,
00485         const cpl_propertylist  * pro_bpm,
00486         const cpl_propertylist  * pro_corr,
00487         const cpl_propertylist  * pro_diff,
00488         const char              * package,
00489         int                    (* load_fset)
00490             (const cpl_frameset *, cpl_type, cpl_imagelist *),
00491         const cpl_boolean         opt_nir,
00492         const cpl_parameterlist * parlist,
00493         cpl_size* selection
00494         );
00495 static double irplib_compute_err(double gain, double ron, double photon_noise);
00496 /* wrapper function for different cpl versions*/
00497 static cpl_error_code detmon_lg_dfs_save_imagelist(
00498         cpl_frameset * frameset,
00499         const cpl_parameterlist * parlist,
00500         const cpl_frameset *usedframes,
00501         const cpl_imagelist *coeffs,
00502         const char *recipe_name,
00503         const cpl_propertylist *mypro_coeffscube,
00504         const char * package,
00505         const char * name_o);
00506 
00507 /*--------------------------------------------------------------------------*/
00508 static void irplib_free(char** pointer){
00509 
00510    if(pointer && *pointer) {
00511       cpl_free(*pointer);
00512       *pointer=NULL;
00513    }
00514 }
00515 
00516 static cpl_error_code detmon_lg_reduce_set(int i, cpl_frameset * frameset, int nsets,
00517         const char              * tag_on,
00518         const char              * tag_off,
00519         const char              * recipe_name,
00520         const char              * pipeline_name,
00521         const char              * pafregexp,
00522         const cpl_propertylist  * pro_lintbl,
00523         const cpl_propertylist  * pro_gaintbl,
00524         const cpl_propertylist  * pro_coeffscube,
00525         const cpl_propertylist  * pro_bpm,
00526         const cpl_propertylist  * pro_corr,
00527         const cpl_propertylist  * pro_diff,
00528         const char              * package,
00529         int                    (* load_fset)
00530             (const cpl_frameset *, cpl_type, cpl_imagelist *),
00531         const cpl_boolean         opt_nir,
00532         const cpl_parameterlist * parlist,
00533         cpl_size* selection
00534         )
00535 {
00536     int  j;
00537     int nexts = detmon_lg_config.nb_extensions;
00538 
00539     double* exptime_on = 0;
00540     double* exptime_off = 0;
00541     int* index_on = 0;
00542     int* index_off = 0;
00543     cpl_frameset  * cur_fset = NULL;
00544     cpl_frameset* cur_fset_on = 0;
00545     cpl_frameset* cur_fset_off = 0;
00546 
00547     /* Reduce data set nb i */
00548     cur_fset =
00549            (nsets == 1) ? /* would be better (selection == 0) ? */
00550         cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
00551 
00552 
00553     skip_if(cur_fset == NULL);
00554 
00555     /* Split input frameset into 2 sub-framesets for ON and OFF frames */
00556     cur_fset_on  = cpl_frameset_new();
00557     cur_fset_off = cpl_frameset_new();
00558     cpl_msg_info(cpl_func, "Splitting into ON and OFF sub-framesets");
00559     skip_if (detmon_lg_split_onoff(cur_fset,
00560                           cur_fset_on, cur_fset_off,
00561                           tag_on, tag_off /*, opt_nir*/));
00562     if (cpl_frameset_get_size(cur_fset_on)  == 0)
00563     {
00564         cpl_msg_error(cpl_func, "No lamp frames in input");
00565         skip_if(1);
00566     }
00567 
00568     if (cpl_frameset_get_size(cur_fset_off)  == 0)
00569     {
00570         cpl_msg_error(cpl_func, "No dark / bias frames in input");
00571         skip_if(1);
00572     }
00573     cpl_msg_info(cpl_func, "found on-frames[%" CPL_SIZE_FORMAT "] off-frames[%" CPL_SIZE_FORMAT "]",cpl_frameset_get_size(cur_fset_on), cpl_frameset_get_size(cur_fset_off));
00574     /* Labelise each sub-frameset according to DIT values */
00575 /*      selection_on = cpl_frameset_labelise(cur_fset_on,
00576                          detmon_lg_compare_pairs,
00577                          &nsets_on);
00578 
00579     skip_if (selection_on == NULL);
00580 */
00581     exptime_on = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_on));
00582     exptime_off = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_off));
00583 
00584     index_on = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_on));
00585     index_off = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_off));
00586     irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
00587     irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
00588 /*  for (j = 0; j < cpl_frameset_get_size(cur_fset_on); j++)
00589     {
00590         cpl_msg_info(cpl_func, "%d: \t %d \t %f", j , index_on[j], exptime_on[j]);
00591     }
00592     */
00593     /* TODO Check that each ON frame pair has a corresponding OFF frame*/
00594 
00595     /* Test if they have equal nb of labels */
00596 /*      if (!detmon_lg_config.collapse) {
00597         skip_if(nsets_on != nsets_off);
00598     }
00599 */
00600     skip_if(detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
00601 
00602     if(detmon_lg_config.exts >= 0)
00603     {
00604         /*
00605          * In the optical domain, the first 2 frames
00606          * are used apart from the pairs.
00607          */
00608 
00609 #if 0
00610         if (detmon_lg_config.lamp_ok) {
00611         skip_if(detmon_opt_lampcr(cur_fset, 0));
00612         }
00613 #endif
00614         skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
00615                           index_on,
00616                           index_off,
00617                           exptime_on,
00618                           exptime_off,
00619                           detmon_lg_config.exts,
00620                           i,
00621                 recipe_name, pipeline_name, pafregexp,
00622                 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
00623                 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
00624     } else {
00625         for(j = 1; j <= nexts; j++) {
00626         /*
00627          * In the optical domain, the first 2 frames
00628          * are used apart from the pairs.
00629          */
00630 
00631 #if 0
00632         if (detmon_lg_config.lamp_ok) {
00633             skip_if(detmon_opt_lampcr(cur_fset, j));
00634         }
00635 #endif
00636 
00637         skip_if(detmon_lg_core(cur_fset_on, cur_fset_off,
00638                           index_on,
00639                           index_off,
00640                           exptime_on,
00641                           exptime_off,
00642                           j, i,  recipe_name, pipeline_name,pafregexp,  pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
00643         }
00644     }
00645     end_skip;
00646 
00647     cpl_frameset_delete(cur_fset);
00648     cpl_frameset_delete(cur_fset_on);
00649     cpl_frameset_delete(cur_fset_off);
00650     cpl_free(index_on);
00651     cpl_free(index_off);
00652     cpl_free(exptime_on);
00653     cpl_free(exptime_off);
00654     return cpl_error_get_code();
00655 }
00656 /*
00657  * @brief  Reduce linearity and gain in the IR domain
00658  * @param  parlist              List of required parameters
00659  * @param  frameset             Input frameset
00660  * @param  tag_on               Tag to identify the ON frames
00661  * @param  tag_off              Tag to identify the OFF frames
00662  * @param  recipe_name          Name of the recipe calling this function
00663  * @param  pipeline_name        Name of the pipeline calling this function
00664  * @param  procatg_lintbl       PRO.CATG keyword for the Linearity Table
00665  * @param  procatg_gaintbl      PRO.CATG keyword for the Gain Table
00666  * @param  procatg_coeffscube     PRO.CATG keyword for the
00667  *                              Linearity Coefficients' Images
00668  * @param  procatg_bpm          PRO.CATG required for the Bad Pixel Map
00669  * @param  procatg_corr     PRO.CATG required for the Autocorrelation Images
00670  *                              (Intermediate product - only created if required)
00671  * @param  procatg_diff         PRO.CATG required for the Difference Images
00672  *                              (Intermediate Product - only created if required)
00673  * @param  package              PACKAGE (incl. VERSION) required
00674  *                              for the DFS keywords
00675  * @param  compare              Compare function used to classified frameset into
00676  *                              different settings, if any.
00677  * @param  load_fset            Loading function for preprocessing of input
00678                                 frames with special data format (needed for
00679                                 AMBER and MIDI processing)
00680 
00681  * @param  opt_nir              Boolean parameter to activate/deactivate
00682  *                              OPT-only / IR-only parts of the recipe
00683  * @return 0 on success, -1 on fail.
00684  * @note: The parlist contains the following parameters:
00685  *
00686  * @par1  kappa                 Kappa value used for the kappa-sigma clipping
00687  *                              rejection of bad pixels when computing sigma for
00688  *                              gain calculation
00689  * @par2  niter                 Number of iterations for the kappa-sigma clipping
00690  * @par3  threshold_min         Minimum threshold of the k-sigma (Not applied)
00691  * @par4  threshold_max         Maximum threshold of the k-sigma (Not applied)
00692  * @par5  llx                   Region of Interest (Default to the whole area)
00693  * @par6  lly                   Region of Interest (Default to the whole area)
00694  * @par7  urx                   Region of Interest (Default to the whole area)
00695  * @par8  ury                   Region of Interest (Default to the whole area)
00696  * @par9  ref_level             Reference Level (Not applied)
00697  * @par10 threshold             Threshold (Not applied)
00698  * @par11 intermediate          Boolean to activate the production of
00699  *                              Intermediate Products
00700  * @par12 autocorr              Boolean to activate autocorr method
00701  * @par13 collapse              Boolean to activate collapse of OFF frames
00702  * @par14 rescale               Boolean to activate pair rescaling
00703  * @par15 m                     X-Shift of the autocorrelation
00704  * @par16 n                     Y-Shift of the autocorrelation
00705  * @par17 llx1                  Region of Interest 1 (Only OPT)
00706  * @par18 lly1                  Region of Interest 1 (Only OPT)
00707  * @par19 urx1                  Region of Interest 1 (Only OPT)
00708  * @par20 ury1                  Region of Interest 1 (Only OPT)
00709  * @par21 llx2                  Region of Interest 2 (Only OPT)
00710  * @par22 lly2                  Region of Interest 2 (Only OPT)
00711  * @par23 urx2                  Region of Interest 2 (Only OPT)
00712  * @par24 ury2                  Region of Interest 2 (Only OPT)
00713  * @par25 llx3                  Region of Interest 3 (Only OPT)
00714  * @par26 lly3                  Region of Interest 3 (Only OPT)
00715  * @par27 urx3                  Region of Interest 3 (Only OPT)
00716  * @par28 ury3                  Region of Interest 3 (Only OPT)
00717  * @par29 llx4                  Region of Interest 4 (Only OPT)
00718  * @par30 lly4                  Region of Interest 4 (Only OPT)
00719  * @par31 urx4                  Region of Interest 4 (Only OPT)
00720  * @par32 ury4                  Region of Interest 4 (Only OPT)
00721  * @par33 llx5                  Region of Interest 5 (Only OPT)
00722  * @par34 lly5                  Region of Interest 5 (Only OPT)
00723  * @par35 urx5                  Region of Interest 5 (Only OPT)
00724  * @par36 ury5                  Region of Interest 5 (Only OPT)
00725  * @par37 exts                  Integer to select extension
00726  */
00727 
00728 /*--------------------------------------------------------------------------*/
00729 
00730 cpl_error_code
00731 detmon_lg(cpl_frameset            * frameset,
00732                  const cpl_parameterlist * parlist,
00733                  const char              * tag_on,
00734                  const char              * tag_off,
00735                  const char              * recipe_name,
00736                  const char              * pipeline_name,
00737                  const char              * pafregexp,
00738                  const cpl_propertylist  * pro_lintbl,
00739                  const cpl_propertylist  * pro_gaintbl,
00740                  const cpl_propertylist  * pro_coeffscube,
00741                  const cpl_propertylist  * pro_bpm,
00742                  const cpl_propertylist  * pro_corr,
00743                  const cpl_propertylist  * pro_diff,
00744                  const char              * package,
00745                  int                    (* compare) (const cpl_frame *,
00746                              const cpl_frame *),
00747          int                    (* load_fset) (const cpl_frameset *,
00748                                cpl_type,
00749                                                cpl_imagelist *),
00750                  const cpl_boolean         opt_nir)
00751 {
00752     cpl_size              nsets;
00753     cpl_size            * selection = NULL;
00754     int              i;
00755     cpl_frame      * first     = NULL;
00756     cpl_image      * reference = NULL;
00757 
00758     /*
00759      * Variables used only inside the for() statement.
00760      * However, there are declared here to ease
00761      * memory management in error case.
00762      */
00763     cpl_frameset     * cur_fset        = NULL;
00764     cpl_frameset     * cur_fset_on     = NULL;
00765     cpl_frameset     * cur_fset_off    = NULL;
00766 
00767     /* Test entries */
00768     cpl_ensure_code(frameset           != NULL, CPL_ERROR_NULL_INPUT);
00769     cpl_ensure_code(parlist            != NULL, CPL_ERROR_NULL_INPUT);
00770     cpl_ensure_code(tag_on             != NULL, CPL_ERROR_NULL_INPUT);
00771     cpl_ensure_code(tag_off            != NULL, CPL_ERROR_NULL_INPUT);
00772     cpl_ensure_code(recipe_name        != NULL, CPL_ERROR_NULL_INPUT);
00773     cpl_ensure_code(pipeline_name      != NULL, CPL_ERROR_NULL_INPUT);
00774     cpl_ensure_code(pro_lintbl         != NULL, CPL_ERROR_NULL_INPUT);
00775     cpl_ensure_code(pro_gaintbl        != NULL, CPL_ERROR_NULL_INPUT);
00776     cpl_ensure_code(pro_coeffscube     != NULL, CPL_ERROR_NULL_INPUT);
00777     cpl_ensure_code(pro_bpm            != NULL, CPL_ERROR_NULL_INPUT);
00778     cpl_ensure_code(pro_corr           != NULL, CPL_ERROR_NULL_INPUT);
00779     cpl_ensure_code(pro_diff           != NULL, CPL_ERROR_NULL_INPUT);
00780     cpl_ensure_code(package            != NULL, CPL_ERROR_NULL_INPUT);
00781 
00782     cpl_msg_info(cpl_func,"frameset size [%" CPL_SIZE_FORMAT "]", cpl_frameset_get_size(frameset));
00783 
00784 
00785     skip_if (detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
00786 
00787     /*
00788      * First check of input consistency in NIR case:
00789      * There must be a pair ON and a pair OFF for each DIT.
00790      */
00791 
00792     skip_if (detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
00793                            parlist, opt_nir));
00794 
00795     /*
00796      * Retrieve first image to check some parameters' values and
00797      * set default values which refer to the image.
00798      */
00799 
00800     first = cpl_frameset_get_first(frameset);
00801     irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT, "Empty data set! Provide %s and %s input frames",tag_on,tag_off);
00802 
00803     detmon_lg_config.load_fset = load_fset;
00804     detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
00805 
00806 
00807     if (detmon_lg_config.exts < 0) {
00808         reference = cpl_image_load(cpl_frame_get_filename(first),
00809                                    CPL_TYPE_FLOAT, 0, 1);
00810     } else {
00811     if (load_fset != NULL) {
00812         cpl_frameset * new = cpl_frameset_new();
00813         cpl_imagelist * p = cpl_imagelist_new();
00814         cpl_frameset_insert(new, cpl_frame_duplicate(first));
00815         (*load_fset)(new, CPL_TYPE_FLOAT, p);
00816         reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
00817         cpl_imagelist_delete(p);
00818         cpl_frameset_delete(new);
00819     } else {
00820            cpl_msg_info(cpl_func,"name=%s",cpl_frame_get_filename(first));
00821         reference = cpl_image_load(cpl_frame_get_filename(first),
00822                        CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
00823     }
00824     }
00825     skip_if (reference == NULL);
00826 
00827     skip_if (detmon_lg_check_defaults(reference));
00828 
00829     /* Labelise all input frames */
00830 
00831     /*
00832      * After each setting iteration, frameset will be modified (product
00833      * frames will have been added), so it is better to duplicate it, keep
00834      * it in its original state for the labelise-extract scheme.
00835      */
00836     if (compare == NULL) {
00837         nsets = 1;
00838     } else {
00839         cpl_msg_info(cpl_func, "Identifying different settings");
00840         selection = cpl_frameset_labelise(frameset, compare, &nsets);
00841         skip_if (selection == NULL);
00842     }
00843 
00844     /* Get the nb of extensions */
00845     detmon_lg_config.nb_extensions = 1;
00846     if (detmon_lg_config.exts < 0)
00847     {
00848         detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
00849     }
00850     /* Extract settings and reduce each of them */
00851     for(i = 0; i < nsets; i++)
00852     {
00853         int fr_size = cpl_frameset_get_size(frameset);
00854         int fr_size_new = 0;
00855         cpl_msg_info(cpl_func, "Reduce data set nb %d out of %" CPL_SIZE_FORMAT "",
00856                  i + 1, nsets);
00857         skip_if(detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
00858                 recipe_name,
00859                 pipeline_name,
00860                 pafregexp,
00861                 pro_lintbl,
00862                 pro_gaintbl,
00863                 pro_coeffscube,
00864                 pro_bpm,
00865                 pro_corr,
00866                 pro_diff,
00867                 package,
00868                 load_fset,
00869                 opt_nir,
00870                 parlist,
00871                 selection));
00872         fr_size_new = cpl_frameset_get_size(frameset);
00873         /* the size of the frameset could be changed during the detmon_lg_reduce_set call
00874          * so the size of the selection array should be adjusted with some fake values,
00875          * to avoid reading of the not allocated memory
00876          * see DFS08110 for the error description
00877          * */
00878         if (fr_size_new > fr_size)
00879         {
00880             selection = cpl_realloc(selection, fr_size_new  * sizeof(selection[0]));
00881             memset(selection + fr_size,  -1, (fr_size_new - fr_size) * sizeof(selection[0]));
00882         }
00883     }
00884 
00885     end_skip;
00886 
00887     cpl_frameset_delete(cur_fset);
00888     cpl_frameset_delete(cur_fset_on);
00889     cpl_frameset_delete(cur_fset_off);
00890     cpl_free(selection);
00891     cpl_image_delete(reference);
00892 
00893     return cpl_error_get_code();
00894 }
00895 
00896 /*---------------------------------------------------------------------------*/
00927 /*---------------------------------------------------------------------------*/
00928 
00929 static cpl_error_code
00930 detmon_lg_core(cpl_frameset * cur_fset_on,
00931               cpl_frameset * cur_fset_off,
00932               int * index_on,
00933               int * index_off,
00934               double * exptime_on,
00935               double * exptime_off,
00936               int whichext,
00937                       int whichset,
00938               const char              * recipe_name,
00939               const char              * pipeline_name,
00940               const char              * pafregexp,
00941               const cpl_propertylist  * pro_lintbl,
00942               const cpl_propertylist  * pro_gaintbl,
00943               const cpl_propertylist  * pro_coeffscube,
00944               const cpl_propertylist  * pro_bpm,
00945               const cpl_propertylist  * pro_corr,
00946               const cpl_propertylist  * pro_diff,
00947               const char              * package,
00948               int                    (* load_fset) (const cpl_frameset *,
00949                                 cpl_type,
00950                                 cpl_imagelist *),
00951               int nsets, cpl_boolean opt_nir,
00952                       cpl_frameset * frameset, const cpl_parameterlist * parlist,
00953                       cpl_frameset * cur_fset)
00954 {
00955   cpl_table * gain_table = cpl_table_new(
00956       cpl_frameset_get_size(cur_fset_on) / 2);
00957   cpl_table * linear_table = cpl_table_new(
00958       cpl_frameset_get_size(cur_fset_on) / 2);
00959   cpl_imagelist * coeffs = NULL;
00960   cpl_image * bpm = NULL;
00961   cpl_imagelist * autocorr_images = NULL;
00962   cpl_imagelist * diff_flats = NULL;
00963   cpl_propertylist * gaint_qclist = NULL;
00964   cpl_propertylist * lint_qclist = NULL;
00965   cpl_propertylist * linc_qclist = NULL;
00966   cpl_propertylist * bpm_qclist = NULL;
00967 
00968   int next_index_on = 0;
00969   int next_index_off = 0;
00970 
00971   /* Reduce extension nb i */
00972   cpl_msg_info(cpl_func, "Reduce extension nb %d ", whichext);
00973 
00974   /* FIXME: All other memory objects in use should be
00975    initialised here (except coeffs which can not be) */
00976   if (detmon_lg_config.intermediate) {
00977     autocorr_images = cpl_imagelist_new();
00978     diff_flats = cpl_imagelist_new();
00979   }
00980 
00981   gaint_qclist = cpl_propertylist_new();
00982   lint_qclist = cpl_propertylist_new();
00983   linc_qclist = cpl_propertylist_new();
00984   bpm_qclist = cpl_propertylist_new();
00985 
00986   /* Reduction done here */
00987   cpl_msg_info(cpl_func, "Starting data reduction");
00988   skip_if(
00989       detmon_lg_reduce(cur_fset_on, cur_fset_off,
00990           index_on, index_off, exptime_on, exptime_off,
00991           &next_index_on, &next_index_off,
00992           &coeffs, gain_table,
00993           linear_table, &bpm, autocorr_images,
00994           diff_flats, gaint_qclist, lint_qclist,
00995           linc_qclist, bpm_qclist, load_fset,
00996           opt_nir, whichext));
00997 
00998   /* Save the products for each setting */
00999   cpl_msg_info(cpl_func, "Saving the products");
01000   if (nsets == 1) {
01001     skip_if(
01002         detmon_lg_save(parlist, frameset, recipe_name,
01003             pipeline_name, pafregexp,
01004             pro_lintbl, pro_gaintbl,
01005             pro_coeffscube, pro_bpm,
01006             pro_corr, pro_diff, package,
01007             coeffs, gain_table, linear_table,
01008             bpm, autocorr_images, diff_flats,
01009             gaint_qclist, lint_qclist, linc_qclist,
01010             bpm_qclist, 0, 0, cur_fset, whichext));
01011   } else {
01012     skip_if(
01013         detmon_lg_save(parlist, frameset, recipe_name,
01014             pipeline_name, pafregexp,
01015             pro_lintbl, pro_gaintbl,
01016             pro_coeffscube, pro_bpm,
01017             pro_corr, pro_diff, package,
01018             coeffs, gain_table, linear_table,
01019             bpm, autocorr_images, diff_flats,
01020             gaint_qclist, lint_qclist, linc_qclist,
01021             bpm_qclist, 1, whichset+ 1, cur_fset,
01022             whichext));
01023   }
01024 
01025   end_skip;
01026 
01027   /* Free for each extension */
01028 
01029   cpl_table_delete(gain_table);
01030   cpl_table_delete(linear_table);
01031   cpl_imagelist_delete(coeffs);
01032   cpl_propertylist_delete(gaint_qclist);
01033   cpl_propertylist_delete(lint_qclist);
01034   cpl_propertylist_delete(linc_qclist);
01035   if(bpm_qclist != NULL) cpl_propertylist_delete(bpm_qclist);
01036   cpl_image_delete(bpm);
01037   cpl_imagelist_delete(autocorr_images);
01038   cpl_imagelist_delete(diff_flats);
01039 
01040   return cpl_error_get_code();
01041 }
01042 /*--------------------------------------------------------------------------*/
01043 
01044 /*
01045  * @brief  Correlate two images with a given range of shifts
01046  * @param  image1       Input image
01047  * @param  image2       Input image
01048  * @param  m            Shift to apply on the x-axis
01049  * @param  n            Shift to apply on the y-axis
01050  * @return              An image of size 2m+1 by 2n+1. Each pixel value
01051  *                      corresponds to the correlation of shift the position
01052  *                      of the pixel. Pixel in the centre (m+1, n+1),
01053  *                      corresponds to shift (0,0). Pixels to the left and
01054  *                      down correspond to negative shifts.
01055  *
01056  * @note                At this moment, this function only accepts images to
01057  *                      have both the same size.
01058  */
01059 
01060 /*--------------------------------------------------------------------------*/
01061 
01062 cpl_image              *
01063 detmon_image_correlate(const cpl_image * image1,
01064                               const cpl_image * image2,
01065                               const int m, const int n)
01066 {
01067     cpl_image              *image1_padded = NULL;
01068     cpl_image              *image2_padded = NULL;
01069     int                     nx, ny;
01070     int                     nx2, ny2;
01071     int                     i,j;
01072 
01073     cpl_image              *corr_image = NULL;
01074     cpl_image              *corr_image_window = NULL;
01075     cpl_image              *reorganised= NULL;
01076     cpl_image              *image= NULL;
01077 
01078     cpl_image* image_ri_inv = NULL;
01079     cpl_image* image_in_inv = NULL;
01080     cpl_image* image_ri1 = NULL;
01081     cpl_image* image_ri2 = NULL;
01082     cpl_error_code err = CPL_ERROR_NONE;
01083 
01084     /* Test the entries */
01085     cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01086     cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01087 
01088     cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
01089     cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
01090 
01091     nx = cpl_image_get_size_x(image1);
01092     ny = cpl_image_get_size_y(image1);
01093 
01094     nx2 = cpl_image_get_size_x(image2);
01095     ny2 = cpl_image_get_size_y(image2);
01096 
01097     /* At this moment, the images must be of the same size */
01098     cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
01099 
01100     /* Pad the images with zeroes to avoid periodical effects of DFT */
01101     image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
01102     cpl_image_copy(image1_padded, image1, m + 1, n + 1);
01103 
01104     image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
01105     cpl_image_copy(image2_padded, image2, m + 1, n + 1);
01106 
01107     /*New dimensions of the padded images */
01108     nx = nx + 2 * m;
01109     ny = ny + 2 * n;
01110 
01111     image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
01112     image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
01113     /* Actually perform the FFT */
01114     cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
01115     cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
01116     err = cpl_error_get_code();
01117     cpl_image_delete(image1_padded);
01118     image1_padded = NULL;
01119     cpl_image_delete(image2_padded);
01120     image2_padded = NULL;
01121     if (err == CPL_ERROR_NONE)
01122     {
01123     /* Cleanup resources */
01124         image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01125         image_in_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
01126 
01127         for (i = 1; i <= nx; i++)
01128         {
01129             for (j = 1; j <= ny; j++)
01130             {
01131                 int rej = 0;
01132                 double complex value1, value2, value;
01133                 value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
01134                 value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
01135                 value = conj(value1) * value2;
01136                 cpl_image_set_complex(image_in_inv, i, j, value);
01137             }
01138         }
01139         cpl_image_delete(image_ri1);
01140         image_ri1 = NULL;
01141         cpl_image_delete(image_ri2);
01142         image_ri2 = NULL;
01143 
01144         err = cpl_error_get_code();
01145         if (err == CPL_ERROR_NONE)
01146         {
01147 
01148         /* Actually perform the FFT */
01149         cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
01150         cpl_image_delete(image_in_inv);
01151 
01152         /* Get the module of the inversed signal */
01153         corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01154         for (i = 1; i <= nx; i++)
01155         {
01156             for (j = 1; j <= ny; j++)
01157             {
01158                 int rej = 0;
01159                 double value =0;
01160                 value = cpl_image_get(image_ri_inv, i, j, &rej);
01161                 cpl_image_set(corr_image, i, j, value);
01162             }
01163         }
01164         cpl_image_delete(image_ri_inv);
01165         err = cpl_error_get_code();
01166         if (err == CPL_ERROR_NONE)
01167         {
01168         /* Reorganise the pixels to the output */
01169             reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01170 
01171             image = cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
01172             cpl_image_copy(reorganised, image, 1, 1);
01173             cpl_image_delete(image);
01174             image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
01175             cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
01176             cpl_image_delete(image);
01177 
01178             cpl_image_delete(corr_image);
01179 
01180             corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01181             image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
01182             cpl_image_copy(corr_image, image, 1, 1);
01183             cpl_image_delete(image);
01184 
01185             image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
01186             cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
01187             cpl_image_delete(image);
01188             /* Extract a window with the desired shifts */
01189             corr_image_window = cpl_image_extract(corr_image,
01190                                                   nx / 2 + 1 - m,
01191                                                   ny / 2 + 1 - n,
01192                                                   nx / 2 + 1 + m, ny / 2 + 1 + n);
01193             }
01194         /* Free and return */
01195 
01196         }
01197         cpl_image_delete(reorganised);
01198         cpl_image_delete(corr_image);
01199 
01200         if(cpl_image_divide_scalar(corr_image_window,
01201                                    cpl_image_get_max(corr_image_window))) {
01202             cpl_image_delete(corr_image_window);
01203             return NULL;
01204         }
01205     }
01206     cpl_image_delete (image_ri1);
01207     cpl_image_delete (image_ri2);
01208     cpl_image_delete (image1_padded);
01209     cpl_image_delete (image2_padded);
01210     return corr_image_window;
01211 }
01212 
01213 
01214 
01215 /*--------------------------------------------------------------------------*/
01216 
01217 /*
01218  * @brief  Autocorrelate an image with a given range of shifts, using
01219  *         cpl_image_fft()
01220  * @param  input2       Input image
01221  * @param  m            Shift to apply on the x-axis
01222  * @param  n            Shift to apply on the y-axis
01223  * @return              An image of size 2m+1 by 2n+1. Each pixel value
01224  *                      corresponds to the correlation of shift the position
01225  *                      of the pixel. Pixel in the centre (m+1, n+1),
01226  *                      corresponds to shift (0,0). Pixels to the left and
01227  *                      down correspond to negative shifts.
01228  */
01229 
01230 /*--------------------------------------------------------------------------*/
01231 
01232 cpl_image              *
01233 detmon_autocorrelate(const cpl_image * input2, const int m,
01234                             const int n)
01235 {
01236     cpl_image              *im_re = NULL;
01237     cpl_image              *im_im = NULL;
01238     int                     nx, ny;
01239     cpl_image              *ifft_re = NULL;
01240     cpl_image              *ifft_im = NULL;
01241     cpl_image              *autocorr = NULL;
01242     cpl_image              *autocorr_norm_double = NULL;
01243     cpl_image              *autocorr_norm = NULL;
01244     cpl_image              *reorganised = NULL;
01245     cpl_image              *image = NULL;
01246     int                     p;
01247     cpl_error_code          error;
01248     cpl_image              *input;
01249 
01250     cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01251 
01252     cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
01253     cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
01254 
01255     nx = cpl_image_get_size_x(input2) + 2 * m;
01256     ny = cpl_image_get_size_y(input2) + 2 * n;
01257 
01258     p = 128;
01259     while(nx > p || ny > p) {
01260         p *= 2;
01261     }
01262 
01263     input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
01264 
01265     im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01266     error = cpl_image_copy(im_re, input, 1, 1);
01267     cpl_ensure(!error, error, NULL);
01268 
01269     im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01270 
01271     error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
01272     cpl_ensure(!error, error, NULL);
01273 
01274     ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01275     error = cpl_image_power(im_re, 2);
01276     cpl_ensure(!error, error, NULL);
01277 
01278     error = cpl_image_add(ifft_re, im_re);
01279     cpl_ensure(!error, error, NULL);
01280 
01281     cpl_image_delete(im_re);
01282 
01283     error = cpl_image_power(im_im, 2);
01284     cpl_ensure(!error, error, NULL);
01285 
01286     error = cpl_image_add(ifft_re, im_im);
01287     cpl_ensure(!error, error, NULL);
01288 
01289     cpl_image_delete(im_im);
01290 
01291     ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01292 
01293     error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
01294     cpl_ensure(!error, error, NULL);
01295 
01296     autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01297 
01298     error = cpl_image_power(ifft_re, 2);
01299     cpl_ensure(!error, error, NULL);
01300 
01301     error = cpl_image_add(autocorr, ifft_re);
01302     cpl_ensure(!error, error, NULL);
01303 
01304     cpl_image_delete(ifft_re);
01305 
01306     error = cpl_image_power(ifft_im, 2);
01307     cpl_ensure(!error, error, NULL);
01308 
01309     error = cpl_image_add(autocorr, ifft_im);
01310     cpl_ensure(!error, error, NULL);
01311 
01312     cpl_image_delete(ifft_im);
01313 
01314     /* Reorganise the pixels to the output */
01315     reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01316 
01317     image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
01318     cpl_image_copy(reorganised, image, 1, 1);
01319     cpl_image_delete(image);
01320 
01321     image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
01322     cpl_image_copy(reorganised, image, p / 2 + 1, 1);
01323     cpl_image_delete(image);
01324 
01325     cpl_image_delete(autocorr);
01326 
01327     autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01328 
01329     image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
01330     cpl_image_copy(autocorr, image, 1, 1);
01331     cpl_image_delete(image);
01332 
01333     image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
01334     cpl_image_copy(autocorr, image, 1, p / 2 + 1);
01335     cpl_image_delete(image);
01336 
01337     cpl_image_delete(reorganised);
01338 
01339     autocorr_norm_double =
01340         cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
01341                           p / 2 + 1 + m, p / 2 + 1 + n);
01342 
01343     cpl_image_delete(autocorr);
01344 
01345     if(cpl_image_divide_scalar(autocorr_norm_double,
01346                                cpl_image_get_max(autocorr_norm_double))) {
01347         cpl_image_delete(autocorr_norm_double);
01348         cpl_ensure(0, cpl_error_get_code(), NULL);
01349     }
01350 
01351 
01352     autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
01353     cpl_image_delete(autocorr_norm_double);
01354 
01355     cpl_image_delete(input);
01356 
01357     return autocorr_norm;
01358 }
01359 
01360 /*---------------------------------------------------------------------------*/
01371 /*---------------------------------------------------------------------------*/
01372 cpl_error_code
01373 detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
01374                                   const char *recipe_name,
01375                                   const char *pipeline_name)
01376 {
01377     const cpl_error_code error =
01378     detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01379                   "PTC", /* --method */
01380                   3,   /* --order         */
01381                               3.,        /* --kappa         */
01382                               5,       /* --niter         */
01383                               -1,       /* --llx           */
01384                               -1,       /* --lly           */
01385                               -1,       /* --urx           */
01386                               -1,       /* --ury           */
01387                               10000,    /* --ref_level     */
01388                               "CPL_FALSE",      /* --intermediate  */
01389                               "CPL_FALSE",      /* --autocorr      */
01390                               "CPL_FALSE",      /* --collapse      */
01391                               "CPL_TRUE",       /* --rescale       */
01392                       "CPL_TRUE",/* --pix2pix */
01393                       "CPL_FALSE", /* --bpmbin */
01394                               -1,       /* --filter        */
01395                               26,       /* --m             */
01396                               26,       /* --n             */
01397                       1e-3, /* --tolerance */
01398                   "CPL_FALSE", /* --pafgen */
01399                       recipe_name, /* --pafname */
01400                               -1,       /* --llx1          */
01401                               -1,       /* --lly1          */
01402                               -1,       /* --urx1          */
01403                               -1,       /* --ury1          */
01404                               -1,       /* --llx2          */
01405                               -1,       /* --lly2          */
01406                               -1,       /* --urx2          */
01407                               -1,       /* --ury2          */
01408                               -1,       /* --llx3          */
01409                               -1,       /* --lly3          */
01410                               -1,       /* --urx3          */
01411                               -1,       /* --ury3          */
01412                               -1,       /* --llx4          */
01413                               -1,       /* --lly4          */
01414                               -1,       /* --urx4          */
01415                               -1,       /* --ury4          */
01416                               -1,       /* --llx5          */
01417                               -1,       /* --lly5          */
01418                               -1,       /* --urx5          */
01419                               -1,       /* --ury5          */
01420                       0,      /* --exts */
01421                           NIR);       /* This is to specify OPT params */
01422 
01423 
01424     cpl_ensure_code(!error, error);
01425 
01426     return cpl_error_get_code();
01427 }
01428 
01429 /*---------------------------------------------------------------------------*/
01440 /*---------------------------------------------------------------------------*/
01441 cpl_error_code
01442 detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
01443                                   const char *recipe_name,
01444                                   const char *pipeline_name)
01445 {
01446     const cpl_error_code error =
01447     detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01448                   "PTC", /* --method */
01449                   3,   /* --order         */
01450                               3.,        /* --kappa         */
01451                               5,       /* --niter         */
01452                               -1,       /* --llx           */
01453                               -1,       /* --lly           */
01454                               -1,       /* --urx           */
01455                               -1,       /* --ury           */
01456                               10000,    /* --ref_level     */
01457                               "CPL_FALSE",      /* --intermediate  */
01458                               "CPL_FALSE",      /* --autocorr      */
01459                               "CPL_TRUE",      /* --collapse      */
01460                               "CPL_TRUE",       /* --rescale       */
01461                       "CPL_FALSE", /* --pix2pix */
01462                       "CPL_FALSE", /* --bpmbin */
01463                               -1,       /* --filter        */
01464                               26,       /* --m             */
01465                               26,       /* --n             */
01466                       1e-3, /* --tolerance */
01467                   "CPL_FALSE", /* --pafgen */
01468                       recipe_name, /* --pafname */
01469                               -1,       /* --llx1          */
01470                               -1,       /* --lly1          */
01471                               -1,       /* --urx1          */
01472                               -1,       /* --ury1          */
01473                               -1,       /* --llx2          */
01474                               -1,       /* --lly2          */
01475                               -1,       /* --urx2          */
01476                               -1,       /* --ury2          */
01477                               -1,       /* --llx3          */
01478                               -1,       /* --lly3          */
01479                               -1,       /* --urx3          */
01480                               -1,       /* --ury3          */
01481                               -1,       /* --llx4          */
01482                               -1,       /* --lly4          */
01483                               -1,       /* --urx4          */
01484                               -1,       /* --ury4          */
01485                               -1,       /* --llx5          */
01486                               -1,       /* --lly5          */
01487                               -1,       /* --urx5          */
01488                               -1,       /* --ury5          */
01489                       0,      /* --exts */
01490                           OPT);       /* This is to specify OPT params */
01491 
01492     cpl_ensure_code(!error, error);
01493 
01494     return cpl_error_get_code();
01495 }
01496 
01497 /*---------------------------------------------------------------------------*/
01551 /*---------------------------------------------------------------------------*/
01552 cpl_error_code
01553 detmon_lg_fill_parlist(cpl_parameterlist * parlist,
01554                           const char *recipe_name, const char *pipeline_name,
01555               const char *method,
01556                           int order,
01557                           double kappa,
01558                           int niter,
01559                           int llx,
01560                           int lly,
01561                           int urx,
01562                           int ury,
01563                           int ref_level,
01564                           const char *intermediate,
01565                           const char *autocorr,
01566                           const char *collapse,
01567                           const char *rescale,
01568                   const char *pix2pix,
01569                   const char *bpmbin,
01570                           int filter,
01571                           int m,
01572                           int n,
01573                   double tolerance,
01574                   const char *pafgen,
01575                   const char * pafname,
01576                           int llx1,
01577                           int lly1,
01578                           int urx1,
01579                           int ury1,
01580                           int llx2,
01581                           int lly2,
01582                           int urx2,
01583                           int ury2,
01584                           int llx3,
01585                           int lly3,
01586                           int urx3,
01587                           int ury3,
01588                           int llx4,
01589                           int lly4,
01590                           int urx4,
01591                           int ury4,
01592                   int llx5, int lly5, int urx5, int ury5, int exts,
01593                           cpl_boolean opt_nir)
01594 {
01595     const cpl_error_code error =
01596     detmon_fill_parlist(parlist, recipe_name, pipeline_name, 25,
01597                    "method",
01598                    "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
01599                                    "CPL_TYPE_STRING", method,
01600 
01601                                "order",
01602                                "Polynomial order for the fit (Linearity)",
01603                                "CPL_TYPE_INT", order,
01604                                "kappa",
01605                                "Kappa value for the kappa-sigma clipping (Gain)",
01606                                "CPL_TYPE_DOUBLE", kappa,
01607                                "niter",
01608                                "Number of iterations to compute rms (Gain)",
01609                                "CPL_TYPE_INT", niter,
01610                                "llx",
01611                                "x coordinate of the lower-left "
01612                                "point of the region of interest. If not modified, default value will be 1.",
01613                                "CPL_TYPE_INT", llx,
01614                                "lly",
01615                                "y coordinate of the lower-left "
01616                                "point of the region of interest. If not modified, default value will be 1.",
01617                                "CPL_TYPE_INT", lly,
01618                                "urx",
01619                                "x coordinate of the upper-right "
01620                                "point of the region of interest. If not modified, default value will be X dimension of the input image.",
01621                                "CPL_TYPE_INT", urx,
01622                                "ury",
01623                                "y coordinate of the upper-right "
01624                                "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
01625                                "CPL_TYPE_INT", ury,
01626                                "ref_level",
01627                                "User reference level",
01628                                "CPL_TYPE_INT", ref_level,
01629                                "intermediate",
01630                                "De-/Activate intermediate products",
01631                                "CPL_TYPE_BOOL", intermediate,
01632                                
01633                                "autocorr",
01634                                "De-/Activate the autocorr option",
01635                                "CPL_TYPE_BOOL", autocorr,
01636                                
01637                                "collapse",
01638                                "De-/Activate the collapse option",
01639                                "CPL_TYPE_BOOL", collapse,
01640                                "rescale",
01641                                "De-/Activate the image rescale option",
01642                                "CPL_TYPE_BOOL", rescale,
01643                    "pix2pix",
01644                                "De-/Activate the computation with pixel to pixel accuracy",
01645                                "CPL_TYPE_BOOL", pix2pix,
01646                    "bpmbin",
01647                                "De-/Activate the binary bpm option",
01648                                "CPL_TYPE_BOOL", bpmbin,
01649                                "m",
01650                                "Maximum x-shift for the autocorr",
01651                                "CPL_TYPE_INT", m,
01652                                "filter",
01653                                "Upper limit of Median flux to be filtered",
01654                                "CPL_TYPE_INT", filter,
01655                                "n",
01656                                "Maximum y-shift for the autocorr",
01657                    "CPL_TYPE_INT", n,
01658                                "tolerance",
01659                                "Tolerance for pair discrimination",
01660                    "CPL_TYPE_DOUBLE", tolerance,
01661 
01662                                "pafgen",
01663                                "Generate PAF file",
01664                    "CPL_TYPE_BOOL", pafgen,
01665                                "pafname",
01666                                "Specific name for PAF file",
01667                    "CPL_TYPE_STRING", pafname,
01668 
01669 
01670                                "exts",
01671                                "Activate the multi-exts option. Choose -1 to process all extensions. Choose an extension number"
01672                                " to process the appropriate extension.",
01673                                "CPL_TYPE_INT", exts,
01674 
01675                                "fpn_method",
01676                                "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
01677                                "CPL_TYPE_STRING", "HISTOGRAM",
01678 
01679                                "fpn_smooth",
01680                                "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
01681                                "CPL_TYPE_INT", 13,
01682 
01683                                "saturation_limit",
01684                                "all frames with mean saturation above the limit would not be used in calculation",
01685                                "CPL_TYPE_DOUBLE", 65535.0
01686     );
01687    detmon_fill_parlist(parlist, recipe_name, pipeline_name, 1,
01688                                "coeffs_cube_split",
01689                                "if TRUE, the recipe writes as many "
01690                                "COEFFS_CUBE_Pi (i=0..order) as the value of "
01691                                "the order parameter in a separate file",
01692                                "CPL_TYPE_BOOL", "CPL_FALSE");
01693     /* OPT specific parameters */
01694     if(opt_nir == FALSE) {
01695         const cpl_error_code erroropt =
01696         detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
01697                                "llx1",
01698                                "x coord of the lower-left point of the first "
01699                                "field used for contamination measurement. If not modified, default value will be 1.",
01700                                "CPL_TYPE_INT", llx1,
01701                                "lly1",
01702                                "y coord of the lower-left point of the first "
01703                                "field used for contamination measurement. If not modified, default value will be 1.",
01704                                "CPL_TYPE_INT", lly1,
01705                                "urx1",
01706                                "x coord of the upper-right point of the first "
01707                                "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
01708                                "CPL_TYPE_INT", urx1,
01709                                "ury1",
01710                                "y coord of the upper-right point of the first "
01711                                "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01712                                "CPL_TYPE_INT", ury1,
01713                                "llx2",
01714                                "x coord of the lower-left point of the second "
01715                                "field used for contamination measurement. If not modified, default value will be 1.",
01716                                "CPL_TYPE_INT", llx2,
01717                                "lly2",
01718                                "y coord of the lower-left point of the second "
01719                                "field used for contamination measurement. If not modified, default value will be 1.",
01720                                "CPL_TYPE_INT", lly2,
01721                                "urx2",
01722                                "x coord of the upper-right point of the second "
01723                                "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01724                                "CPL_TYPE_INT", urx2,
01725                                "ury2",
01726                                "y coord of the upper-right point of the second "
01727                                "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01728                                "CPL_TYPE_INT", ury2,
01729                                "llx3",
01730                                "x coord of the lower-left point of the third "
01731                                "field used for contamination measurement. If not modified, default value will be 1.",
01732                                "CPL_TYPE_INT", llx3,
01733                                "lly3",
01734                                "y coord of the lower-left point of the third "
01735                                "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01736                                "CPL_TYPE_INT", lly3,
01737                                "urx3",
01738                                "x coord of the upper-right point of the third "
01739                                "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01740                                "CPL_TYPE_INT", urx3,
01741                                "ury3",
01742                                "y coord of the upper-right point of the third "
01743                                "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
01744                                "CPL_TYPE_INT", ury3,
01745                                "llx4",
01746                                "x coord of the lower-left point of the fourth "
01747                                "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01748                                "CPL_TYPE_INT", llx4,
01749                                "lly4",
01750                                "y coord of the lower-left point of the fourth "
01751                                "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01752                                "CPL_TYPE_INT", lly4,
01753                                "urx4",
01754                                "x coord of the upper-right point of the fourth "
01755                                "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01756                                "CPL_TYPE_INT", urx4,
01757                                "ury4",
01758                                "y coord of the upper-right point of the fourth "
01759                                "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01760                                "CPL_TYPE_INT", ury4,
01761                                "llx5",
01762                                "x coord of the lower-left point of the fifth "
01763                                "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01764                                "CPL_TYPE_INT", llx5,
01765                                "lly5",
01766                                "y coord of the lower-left point of the fifth "
01767                                "field used for contamination measurement. If not modified, default value will be 1.",
01768                                "CPL_TYPE_INT", lly5,
01769                                "urx5",
01770                                "x coord of the upper-right point of the fifth "
01771                                "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01772                                "CPL_TYPE_INT", urx5,
01773 
01774                                "ury5",
01775                                "y coord of the upper-right point of the fifth "
01776                                "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
01777                    "CPL_TYPE_INT", ury5);
01778         cpl_ensure_code(!erroropt, erroropt);
01779     }
01780 
01781     cpl_ensure_code(!error, error);
01782 
01783     return cpl_error_get_code();
01784 }
01785 
01786 /*---------------------------------------------------------------------------*/
01795 /*---------------------------------------------------------------------------*/
01796 static cpl_error_code
01797 detmon_lg_retrieve_parlist(const char              * pipeline_name,
01798                   const char              * recipe_name,
01799                   const cpl_parameterlist * parlist,
01800                   cpl_boolean               opt_nir)
01801 {
01802 
01803     char                   * par_name;
01804     cpl_parameter          * par;
01805 
01806     /* --method */
01807     par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
01808     assert(par_name != NULL);
01809     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01810     detmon_lg_config.method = cpl_parameter_get_string(par);
01811     cpl_free(par_name);
01812 
01813     /* --order */
01814     detmon_lg_config.order =
01815         detmon_retrieve_par_int("order", pipeline_name, recipe_name,
01816                                    parlist);
01817 
01818     /* --kappa */
01819     detmon_lg_config.kappa =
01820         detmon_retrieve_par_double("kappa", pipeline_name, recipe_name,
01821                                    parlist);
01822 
01823     /* --niter */
01824     detmon_lg_config.niter =
01825         detmon_retrieve_par_int("niter", pipeline_name, recipe_name,
01826                                    parlist);
01827 
01828     /* --llx */
01829     detmon_lg_config.llx =
01830         detmon_retrieve_par_int("llx", pipeline_name, recipe_name,
01831                                    parlist);
01832 
01833     /* --lly */
01834     detmon_lg_config.lly =
01835         detmon_retrieve_par_int("lly", pipeline_name, recipe_name,
01836                                    parlist);
01837 
01838     /* --urx */
01839     detmon_lg_config.urx =
01840         detmon_retrieve_par_int("urx", pipeline_name, recipe_name,
01841                                    parlist);
01842 
01843     /* --ury */
01844     detmon_lg_config.ury =
01845         detmon_retrieve_par_int("ury", pipeline_name, recipe_name,
01846                                    parlist);
01847 
01848     /* --ref_level */
01849     detmon_lg_config.ref_level =
01850         detmon_retrieve_par_int("ref_level", pipeline_name, recipe_name,
01851                                    parlist);
01852 
01853     /* --intermediate */
01854     par_name =
01855         cpl_sprintf("%s.%s.intermediate", pipeline_name, recipe_name);
01856     assert(par_name != NULL);
01857     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01858     detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
01859     cpl_free(par_name);
01860 
01861     /* --autocorr */
01862     par_name = cpl_sprintf("%s.%s.autocorr", pipeline_name, recipe_name);
01863     assert(par_name != NULL);
01864     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01865     detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
01866     cpl_free(par_name);
01867     
01868     /* --coeffs_cube_split */
01869     par_name = cpl_sprintf("%s.%s.coeffs_cube_split", pipeline_name, recipe_name);
01870     assert(par_name != NULL);
01871     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01872     detmon_lg_config.split_coeffs = cpl_parameter_get_bool(par);
01873     cpl_free(par_name);
01874     
01875     /* --collapse */
01876     par_name = cpl_sprintf("%s.%s.collapse", pipeline_name, recipe_name);
01877     assert(par_name != NULL);
01878     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01879     detmon_lg_config.collapse = cpl_parameter_get_bool(par);
01880     cpl_free(par_name);
01881 
01882     /* --rescale */
01883     par_name = cpl_sprintf("%s.%s.rescale", pipeline_name, recipe_name);
01884     assert(par_name != NULL);
01885     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01886     detmon_lg_config.rescale = cpl_parameter_get_bool(par);
01887     cpl_free(par_name);
01888 
01889     /* --pix2pix */
01890     par_name = cpl_sprintf("%s.%s.pix2pix", pipeline_name, recipe_name);
01891     assert(par_name != NULL);
01892     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01893     detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
01894     cpl_free(par_name);
01895 
01896     /* --bpmbin */
01897     par_name = cpl_sprintf("%s.%s.bpmbin", pipeline_name, recipe_name);
01898     assert(par_name != NULL);
01899     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01900     detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
01901     cpl_free(par_name);
01902 
01903     /* --filter */
01904     detmon_lg_config.filter =
01905         detmon_retrieve_par_int("filter", pipeline_name,
01906                                    recipe_name, parlist);
01907 
01908     /* --m */
01909     detmon_lg_config.m =
01910         detmon_retrieve_par_int("m", pipeline_name, recipe_name, parlist);
01911 
01912     /* --n */
01913     detmon_lg_config.n =
01914         detmon_retrieve_par_int("n", pipeline_name, recipe_name, parlist);
01915 
01916     /* --tolerance */
01917     par_name = cpl_sprintf("%s.%s.tolerance", pipeline_name, recipe_name);
01918     assert(par_name != NULL);
01919     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01920     detmon_lg_config.tolerance = cpl_parameter_get_double(par);
01921     cpl_free(par_name);
01922 
01923 
01924     /* --pafgen */
01925     par_name = cpl_sprintf("%s.%s.pafgen", pipeline_name, recipe_name);
01926     assert(par_name != NULL);
01927     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01928     detmon_lg_config.pafgen = cpl_parameter_get_bool(par);
01929     cpl_free(par_name);
01930 
01931     /* --pafname */
01932     par_name = cpl_sprintf("%s.%s.pafname", pipeline_name, recipe_name);
01933     assert(par_name != NULL);
01934     par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01935     detmon_lg_config.pafname = cpl_parameter_get_string(par);
01936     cpl_free(par_name);
01937 
01938     if(opt_nir == OPT) {
01939     /* --llx1 */
01940     detmon_lg_config.llx1 =
01941         detmon_retrieve_par_int("llx1", pipeline_name, recipe_name,
01942                        parlist);
01943 
01944     /* --lly1 */
01945     detmon_lg_config.lly1 =
01946         detmon_retrieve_par_int("lly1", pipeline_name, recipe_name,
01947                        parlist);
01948 
01949     /* --urx1 */
01950     detmon_lg_config.urx1 =
01951         detmon_retrieve_par_int("urx1", pipeline_name, recipe_name,
01952                        parlist);
01953 
01954     /* --ury1 */
01955     detmon_lg_config.ury1 =
01956         detmon_retrieve_par_int("ury1", pipeline_name, recipe_name,
01957                        parlist);
01958 
01959     /* --llx2 */
01960     detmon_lg_config.llx2 =
01961         detmon_retrieve_par_int("llx2", pipeline_name, recipe_name,
01962                        parlist);
01963 
01964     /* --lly2 */
01965     detmon_lg_config.lly2 =
01966         detmon_retrieve_par_int("lly2", pipeline_name, recipe_name,
01967                        parlist);
01968 
01969     /* --urx2 */
01970     detmon_lg_config.urx2 =
01971         detmon_retrieve_par_int("urx2", pipeline_name, recipe_name,
01972                        parlist);
01973 
01974     /* --ury2 */
01975     detmon_lg_config.ury2 =
01976         detmon_retrieve_par_int("ury2", pipeline_name, recipe_name,
01977                        parlist);
01978 
01979     /* --llx3 */
01980     detmon_lg_config.llx3 =
01981         detmon_retrieve_par_int("llx3", pipeline_name, recipe_name,
01982                        parlist);
01983 
01984     /* --lly3 */
01985     detmon_lg_config.lly3 =
01986         detmon_retrieve_par_int("lly3", pipeline_name, recipe_name,
01987                        parlist);
01988 
01989     /* --urx3 */
01990     detmon_lg_config.urx3 =
01991         detmon_retrieve_par_int("urx3", pipeline_name, recipe_name,
01992                        parlist);
01993 
01994     /* --ury3 */
01995     detmon_lg_config.ury3 =
01996         detmon_retrieve_par_int("ury3", pipeline_name, recipe_name,
01997                        parlist);
01998 
01999     /* --llx4 */
02000     detmon_lg_config.llx4 =
02001         detmon_retrieve_par_int("llx4", pipeline_name, recipe_name,
02002                        parlist);
02003 
02004     /* --lly4 */
02005     detmon_lg_config.lly4 =
02006         detmon_retrieve_par_int("lly4", pipeline_name, recipe_name,
02007                        parlist);
02008 
02009     /* --urx4 */
02010     detmon_lg_config.urx4 =
02011         detmon_retrieve_par_int("urx4", pipeline_name, recipe_name,
02012                        parlist);
02013 
02014     /* --ury4 */
02015     detmon_lg_config.ury4 =
02016         detmon_retrieve_par_int("ury4", pipeline_name, recipe_name,
02017                        parlist);
02018 
02019     /* --llx5 */
02020     detmon_lg_config.llx5 =
02021         detmon_retrieve_par_int("llx5", pipeline_name, recipe_name,
02022                        parlist);
02023 
02024     /* --lly5 */
02025     detmon_lg_config.lly5 =
02026         detmon_retrieve_par_int("lly5", pipeline_name, recipe_name,
02027                        parlist);
02028 
02029     /* --urx5 */
02030     detmon_lg_config.urx5 =
02031         detmon_retrieve_par_int("urx5", pipeline_name, recipe_name,
02032                        parlist);
02033 
02034     /* --ury5 */
02035     detmon_lg_config.ury5 =
02036         detmon_retrieve_par_int("ury5", pipeline_name, recipe_name,
02037                        parlist);
02038     }
02039 
02040     /* --exts */
02041     detmon_lg_config.exts =
02042         detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
02043                                    parlist);
02044     /* --fpn_method */
02045     {
02046         const char* str_method = 0;
02047         detmon_lg_config.fpn_method = FPN_HISTOGRAM;
02048         par_name =
02049             cpl_sprintf("%s.%s.fpn_method", pipeline_name, recipe_name);
02050         assert(par_name != NULL);
02051         par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
02052         if (par)
02053         {
02054             str_method = cpl_parameter_get_string(par);
02055             if (strcmp(str_method, "SMOOTH") == 0)
02056             {
02057                 detmon_lg_config.fpn_method = FPN_SMOOTH;
02058             }
02059             else if (strcmp(str_method, "HISTOGRAM") == 0)
02060             {
02061                 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
02062             }
02063         }
02064         cpl_free(par_name);
02065     }
02066     /* --fpn_smooth */
02067     detmon_lg_config.fpn_smooth =
02068         detmon_retrieve_par_int("fpn_smooth", pipeline_name, recipe_name,
02069                                    parlist);
02070     /* --saturation_limit*/
02071     {
02072         detmon_lg_config.saturation_limit = 65535;
02073         par_name =
02074             cpl_sprintf("%s.%s.saturation_limit", pipeline_name, recipe_name);
02075         assert(par_name != NULL);
02076         par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
02077         if (par)
02078         {
02079             detmon_lg_config.saturation_limit  = cpl_parameter_get_double(par);
02080         }
02081         cpl_free(par_name);
02082     }
02083     if(cpl_error_get_code())
02084     {
02085         cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
02086         cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
02087     }
02088 
02089 
02090     return cpl_error_get_code();
02091 }
02092 
02093 /*---------------------------------------------------------------------------*/
02099 /*---------------------------------------------------------------------------*/
02100 static cpl_error_code
02101 detmon_lg_check_defaults(const cpl_image * reference)
02102 {
02103     const int               nx = cpl_image_get_size_x(reference);
02104     const int               ny = cpl_image_get_size_y(reference);
02105 
02106     detmon_lg_config.nx = nx;
02107     detmon_lg_config.ny = ny;
02108 
02109     detmon_lg_config.wholechip = CPL_FALSE;
02110 
02111     if(detmon_lg_config.llx == -1)
02112         detmon_lg_config.llx = 1;
02113     if(detmon_lg_config.lly == -1)
02114         detmon_lg_config.lly = 1;
02115     if(detmon_lg_config.urx == -1)
02116         detmon_lg_config.urx = nx;
02117     if(detmon_lg_config.ury == -1)
02118         detmon_lg_config.ury = ny;
02119 
02120     if (detmon_lg_config.llx == 1  &&
02121     detmon_lg_config.lly == 1  &&
02122     detmon_lg_config.urx == nx &&
02123     detmon_lg_config.ury == ny)
02124     detmon_lg_config.wholechip = CPL_TRUE;
02125 
02126     if(detmon_lg_config.llx1 == -1)
02127         detmon_lg_config.llx1 = 1;
02128     if(detmon_lg_config.lly1 == -1)
02129         detmon_lg_config.lly1 = 1;
02130     if(detmon_lg_config.urx1 == -1)
02131         detmon_lg_config.urx1 = nx;
02132     if(detmon_lg_config.ury1 == -1)
02133         detmon_lg_config.ury1 = ny;
02134 
02135     if(detmon_lg_config.llx2 == -1)
02136         detmon_lg_config.llx2 = 1;
02137     if(detmon_lg_config.lly2 == -1)
02138         detmon_lg_config.lly2 = 1;
02139     if(detmon_lg_config.urx2 == -1)
02140         detmon_lg_config.urx2 = nx / 2;
02141     if(detmon_lg_config.ury2 == -1)
02142         detmon_lg_config.ury2 = ny / 2;
02143 
02144     if(detmon_lg_config.llx3 == -1)
02145         detmon_lg_config.llx3 = 1;
02146     if(detmon_lg_config.lly3 == -1)
02147         detmon_lg_config.lly3 = ny / 2;
02148     if(detmon_lg_config.urx3 == -1)
02149         detmon_lg_config.urx3 = nx / 2;
02150     if(detmon_lg_config.ury3 == -1)
02151         detmon_lg_config.ury3 = ny;
02152 
02153     if(detmon_lg_config.llx4 == -1)
02154         detmon_lg_config.llx4 = nx / 2;
02155     if(detmon_lg_config.lly4 == -1)
02156         detmon_lg_config.lly4 = ny / 2;
02157     if(detmon_lg_config.urx4 == -1)
02158         detmon_lg_config.urx4 = nx;
02159     if(detmon_lg_config.ury4 == -1)
02160         detmon_lg_config.ury4 = ny;
02161 
02162     if(detmon_lg_config.llx5 == -1)
02163         detmon_lg_config.llx5 = nx / 2;
02164     if(detmon_lg_config.lly5 == -1)
02165         detmon_lg_config.lly5 = 1;
02166     if(detmon_lg_config.urx5 == -1)
02167         detmon_lg_config.urx5 = nx;
02168     if(detmon_lg_config.ury5 == -1)
02169         detmon_lg_config.ury5 = ny / 2;
02170 
02171     if(detmon_lg_config.intermediate == TRUE) {
02172         cpl_msg_warning(cpl_func, "PLEASE NOTE: The --intermediate option saves the difference and correlation images produced during autocorrelation computation. Therefore, --autocorr option has been automatically activated. If you didn't want to run this, please abort and rerun.");
02173         detmon_lg_config.autocorr = TRUE;
02174     }
02175 
02176 
02177     detmon_lg_config.lamp_stability = 0.0;
02178 
02179     detmon_lg_config.lamp_ok = FALSE;
02180 
02181     detmon_lg_config.cr = 0.0;
02182 
02183     return cpl_error_get_code();
02184 }
02185 
02186 /*---------------------------------------------------------------------------*/
02197 /*---------------------------------------------------------------------------*/
02198 static cpl_error_code
02199 detmon_lg_split_onoff(const cpl_frameset * cur_fset,
02200                              cpl_frameset * cur_fset_on,
02201                              cpl_frameset * cur_fset_off,
02202                              const char *tag_on,
02203                              const char *tag_off)
02204 {
02205     int                     nframes;
02206     int                     i;
02207 
02208     const cpl_frame * first;
02209     const cpl_frame * second;
02210 
02211     const char * first_tag;
02212     const char * second_tag;
02213 
02214     cpl_frame * cur_frame_dup = NULL;
02215 
02216     skip_if((first   = cpl_frameset_get_first_const(cur_fset)) == NULL);
02217     skip_if((second  = cpl_frameset_get_next_const (cur_fset)) == NULL);
02218 
02219     skip_if((first_tag  = cpl_frame_get_tag(first))  == NULL);
02220     skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
02221 
02222 #if 0
02223     if (opt_nir == OPT &&
02224     ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
02225      (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
02226     detmon_lg_config.lamp_ok = TRUE;
02227     }
02228 #endif
02229 
02230     nframes = cpl_frameset_get_size(cur_fset);
02231     for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
02232         const cpl_frame * cur_frame =
02233         cpl_frameset_get_frame_const(cur_fset, i);
02234     char            * tag;
02235 
02236         /* Duplication is required for insertion to a different frameset */
02237         cur_frame_dup = cpl_frame_duplicate(cur_frame);
02238         tag = (char *) cpl_frame_get_tag(cur_frame_dup);
02239 
02240         /* Insertion in the corresponding sub-frameset */
02241         if(!strcmp(tag, tag_on)) {
02242             skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
02243         } else if(!strcmp(tag, tag_off)) {
02244             skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
02245         } else {
02246             cpl_frame_delete(cur_frame_dup);
02247         cur_frame_dup = NULL;
02248         }
02249     }
02250     cur_frame_dup = NULL;
02251 
02252     end_skip;
02253 
02254     cpl_frame_delete(cur_frame_dup);
02255 
02256     return cpl_error_get_code();
02257 }
02258 
02259 /*--------------------------------------------------------------------------*/
02281 /*--------------------------------------------------------------------------*/
02282 
02283 static cpl_error_code
02284 detmon_lg_reduce(const cpl_frameset * set_on,
02285                         const cpl_frameset * set_off,
02286                         int* index_on, int* index_off, double* exptime_on, double* exptime_off,
02287                         int *next_index_on, int* next_index_off,
02288                         cpl_imagelist ** coeffs_ptr,
02289                         cpl_table * gain_table,
02290                         cpl_table * linear_table,
02291                         cpl_image ** bpm_ptr,
02292                         cpl_imagelist * autocorr_images,
02293                         cpl_imagelist * diff_flats,
02294                         cpl_propertylist * gaint_qclist,
02295                         cpl_propertylist * lint_qclist,
02296                         cpl_propertylist * linc_qclist,
02297                         cpl_propertylist * bpm_qclist,
02298          int                    (* load_fset) (const cpl_frameset *,
02299                                cpl_type,
02300                                                cpl_imagelist *),
02301             const cpl_boolean opt_nir,
02302                         int whichext)
02303 {
02304     const double D_INVALID_VALUE = -999;
02305     int                     i;
02306     cpl_imagelist         * linearity_inputs = NULL;
02307     cpl_imagelist         * opt_offs = NULL;
02308     int                     nsets;
02309     cpl_propertylist      * reflist = NULL;
02310     int dit_nskip=0;
02311     int rows_affected = 1;
02312     int last_best = 0;
02313     /* Test entries */
02314     cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02315     cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02316 
02317     nsets = cpl_frameset_get_size(set_on) / 2;
02318 
02319     detmon_lg_config.load_fset = load_fset;
02320     if(detmon_lg_config.collapse) {
02321         /*
02322          * When the 'collapse' option is used, there are no OFF pairs. We
02323          * construct a pair with the 2 first raw OFF frames, which will be
02324          * passed for each DIT value, to maintain the same API in the function
02325          * detmon_gain_table_fill_row().
02326          */
02327         const cpl_frame        *first = cpl_frameset_get_first_const(set_off);
02328         cpl_frame              *dup_first = cpl_frame_duplicate(first);
02329 
02330         const cpl_frame        *second = cpl_frameset_get_next_const(set_off);
02331         cpl_frame              *dup_second = cpl_frame_duplicate(second);
02332 
02333         cpl_frameset           *raw_offs = cpl_frameset_new();
02334 
02335         skip_if(cpl_frameset_insert(raw_offs, dup_first));
02336         skip_if(cpl_frameset_insert(raw_offs, dup_second));
02337 
02338         opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
02339                            0, whichext);
02340 
02341         cpl_frameset_delete(raw_offs);
02342 
02343     }
02344 
02345     skip_if(detmon_lg_reduce_init(gain_table,
02346                      linear_table,
02347                      &linearity_inputs,
02348                                  opt_nir));
02349     if (!strcmp(detmon_lg_config.method, "PTC"))
02350     {
02351         cpl_msg_warning(cpl_func, "PTC method incompatible with lamp stability computation");
02352     }
02353     else if(!detmon_lg_config.collapse)
02354     {
02355         skip_if(detmon_lg_lamp_stab(set_on, set_off,
02356                        opt_nir, whichext));
02357     }
02358     /* Unselect all rows, to select only invalid ones */
02359     skip_if(cpl_table_unselect_all(linear_table));
02360     skip_if(cpl_table_unselect_all(gain_table));
02361 
02362     /* Loop on every DIT value */
02363 
02364     for(i = 0; i < nsets ; i++)
02365     {
02366             skip_if(detmon_lg_reduce_dit(set_on,
02367                     index_on, exptime_on,
02368                     i,
02369                     &dit_nskip,
02370                     set_off,
02371                     index_off, exptime_off,
02372                     next_index_on, next_index_off,
02373                     linear_table,
02374                     gain_table, linearity_inputs,
02375                     lint_qclist, opt_nir,
02376                     autocorr_images, diff_flats,
02377                     opt_offs,  whichext,
02378                     &rows_affected));
02379         if (rows_affected == 0)
02380         {
02381             cpl_msg_warning(cpl_func, "The rest frames would not be taken into calculation, check the messages above");
02382             cpl_table_select_row(linear_table, i);
02383             cpl_table_select_row(gain_table, i);
02384         }
02385         else
02386         {
02387             last_best = i;
02388         }
02389     }
02390     skip_if(detmon_add_adl_column(linear_table, opt_nir));
02391 
02392     /*
02393      * Removal of rows corresponding to frames above --filter threshold.
02394      * See calls to cpl_table_select_row() in detmon_lg_reduce_dit().
02395      */
02396     skip_if(cpl_table_erase_selected(gain_table));
02397     skip_if(cpl_table_erase_selected(linear_table));
02398 
02399     reflist = cpl_propertylist_new();
02400     skip_if(cpl_propertylist_append_bool(reflist, "ADU", FALSE));
02401     skip_if(cpl_table_sort(gain_table, reflist));
02402     /*
02403      * --Final reduction--
02404      * The following call to detmon_lg_reduce_all() makes the
02405      * computations which are over all posible DIT values.
02406      */
02407     skip_if(detmon_lg_reduce_all(linear_table,
02408                     gaint_qclist, lint_qclist, linc_qclist,
02409                     bpm_qclist, coeffs_ptr, bpm_ptr,
02410                     linearity_inputs,
02411                     gain_table, whichext, opt_nir));
02412     {
02413         /*FPN Computation*/
02414         double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
02415 //      cpl_propertylist_append_int(gaint_qclist, "NNNEXT", whichext);      
02416 //      cpl_msg_warning(cpl_func, "---------- ext %i" , whichext);
02417         cpl_error_code cplerr = cpl_error_get_code();
02418         if (cplerr != CPL_ERROR_NONE || (gain == 0.0))
02419         {
02420             cpl_msg_warning(cpl_func, "Cannot read gain from QC parameters - FPN will not be computed");
02421             cpl_error_reset();
02422         }
02423         else
02424         {
02425         detmon_fpn_compute(set_on, index_on, last_best, lint_qclist,
02426                 detmon_lg_config.llx,
02427                 detmon_lg_config.lly,
02428                 detmon_lg_config.urx,
02429                 detmon_lg_config.ury,
02430                 gain,
02431                 whichext,
02432                 detmon_lg_config.fpn_method,
02433                 detmon_lg_config.fpn_smooth);
02434         }
02435     }
02436   /* change NaN in the gain table to the invalid value D_INVALID_VALUE*/
02437 
02438   detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
02439   end_skip;
02440   cpl_imagelist_delete(linearity_inputs);
02441   cpl_imagelist_delete(opt_offs);
02442   cpl_propertylist_delete(reflist);
02443 
02444   return cpl_error_get_code();
02445 }
02446 
02447 static cpl_error_code detmon_table_fill_invalid(cpl_table* ptable, double code)
02448 {
02449     int ncols = cpl_table_get_ncol(ptable);
02450     cpl_array* pnames = cpl_table_get_column_names(ptable);
02451     int nrows = cpl_table_get_nrow(ptable);
02452     int i = 0;
02453     for (i=0; i < ncols; i++)
02454     {
02455         int j = 0;
02456         for (j = 0; j< nrows; j++)
02457         {
02458             const char* colname = cpl_array_get_data_string_const(pnames)[i];
02459             int isnull;
02460             cpl_type type = cpl_table_get_column_type(ptable, colname);
02461             cpl_table_get(ptable, colname, j, &isnull);
02462             if(isnull == 1)
02463             {
02464                 if (type == CPL_TYPE_DOUBLE)
02465                 {
02466                     cpl_table_set(ptable,colname,j, code);
02467                 }
02468                 else if (type == CPL_TYPE_FLOAT)
02469                 {
02470                     cpl_table_set_float(ptable,colname,j, (float)code);
02471                 }
02472             }
02473         }
02474     }
02475     cpl_array_delete(pnames);
02476     return cpl_error_get_code();
02477 }
02478 
02479 static cpl_error_code
02480 detmon_fpn_compute(const cpl_frameset *set_on,
02481         int * index_on,
02482         int last_best,
02483         cpl_propertylist *lint_qclist,
02484         int llx,
02485         int lly,
02486         int urx,
02487         int ury,
02488         double gain,
02489         int whichext,
02490         FPN_METHOD fpn_method,
02491         int smooth_size)
02492 {
02493     double fpn = 0;
02494     const cpl_image* im1 = 0;
02495     int range[4];
02496     cpl_imagelist* ons = 0;
02497     cpl_frameset          * pair_on = 0;
02498     int nsets_extracted = cpl_frameset_get_size(set_on);
02499     cpl_size * selection = NULL;
02500     double mse = 0;
02501     range[0] = llx;
02502     range[1] = lly;
02503     range[2] = urx;
02504     range[3] = ury;
02505 
02506     /* Retrieve 2 ON frames with the highest DIT -
02507      * the last best 2 values in the index*/
02508     selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
02509     memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
02510 
02511     selection[index_on[last_best*2 + 0] ] = 1;
02512     selection[index_on[last_best*2 + 1] ] = 1;
02513      pair_on = cpl_frameset_extract(set_on, selection, 1);
02514      ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
02515 
02516     skip_if(ons == NULL);
02517     skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
02518 
02519     fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
02520     skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
02521                                fpn));
02522     skip_if(cpl_propertylist_append_double(lint_qclist, "ESO QC GAIN ERR",
02523                                mse));
02524 
02525   end_skip;
02526     cpl_frameset_delete(pair_on);
02527     cpl_imagelist_delete(ons);
02528     cpl_free(selection);
02529     return cpl_error_get_code();
02530 }
02531 
02532 /*--------------------------------------------------------------------------*/
02540 /*--------------------------------------------------------------------------*/
02541 static cpl_error_code
02542 detmon_lg_lamp_stab(const cpl_frameset * lamps,
02543                const cpl_frameset * darks,
02544                            cpl_boolean          opt_nir,
02545                            int                  whichext)
02546 {
02547     /*
02548      * NOTE:
02549      * Most of this code is copied (and modified) from
02550      * isaac_img_detlin_load(), in isaac_img_detlin.c v.1.25
02551      */
02552 
02553     int                     nb_lamps;
02554 
02555     cpl_vector          *   selection = NULL;
02556     cpl_propertylist    *   plist;
02557     double                  dit_lamp, dit_dark;
02558     int                     dit_stab;
02559     cpl_imagelist       *   lamps_data = NULL;
02560     cpl_imagelist       *   darks_data = NULL;
02561     double              *   stab_levels = NULL;
02562     int                     i, j;
02563     double              *   ditvals = NULL;
02564     int                     last_stab = 0; /* Avoid false uninit warning */
02565 
02566     /* Check that there are as many lamp as darks */
02567     cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
02568             CPL_ERROR_ILLEGAL_INPUT);
02569     cpl_ensure_code(cpl_frameset_get_size(darks) == nb_lamps,
02570                 CPL_ERROR_ILLEGAL_INPUT);
02571 
02572     /* Check out that they have consistent integration times */
02573     cpl_msg_info(__func__, "Checking DIT consistency");
02574     selection = cpl_vector_new(nb_lamps);
02575     ditvals = cpl_malloc(nb_lamps * sizeof(double));
02576     dit_stab = 0;
02577     for (i = 0; i < nb_lamps; i++) {
02578     const cpl_frame           * c_lamp;
02579     const cpl_frame           * c_dark;
02580         /* Check if ok */
02581         skip_if (cpl_error_get_code());
02582 
02583         /* DIT from LAMP */
02584         c_lamp = cpl_frameset_get_frame_const(lamps, i);
02585         plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
02586     if(opt_nir)
02587         dit_lamp = (double)irplib_pfits_get_dit(plist);
02588     else
02589         dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
02590         cpl_propertylist_delete(plist);
02591         skip_if (cpl_error_get_code());
02592 
02593         /* DIT from DARK */
02594         c_dark = cpl_frameset_get_frame_const(darks, i);
02595         plist  = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
02596     if(opt_nir)
02597         dit_dark = (double)irplib_pfits_get_dit(plist);
02598     else
02599         dit_dark = (double)irplib_pfits_get_dit_opt(plist);
02600         cpl_propertylist_delete(plist);
02601         skip_if (cpl_error_get_code());
02602 
02603         /* Check consistency */
02604         if (fabs(dit_dark-dit_lamp) > 1e-3) {
02605             cpl_msg_error(__func__, "DIT not consistent between LAMP and DARK");
02606         /* FIXME: Should an error code be set here? */
02607         skip_if(1);
02608         }
02609         ditvals[i] = dit_lamp;
02610         /* Set selection */
02611         if (i==0) {
02612             cpl_vector_set(selection, i, -1.0);
02613             dit_stab ++;
02614         last_stab = 0;
02615         } else {
02616         /*
02617          * The second condition is to make sure that frames taken into
02618          * account for lamp stability are not consecutive.
02619          */
02620             if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
02621                 cpl_vector_set(selection, i, -1.0);
02622                 dit_stab ++;
02623         last_stab = i;
02624             } else {
02625                 cpl_vector_set(selection, i, 1.0);
02626             }
02627         }
02628     }
02629 
02630     /* Check if there are enough DITs for stability check */
02631     if (dit_stab < 2) {
02632         cpl_msg_info(__func__, "Not enough frames for stability check");
02633     } else {
02634 
02635     /* Load the data and compute lamp-dark */
02636     cpl_msg_info(__func__, "Compute the differences lamp - dark");
02637     lamps_data = cpl_imagelist_load_frameset(lamps, CPL_TYPE_FLOAT, 1,
02638                          whichext);
02639     darks_data = cpl_imagelist_load_frameset(darks, CPL_TYPE_FLOAT, 1,
02640                          whichext);
02641     skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
02642 
02643     /* Check the lamp stability */
02644     cpl_msg_info(__func__, "Check the lamp stability");
02645     stab_levels = cpl_malloc(dit_stab * sizeof(double));
02646     j = 0;
02647     for (i=0; i<nb_lamps; i++) {
02648         if (cpl_vector_get(selection, i) < 0) {
02649         stab_levels[j] =
02650             cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
02651         j++;
02652         }
02653     }
02654 
02655     /* Compute the lamp stability */
02656     for (i=1; i<dit_stab; i++) {
02657         if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
02658                 detmon_lg_config.lamp_stability)
02659         detmon_lg_config.lamp_stability =
02660             fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
02661     }
02662 
02663 
02664     /* Check the lamp stability */
02665     if (detmon_lg_config.lamp_stability > 0.01) {
02666             cpl_msg_warning(__func__,
02667                 "level difference too high - proceed anyway");
02668     }
02669     }
02670     end_skip;
02671 
02672     cpl_free(ditvals);
02673     cpl_vector_delete(selection);
02674     cpl_imagelist_delete(lamps_data);
02675     cpl_imagelist_delete(darks_data);
02676     cpl_free(stab_levels);
02677 
02678     return cpl_error_get_code();
02679 }
02680 
02681 /*--------------------------------------------------------------------------*/
02704 /*--------------------------------------------------------------------------*/
02705 static cpl_error_code
02706 detmon_lg_reduce_dit(const cpl_frameset * set_on,
02707                 int* index_on, double* exptime_on,
02708                 const int dit_nb,
02709                 int * dit_nskip,
02710                 const cpl_frameset * set_off,
02711                 int * index_off, double* exptime_off,
02712                 int* next_on, int* next_off,
02713                 cpl_table * linear_table,
02714                 cpl_table * gain_table,
02715                 cpl_imagelist * linearity_inputs,
02716                 cpl_propertylist * qclist,
02717                 cpl_boolean opt_nir,
02718                 cpl_imagelist * autocorr_images,
02719                 cpl_imagelist * diff_flats,
02720                 cpl_imagelist * opt_offs,
02721                 int whichext,
02722                 int* rows_affected)
02723 {
02724     cpl_frameset          * pair_on = NULL;
02725     cpl_frameset          * pair_off = NULL;
02726     cpl_imagelist         * ons = NULL;
02727     cpl_imagelist         * offs = NULL;
02728     cpl_boolean             follow = CPL_TRUE;
02729     cpl_imagelist *         masterl = NULL;
02730     unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
02731     double c_dit;
02732     int c_ndit;
02733 
02734     double current_dit = 0;
02735 
02736     const char * filename;
02737 
02738     cpl_propertylist * plist = NULL;
02739     cpl_propertylist* pDETlist = NULL;
02740 
02741     mode = detmon_lg_config.collapse ?
02742     mode | IRPLIB_GAIN_COLLAPSE    | IRPLIB_LIN_COLLAPSE:
02743     mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
02744     mode = detmon_lg_config.pix2pix  ?
02745     mode | IRPLIB_LIN_PIX2PIX : mode;
02746     mode = opt_nir  ?
02747     mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
02748     mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
02749 
02750 
02751     /* ON pair extraction */
02752     skip_if(detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on,  detmon_lg_config.tolerance));
02753     current_dit = exptime_on[*next_on - 1];
02754 
02755     /* Load the ON images */
02756     ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
02757     skip_if(ons == NULL);
02758     cpl_msg_debug(cpl_func, " Loaded ON images: %"  CPL_SIZE_FORMAT 
02759                   ", exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
02760     if(cpl_imagelist_get_size(ons) != 2)
02761     {
02762         cpl_msg_error(cpl_func, "cannot take ON pair, number of images[%" 
02763          CPL_SIZE_FORMAT "]", cpl_imagelist_get_size(ons));
02764         skip_if(TRUE);
02765     }
02766     if(detmon_lg_config.filter > 0)
02767     {
02768         double med1 =
02769             cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
02770                         detmon_lg_config.llx,
02771                         detmon_lg_config.lly,
02772                         detmon_lg_config.urx,
02773                         detmon_lg_config.ury);
02774         double med2 =
02775             cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
02776                         detmon_lg_config.llx,
02777                         detmon_lg_config.lly,
02778                         detmon_lg_config.urx,
02779                         detmon_lg_config.ury);
02780         if ( med1 > (double)detmon_lg_config.filter ||
02781              med2 > (double)detmon_lg_config.filter)
02782             {
02783                 follow = CPL_FALSE;
02784                 cpl_table_select_row(gain_table,   dit_nb);
02785                 cpl_table_select_row(linear_table, dit_nb);
02786                 (*dit_nskip)++;
02787                 cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
02788                         "will not be taken into account for computation "
02789                         "as they are above --filter threshold", dit_nb);
02790             }
02791     }
02792 
02793     if (follow || detmon_lg_config.filter < 0)
02794     {
02795 
02796         /*
02797          * If the --collapse option is not activated by the user, the OFF
02798          * sub-frameset is also supposed to be organized into pairs and,
02799          * therefore, processed as the ON sub-frameset.
02800          */
02801         if(!detmon_lg_config.collapse)
02802         {
02803             if (!strcmp(detmon_lg_config.method, "MED") ||
02804             cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
02805             {
02806                 skip_if(detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off,  detmon_lg_config.tolerance));
02807             }
02808             else
02809             {
02810                 skip_if(detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
02811             }
02812             /* Load the OFF images */
02813             cpl_msg_debug(cpl_func, "  Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
02814             offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
02815 
02816             skip_if(offs == NULL);
02817             skip_if(cpl_error_get_code());
02818         } else
02819         {
02820             /*
02821              * The master bias is required only for
02822              * linearity computation in the OPT domain
02823              */
02824             cpl_image * collapse;
02825             masterl = cpl_imagelist_load_frameset(set_off, CPL_TYPE_FLOAT,
02826                                               1, whichext);
02827             skip_if(masterl == NULL);
02828             skip_if(cpl_error_get_code());
02829 
02830             collapse = cpl_imagelist_collapse_create(masterl);
02831             skip_if(collapse == NULL);
02832             skip_if(cpl_imagelist_set(masterl, collapse, 0));
02833 
02834             /* Any extra error checking needed here? */
02835             offs = (cpl_imagelist *)masterl;
02836         }
02837 
02838         /* Rescaling */
02839         if(detmon_lg_config.rescale)
02840         {
02841             skip_if(detmon_lg_rescale(ons));
02842             if (!detmon_lg_config.collapse &&
02843             !strcmp(detmon_lg_config.method, "MED"))
02844             skip_if(detmon_lg_rescale(offs));
02845         }
02846         /* DIT or EXPTIME value extraction */
02847 
02848         filename =
02849             cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
02850         skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
02851         /* Add columns to the tables DETi WINi UITi*/
02852         if (plist)
02853         {
02854             pDETlist = cpl_propertylist_new();
02855             cpl_propertylist_copy_property_regexp(pDETlist, plist, "DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
02856             if (dit_nb == 0)
02857             {
02858                 irplib_table_create_column(gain_table, pDETlist);
02859                 irplib_table_create_column(linear_table, pDETlist);
02860             }
02861         }
02862         if(opt_nir == NIR) {
02863             c_dit = irplib_pfits_get_dit(plist);
02864             c_ndit = irplib_pfits_get_ndit(plist);
02865         } else {
02866             c_dit = irplib_pfits_get_exptime(plist);
02867             c_ndit=1;
02868         }
02869 
02870         /*
02871          * --GAIN part for each DIT value--
02872          * The following call to detmon_gain_table_fill_row() fills
02873          * in the row nb i
02874          * of the GAIN table (output) and of the FIT table (by-product to be
02875          * used later for the polynomial computation of the GAIN)
02876          */
02877         if(detmon_lg_config.collapse) {
02878             offs = (cpl_imagelist *) opt_offs;
02879         }
02880 
02881         cpl_msg_info(cpl_func, "Computing GAIN for EXPTIME value nb %d",
02882                  dit_nb + 1);
02883 
02884         /* In case PTC is applied, this is allowed */
02885         if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
02886         {
02887             cpl_table_erase_column(gain_table, "MEAN_OFF1");
02888             cpl_table_erase_column(gain_table, "MEAN_OFF2");
02889             cpl_table_erase_column(gain_table, "SIG_OFF_DIF");
02890             cpl_table_erase_column(gain_table, "GAIN");
02891             cpl_table_erase_column(gain_table, "GAIN_CORR");
02892             cpl_table_new_column(gain_table, "MEAN_OFF", CPL_TYPE_DOUBLE);
02893         }
02894 
02895         skip_if(detmon_gain_table_fill_row(gain_table,
02896                               c_dit,c_ndit,
02897                           autocorr_images,
02898                           diff_flats, ons, offs,
02899                           detmon_lg_config.kappa,
02900                           detmon_lg_config.niter,
02901                           detmon_lg_config.llx,
02902                           detmon_lg_config.lly,
02903                           detmon_lg_config.urx,
02904                           detmon_lg_config.ury,
02905                           detmon_lg_config.m,
02906                           detmon_lg_config.n,
02907                           detmon_lg_config.saturation_limit,
02908                           dit_nb, mode, rows_affected));
02909 
02910 
02911         if (*rows_affected)
02912         {
02913             /* fill DETi WINi OPTi columns - see DFS06921*/
02914             skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
02915             /* Linearity reduction */
02916             cpl_msg_info(cpl_func, "Linearity reduction for nb %d",
02917                              dit_nb + 1);
02918             skip_if(detmon_lin_table_fill_row(linear_table, c_dit,
02919                                  linearity_inputs, ons, offs,
02920                                  detmon_lg_config.llx,
02921                                  detmon_lg_config.lly,
02922                                  detmon_lg_config.urx,
02923                                  detmon_lg_config.ury,
02924                                  dit_nb, *dit_nskip, mode));
02925             /* fill DETi WINi OPTi columns - see DFS06921*/
02926             skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
02927         }
02928 
02929 
02930                 /* as we know only at this point if a frame is
02931                    saturated or not, and we would like to compute the
02932                    contamination only on the last non saturated frame,
02933                    we need de facto to compute saturation on any non saturated
02934                    frame, by overwriting the QC parameter. In the end it will
02935                    remain only the last value corresponding to a non saturated
02936                    frame */
02937 
02938         if(opt_nir == OPT &&
02939                    *rows_affected != 0 ) {
02940                    detmon_opt_contamination(ons, offs, mode, qclist);
02941         }
02942 
02943     }
02944 
02945     end_skip;
02946 
02947     cpl_frameset_delete(pair_on);
02948     cpl_imagelist_delete(ons);
02949 
02950     if(!detmon_lg_config.collapse ) {
02951     cpl_imagelist_delete(offs);
02952     }
02953 
02954     if(!detmon_lg_config.collapse) {
02955     cpl_frameset_delete(pair_off);
02956     }
02957 
02958     if(detmon_lg_config.collapse) {
02959     cpl_imagelist_delete(masterl);
02960     }
02961 
02962     cpl_propertylist_delete(plist);
02963     cpl_propertylist_delete(pDETlist);
02964     return cpl_error_get_code();
02965 }
02966 
02967 /*---------------------------------------------------------------------------*/
02973 /*---------------------------------------------------------------------------*/
02974 static cpl_error_code
02975 detmon_add_adl_column(cpl_table * table,
02976                              cpl_boolean opt_nir)
02977 {
02978     cpl_error_code          error;
02979     double                  mean_med_dit;
02980     double                 *dits;
02981 
02982     cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
02983 
02984     mean_med_dit = cpl_table_get_column_mean(table, "MED_DIT");
02985     if (opt_nir == OPT)
02986     dits = cpl_table_get_data_double(table, "EXPTIME");
02987     else
02988     dits = cpl_table_get_data_double(table, "DIT");
02989 
02990     error = cpl_table_copy_data_double(table, "ADL", dits);
02991     cpl_ensure_code(!error, error);
02992     error = cpl_table_multiply_scalar(table, "ADL", mean_med_dit);
02993     cpl_ensure_code(!error, error);
02994 
02995     return cpl_error_get_code();
02996 }
02997 
02998 /*---------------------------------------------------------------------------*/
03006 /*---------------------------------------------------------------------------*/
03007 static cpl_error_code
03008 detmon_lg_reduce_init(cpl_table * gain_table,
03009                              cpl_table * linear_table,
03010                              cpl_imagelist ** linearity_inputs,
03011                              const cpl_boolean opt_nir)
03012 {
03013     skip_if(detmon_gain_table_create(gain_table, opt_nir));
03014     skip_if(detmon_lin_table_create(linear_table, opt_nir));
03015 
03016     if(detmon_lg_config.pix2pix) {
03017     *linearity_inputs = cpl_imagelist_new();
03018     skip_if(*linearity_inputs == NULL);
03019     }
03020 
03021     end_skip;
03022 
03023     return cpl_error_get_code();
03024 }
03025 
03026 /*--------------------------------------------------------------------------*/
03032 /*--------------------------------------------------------------------------*/
03033 static double
03034 irplib_pfits_get_dit(const cpl_propertylist * plist)
03035 {
03036     return irplib_pfits_get_prop_double(plist, "ESO DET DIT");
03037 }
03038 
03039 /*--------------------------------------------------------------------------*/
03045 /*--------------------------------------------------------------------------*/
03046 static double
03047 irplib_pfits_get_dit_opt(const cpl_propertylist * plist)
03048 {
03049     return irplib_pfits_get_prop_double(plist, "ESO DET WIN1 UIT1");
03050 }
03051 
03052 
03053 /*---------------------------------------------------------------------------*/
03058 static cpl_propertylist*
03059 detmon_load_pro_keys(const char* NAME_O)
03060 {
03061    cpl_propertylist* pro_keys=NULL;
03062    pro_keys=cpl_propertylist_load_regexp(NAME_O,0,"^(ESO PRO)",0);
03063    return pro_keys;
03064 }
03065 
03066 
03067 static double irplib_pfits_get_prop_double(const cpl_propertylist * plist, const char* prop_name)
03068 {
03069    double dit;
03070    dit = cpl_propertylist_get_double(plist, prop_name);
03071    if(cpl_error_get_code() != CPL_ERROR_NONE)
03072    {
03073        cpl_msg_error(cpl_func, "Cannot read property '%s', err[%s]",prop_name, cpl_error_get_where());
03074    }
03075    return dit;
03076 }
03077 /*---------------------------------------------------------------------------*/
03109 /*---------------------------------------------------------------------------*/
03110 static cpl_error_code
03111 detmon_gain_table_fill_row(cpl_table * gain_table,
03112                   double c_dit,int c_ndit,
03113                   cpl_imagelist * autocorr_images,
03114                   cpl_imagelist * diff_flats,
03115                   const cpl_imagelist * ons,
03116                                   const cpl_imagelist * offs,
03117                                   double kappa, int nclip,
03118                                   int llx, int lly, int urx, int ury,
03119                                   int m, int n,
03120                                   double saturation_limit,
03121                   const int pos, unsigned mode, int* rows_affected)
03122 {
03123     const cpl_image        *image;
03124     double                  std = 0;
03125     cpl_image              *on_dif = NULL;
03126     cpl_image              *off_dif = NULL;
03127     double                  avg_on1, avg_on2;
03128     double                  avg_off1, avg_off2;
03129     double                  avg_on_dif, sig_on_dif;
03130     double                  avg_off_dif, sig_off_dif;
03131     double                  double_adu, autocorr, gain, gain_corr;
03132     double                  sigma, sigma_corr;
03133 
03134     cpl_table_set(gain_table, "FLAG", pos, 1);
03135     if (mode & IRPLIB_GAIN_NIR)
03136     {
03137         cpl_table_set(gain_table, "DIT", pos, c_dit);
03138         cpl_table_set(gain_table, "NDIT", pos, c_ndit);
03139     } else if (mode & IRPLIB_GAIN_OPT)
03140     {
03141         cpl_table_set(gain_table, "EXPTIME", pos, c_dit);
03142     } else
03143     {
03144         cpl_msg_error(cpl_func, "Mandatory mode (OPT or NIR) not provided");
03145         skip_if(1);
03146     }
03147     if(*rows_affected == 0)
03148     {
03149         cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
03150         cpl_table_set(gain_table, "FLAG", pos, 0);
03151         if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03152         {
03153           autocorr = -1;
03154           if (diff_flats)
03155           {
03156               detmon_lg_add_empty_image(diff_flats, pos);
03157           }
03158           if (autocorr_images)
03159           {
03160               detmon_lg_add_empty_image(autocorr_images, pos);
03161           }
03162         }
03163         return cpl_error_get_code();
03164     }
03165     skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
03166     skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
03167                                          nclip, 1e-5, &avg_on1, &std));
03168     skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
03169     skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
03170                      nclip, 1e-5, &avg_on2, &std));
03171 
03172     if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
03173     {
03174         cpl_msg_warning(cpl_func, "Average saturation is above the limit, the frames would not be taken into calculation");
03175         cpl_msg_warning(cpl_func, "saturation levels [%f ; %f], limit [%f]", avg_on1, avg_on2, saturation_limit);
03176         cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
03177         cpl_table_set(gain_table, "FLAG", pos, 0);
03178         if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03179         {
03180           autocorr = -1;
03181           if (diff_flats)
03182           {
03183               detmon_lg_add_empty_image(diff_flats, pos);
03184           }
03185           if (autocorr_images)
03186           {
03187               detmon_lg_add_empty_image(autocorr_images, pos);
03188           }
03189         }
03190         *rows_affected = 0;
03191     }
03192     else
03193     {
03194         *rows_affected = 1;
03195         skip_if(cpl_table_set_double(gain_table, "MEAN_ON1", pos, avg_on1));
03196         skip_if(cpl_table_set_double(gain_table, "MEAN_ON2", pos, avg_on2));
03197         on_dif =
03198         cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
03199                       cpl_imagelist_get_const(ons, 1));
03200         skip_if(on_dif == NULL);
03201         skip_if(irplib_ksigma_clip(on_dif, llx, lly, urx, ury, kappa,
03202                          nclip, 1e-5,
03203                                              &avg_on_dif, &sig_on_dif));
03204         skip_if(cpl_table_set_double(gain_table, "SIG_ON_DIF", pos, sig_on_dif));
03205 
03206         if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03207         {
03208           if (diff_flats)
03209           {
03210               cpl_image * diff = cpl_image_duplicate(on_dif);
03211               skip_if(cpl_imagelist_set(diff_flats, diff, pos));
03212           }
03213           if (autocorr_images)
03214           {
03215             cpl_image * corr = NULL;
03216             autocorr = detmon_autocorr_factor(on_dif, &corr, m, n);
03217             if(corr)
03218             {
03219                 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
03220             }
03221             else
03222             {
03223                 detmon_lg_add_empty_image(autocorr_images, pos);
03224             }
03225           } else
03226           {
03227             autocorr = detmon_autocorr_factor(on_dif, NULL, m, n);
03228           }
03229           autocorr = isnan(autocorr) ? 1.0 : autocorr;
03230         } else
03231         {
03232             autocorr = 1.0;
03233         }
03234 
03235         if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
03236         {
03237 
03238             skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
03239                        llx, lly, urx, ury, kappa, nclip,
03240                        1e-5, &avg_off1, &std));
03241             skip_if(cpl_table_set_double(gain_table, "MEAN_OFF", pos, avg_off1));
03242 
03243         } else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
03244              ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
03245             skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
03246                                                  llx, lly, urx, ury, kappa, nclip,
03247                                                  1e-5, &avg_off1, &std));
03248             skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
03249             skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
03250                                                  llx, lly, urx, ury, kappa, nclip,
03251                              1e-5, &avg_off2, &std));
03252             skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
03253             off_dif =
03254                 cpl_image_subtract_create(cpl_imagelist_get_const(offs, 0),
03255                                           cpl_imagelist_get_const(offs, 1));
03256             skip_if(off_dif == NULL);
03257             skip_if(irplib_ksigma_clip(off_dif, llx, lly, urx, ury,
03258                                                  kappa, nclip, 1e-5,
03259                              &avg_off_dif, &sig_off_dif));
03260             skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
03261                          pos, sig_off_dif));
03262         } else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
03263         {
03264             int status;
03265             avg_off1 = cpl_table_get_double(gain_table, "MEAN_OFF1", 0, &status);
03266             skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
03267             avg_off2 = cpl_table_get_double(gain_table, "MEAN_OFF2", 0, &status);
03268             skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
03269             sig_off_dif = cpl_table_get_double(gain_table, "SIG_OFF_DIF",
03270                                                0, &status);
03271             skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
03272                                          pos, sig_off_dif));
03273         }
03274 
03275         if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
03276         {
03277             double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
03278         }
03279         else
03280         {
03281             double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
03282 
03283             sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
03284 
03285             sigma_corr = autocorr * sigma;
03286 
03287             gain = double_adu / (c_ndit * sigma);
03288 
03289             gain_corr = double_adu / (c_dit*sigma_corr);
03290 
03291             skip_if(cpl_table_set_double(gain_table, "GAIN", pos, gain));
03292             skip_if(cpl_table_set_double(gain_table, "GAIN_CORR", pos, gain_corr));
03293         }
03294 
03295         skip_if(cpl_table_set_double(gain_table, "AUTOCORR", pos, autocorr));
03296         skip_if(cpl_table_set_double(gain_table, "ADU", pos, double_adu / 2));
03297 
03298         /* FIXME: Remove the following 3 columns after testing period */
03299         skip_if(cpl_table_set_double(gain_table, "Y_FIT",
03300                          pos,
03301                          c_ndit* sig_on_dif * sig_on_dif));
03302         skip_if(cpl_table_set_double(gain_table, "Y_FIT_CORR",
03303                          pos,
03304                          c_ndit * sig_on_dif * sig_on_dif));
03305         skip_if(cpl_table_set_double(gain_table, "X_FIT", pos, double_adu));
03306         skip_if(cpl_table_set_double(gain_table, "X_FIT_CORR",
03307                      pos, double_adu / autocorr));
03308     }
03309     end_skip;
03310 
03311     cpl_image_delete(on_dif);
03312     cpl_image_delete(off_dif);
03313 
03314     return cpl_error_get_code();
03315 }
03316 
03317 /*--------------------------------------------------------------------------*/
03324 /*--------------------------------------------------------------------------*/
03325 
03326 static cpl_image       *
03327 detmon_bpixs(const cpl_imagelist * coeffs,
03328                     cpl_boolean bpmbin,
03329                     const double kappa,
03330                     int *nbpixs)
03331 {
03332     int                     size;
03333     int                     i;
03334     const cpl_image        *first= cpl_imagelist_get_const(coeffs, 0);
03335     cpl_stats              *stats;
03336     double                  cur_mean;
03337     double                  cur_stdev;
03338     double                  lo_cut;
03339     double                  hi_cut;
03340     cpl_mask               *cur_mask;
03341     cpl_mask               *mask = cpl_mask_new(cpl_image_get_size_x(first),
03342                                             cpl_image_get_size_y(first));
03343     cpl_image              *cur_image = NULL;
03344     cpl_image              *bpm = NULL; /* Avoid false uninit warning */
03345     double                  p;
03346 
03347     size = cpl_imagelist_get_size(coeffs);
03348 
03349     if(!bpmbin) {
03350     bpm = cpl_image_new(cpl_image_get_size_x(first),
03351                 cpl_image_get_size_y(first),
03352                 CPL_TYPE_INT);
03353     }
03354 
03355 
03356     for(i = 0; i < size; i++) {
03357         const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
03358 
03359         stats = cpl_stats_new_from_image(cur_coeff,
03360                                          CPL_STATS_MEAN | CPL_STATS_STDEV);
03361         cur_mean = cpl_stats_get_mean(stats);
03362         cur_stdev = cpl_stats_get_stdev(stats);
03363 
03364         lo_cut = cur_mean - kappa * cur_stdev;
03365         hi_cut = cur_mean + kappa * cur_stdev;
03366 
03367         cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
03368         cpl_mask_not(cur_mask);
03369 
03370     if(!bpmbin) {
03371         cur_image = cpl_image_new_from_mask(cur_mask);
03372         p = pow(2, i);
03373         cpl_image_power(cur_image, p);
03374         cpl_image_add(bpm, cur_image);
03375         cpl_image_delete(cur_image);
03376     }
03377 
03378     cpl_mask_or(mask, cur_mask);
03379 
03380         cpl_mask_delete(cur_mask);
03381         cpl_stats_delete(stats);
03382     }
03383 
03384     if(bpmbin) {
03385     bpm = cpl_image_new_from_mask(mask);
03386     }
03387 
03388     *nbpixs += cpl_mask_count(mask);
03389 
03390     cpl_mask_delete(mask);
03391 
03392     return bpm;
03393 }
03394 
03395 
03396 /*--------------------------------------------------------------------------*/
03403 /*--------------------------------------------------------------------------*/
03404 /* Not used so we temporary comment it out
03405 static cpl_image       *
03406 detmon_bpixs2(cpl_vector* x,const cpl_imagelist* y,
03407      const cpl_imagelist * coeffs,cpl_table* gain_table,
03408     const int order, const double kappa,cpl_boolean bpmbin,
03409     int *nbpixs)
03410 {
03411 
03412 
03413   int    size_x=0;
03414   int    size_y=0;
03415   int    size_c=0;
03416 
03417 
03418   int    i=0;
03419   int    j=0;
03420   cpl_size    k=0;
03421   int z=0;
03422   int pix=0;
03423   int sx=0;
03424   int sy=0;
03425 
03426   double* px=NULL;
03427   const float* pdata=NULL;
03428   const float* pcoeffs=NULL;
03429   double pfit=0.;
03430   double* pgain=NULL;
03431   cpl_binary* pmask=NULL;
03432   double gain=0;
03433   const cpl_image* img_data=NULL;
03434 
03435   const cpl_image* img_coeffs=NULL;
03436   cpl_image* bpm=NULL;
03437   cpl_mask* mask=NULL;
03438 
03439   cpl_polynomial* pol=NULL;
03440 
03441   size_x = cpl_vector_get_size(x);
03442   size_y = cpl_imagelist_get_size(y);
03443   size_c = cpl_imagelist_get_size(coeffs);
03444   img_data = cpl_imagelist_get_const(coeffs, 0);
03445   sx = cpl_image_get_size_x(img_data);
03446   sy = cpl_image_get_size_y(img_data);
03447   mask = cpl_mask_new(sx,sy);
03448 
03449   cpl_ensure(size_x == size_y, CPL_ERROR_NULL_INPUT, NULL);
03450 
03451   cpl_ensure(size_c == (order+1), CPL_ERROR_NULL_INPUT, NULL);
03452 
03453   px = cpl_vector_get_data(x);
03454   pmask=cpl_mask_get_data(mask);
03455   pgain=cpl_table_get_data_double(gain_table,"GAIN");
03456   pol=cpl_polynomial_new(1);
03457   for (z = 0; z < size_x; z++) {
03458 
03459     img_data = cpl_imagelist_get_const(y, z);
03460     pdata = cpl_image_get_data_float_const(img_data);
03461     gain=pgain[z];
03462 
03463     for (j = 0; j < sy; j++) {
03464 
03465       for (i = 0; i < sx; i++) {
03466 
03467         pix = j * sx + i;
03468 
03469         for (k = size_c-1; k >= 0; k--) {
03470 
03471           img_coeffs = cpl_imagelist_get_const(coeffs, k);
03472           pcoeffs = cpl_image_get_data_float_const(img_coeffs);
03473           cpl_polynomial_set_coeff(pol, &k, pcoeffs[pix]);
03474 
03475         }
03476 
03477         pfit = cpl_polynomial_eval_1d(pol,px[z],NULL);
03478         if (pdata[pix] > 0) {
03479           if (fabs(pdata[pix] - pfit) > kappa * sqrt(gain*pdata[pix])) {
03480             pmask[pix] = CPL_BINARY_1;
03481           } // check if point to be flagged 
03482         } // check if pos intensity 
03483       } // i loop 
03484     } // j loop 
03485 
03486     //cpl_image_delete(img_data);
03487 
03488   } // z loop 
03489   cpl_polynomial_delete(pol);
03490   if (bpmbin) {
03491     bpm = cpl_image_new_from_mask(mask);
03492   }
03493 
03494   *nbpixs += cpl_mask_count(mask);
03495 
03496   cpl_mask_delete(mask);
03497 
03498   return bpm;
03499 }
03500 
03501 */
03502 /*---------------------------------------------------------------------------*/
03514 /*---------------------------------------------------------------------------*/
03515 
03516 static double
03517 detmon_autocorr_factor(const cpl_image * image,
03518                               cpl_image ** autocorr_image, int m, int n)
03519 {
03520     cpl_image * mycorr_image = NULL;
03521     double      autocorr = 0;
03522     cpl_error_code err = CPL_ERROR_NONE;
03523 
03524     mycorr_image = detmon_image_correlate(image, image, m, n);
03525     err=cpl_error_get_code();
03526     if (err == CPL_ERROR_UNSUPPORTED_MODE)
03527     {
03528         cpl_msg_warning(cpl_func, "FFTW is not supported by CPL, autocorrelation "
03529                 "would be computed using internal implementation");
03530         cpl_error_reset();
03531         if (mycorr_image)
03532             cpl_image_delete(mycorr_image);
03533         mycorr_image = detmon_autocorrelate(image, m, n);
03534     }
03535     if(mycorr_image == NULL) {
03536         return -1;
03537     }
03538 
03539     cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
03540 
03541     autocorr = cpl_image_get_flux(mycorr_image);
03542 
03543     if (autocorr_image) *autocorr_image = mycorr_image;
03544     else cpl_image_delete(mycorr_image);
03545 
03546     return autocorr;
03547 }
03548 
03549 static cpl_propertylist*
03550 detmon_lg_extract_qclist_4plane(cpl_propertylist* linc_qclist,const int ip)
03551 {
03552 
03553    cpl_propertylist* sub_set=NULL;
03554    char* qc_key=NULL;
03555 
03556    sub_set=cpl_propertylist_new();
03557    qc_key=cpl_sprintf("QC LIN COEF%d",ip);
03558    cpl_propertylist_copy_property_regexp(sub_set,linc_qclist,qc_key,0);
03559 
03560    cpl_free(qc_key);
03561    return sub_set;
03562 
03563 }
03564 
03565 
03575 static cpl_error_code
03576 detmon_lg_extract_extention_header(cpl_frameset* frameset,
03577                                           cpl_propertylist* gaint_qclist,
03578                                           cpl_propertylist* lint_qclist,
03579                                           cpl_propertylist* linc_qclist, 
03580                                           cpl_propertylist* bpm_qclist,
03581                                           int whichext)
03582 {
03583 
03584    cpl_propertylist *      xplist = NULL;
03585 
03586    const char * filename =
03587       cpl_frame_get_filename(cpl_frameset_get_first(frameset));
03588 
03589    xplist = cpl_propertylist_load_regexp(filename, whichext,
03590                                          "ESO DET|EXTNAME", 0);
03591    if (detmon_lg_config.exts >= 0) 
03592    {
03593       /* for one extension, copy only extname keyword (if any) - DFS09856 */
03594       cpl_property* propExtname = NULL;            
03595       propExtname = cpl_propertylist_get_property(xplist, "EXTNAME");
03596       cpl_error_reset();
03597       if (NULL != propExtname)
03598       {            
03599          propExtname = cpl_property_duplicate(propExtname);
03600       }
03601       cpl_propertylist_delete(xplist);
03602       xplist = NULL;                        
03603       if (NULL != propExtname)
03604       {
03605          xplist = cpl_propertylist_new();
03606          cpl_propertylist_append_property(xplist, propExtname);
03607          cpl_property_delete(propExtname);
03608       }
03609    }
03610    if (NULL != xplist)
03611    {
03612       cpl_propertylist_append(gaint_qclist, xplist);
03613       cpl_propertylist_append(lint_qclist,  xplist);
03614       cpl_propertylist_append(linc_qclist,  xplist);
03615       cpl_propertylist_append(bpm_qclist,   xplist);
03616       cpl_propertylist_delete(xplist);
03617    }
03618 
03619    return cpl_error_get_code();
03620 }
03621 
03622 
03623 
03624 
03625 
03626 /*---------------------------------------------------------------------------*/
03635 /*---------------------------------------------------------------------------*/
03636 static cpl_error_code
03637 detmon_lg_save_table_with_pro_keys(cpl_table* table,
03638                       const char* name_o,
03639                       cpl_propertylist* xheader,
03640                                           unsigned CPL_IO_MODE)
03641 {
03642 
03643    cpl_propertylist* pro_keys=NULL;
03644    cpl_propertylist* pri_head=NULL;
03645 
03646    pro_keys=detmon_load_pro_keys(name_o);
03647    cpl_propertylist_append(xheader,pro_keys);
03648 
03649    if(CPL_IO_MODE==CPL_IO_DEFAULT) {
03650       pri_head=cpl_propertylist_load(name_o,0);
03651       cpl_table_save(table, pri_head,xheader,name_o,
03652                      CPL_IO_DEFAULT);
03653       cpl_propertylist_delete(pri_head);
03654 
03655    } else {
03656       cpl_table_save(table,NULL,xheader,name_o,
03657                      CPL_IO_EXTEND);
03658    }
03659    cpl_propertylist_delete(pro_keys);
03660 
03661    return cpl_error_get_code();
03662 }
03663 
03664 /*---------------------------------------------------------------------------*/
03672 /*---------------------------------------------------------------------------*/
03673 static cpl_error_code
03674 detmon_lg_save_image_with_pro_keys(cpl_image* image,
03675                       const char* name_o,
03676                       cpl_propertylist* xheader)
03677 {
03678 
03679   cpl_propertylist* pro_keys=NULL;
03680   pro_keys=detmon_load_pro_keys(name_o);
03681   cpl_propertylist_append(xheader,pro_keys);
03682 
03683   cpl_image_save(image,name_o, CPL_BPP_IEEE_FLOAT, 
03684          xheader,CPL_IO_EXTEND);      
03685   cpl_propertylist_delete(pro_keys);
03686       
03687 
03688   return cpl_error_get_code();
03689 }
03690 
03691 /*---------------------------------------------------------------------------*/
03699 /*---------------------------------------------------------------------------*/
03700 static cpl_error_code
03701 detmon_lg_save_imagelist_with_pro_keys(cpl_imagelist* imagelist,
03702                       const char* name_o,
03703                       cpl_propertylist* xheader)
03704 {
03705 
03706   cpl_propertylist* pro_keys=NULL;
03707   pro_keys=detmon_load_pro_keys(name_o);
03708   cpl_propertylist_append(xheader,pro_keys);
03709 
03710   cpl_imagelist_save(imagelist,name_o, CPL_BPP_IEEE_FLOAT, 
03711                      xheader,CPL_IO_EXTEND);      
03712 
03713   cpl_propertylist_delete(pro_keys);
03714       
03715 
03716   return cpl_error_get_code();
03717 }
03718 
03719 /*---------------------------------------------------------------------------*/
03736 static cpl_error_code
03737 detmon_lg_save_plane(const cpl_parameterlist * parlist,
03738                             cpl_frameset* frameset, 
03739                             const cpl_frameset * usedframes,      
03740                             int whichext,
03741                             const char* recipe_name,
03742                             cpl_propertylist* mypro_coeffscube,
03743                             cpl_propertylist* linc_plane_qclist,
03744                             const char* package,
03745                             const char* NAME_O,
03746                             cpl_image* plane)
03747 {
03748    cpl_propertylist* plist=NULL;
03749 
03750    if(detmon_lg_config.exts == 0) {
03751       cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
03752                          NULL, NULL,
03753                          CPL_BPP_IEEE_FLOAT, recipe_name,
03754                          mypro_coeffscube, NULL,
03755                          package, NAME_O);
03756       plist=cpl_propertylist_load(NAME_O,0);
03757      cpl_image_save(plane,NAME_O, CPL_BPP_IEEE_FLOAT, 
03758                     plist,CPL_IO_DEFAULT);      
03759      cpl_propertylist_delete(plist);
03760 
03761    } else if(detmon_lg_config.exts > 0) {
03762      cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
03763                          NULL, NULL,
03764                          CPL_BPP_IEEE_FLOAT, recipe_name,
03765                          mypro_coeffscube, NULL,
03766                          package, NAME_O);
03767 
03768      detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
03769    } else {
03770       if(whichext == 1) 
03771       {
03772          cpl_dfs_save_image(frameset, NULL, parlist, 
03773                             usedframes,NULL, NULL,
03774                             CPL_BPP_IEEE_FLOAT, recipe_name,
03775                             mypro_coeffscube, NULL,
03776                             package, NAME_O);
03777     detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
03778       } else {
03779 
03780     detmon_lg_save_image_with_pro_keys(plane,NAME_O,linc_plane_qclist);
03781 
03782       }
03783 
03784    }
03785   
03786    return cpl_error_get_code();
03787 }
03788 
03789 
03790 
03791 /*---------------------------------------------------------------------------*/
03809 static cpl_error_code
03810 detmon_lg_save_cube(const cpl_parameterlist * parlist,
03811                            cpl_frameset* frameset, 
03812                            const cpl_frameset * usedframes,      
03813                            int whichext,
03814                            const char* recipe_name,
03815                            cpl_propertylist* mypro_coeffscube,
03816                            cpl_propertylist* linc_qclist,
03817                            const char* package,
03818                            const char* NAME_O,
03819                            cpl_imagelist* coeffs)
03820 {
03821 
03822    if(detmon_lg_config.exts == 0) {  
03823       cpl_propertylist_append(mypro_coeffscube, linc_qclist);
03824       detmon_lg_dfs_save_imagelist
03825          (frameset,  parlist, usedframes, coeffs,
03826           recipe_name, mypro_coeffscube, package,
03827           NAME_O);   
03828    } else if(detmon_lg_config.exts > 0)  {
03829       cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
03830                          NULL, NULL,
03831                          CPL_BPP_IEEE_FLOAT, recipe_name,
03832                          mypro_coeffscube, NULL,
03833                          package, NAME_O);
03834 
03835       detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
03836 
03837    } else {
03838       if(whichext == 1) {
03839          cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
03840                             NULL, NULL,
03841                             CPL_BPP_IEEE_FLOAT, recipe_name,
03842                             mypro_coeffscube, NULL,
03843                             package, NAME_O);
03844     detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
03845       } else {
03846     detmon_lg_save_imagelist_with_pro_keys(coeffs,NAME_O,linc_qclist);
03847       }
03848    }
03849    
03850    return cpl_error_get_code();
03851 }
03852 
03853 static char*
03854 detmon_lg_set_paf_name_and_header(cpl_frame* ref_frame,
03855                                          int flag_sets,int which_set,
03856                                          int whichext,
03857                                          const char* paf_suf,
03858                                          cpl_propertylist** plist)
03859 {
03860    char * paf_name=NULL;
03861 
03862    if(detmon_lg_config.exts >= 0) 
03863    {
03864       *plist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03865                                     detmon_lg_config.exts);
03866 
03867       if(!flag_sets) 
03868       {
03869          paf_name=cpl_sprintf("%s_%s.paf", detmon_lg_config.pafname,paf_suf);
03870       } 
03871       else 
03872       {
03873          paf_name=cpl_sprintf("%s_%s_set%02d.paf",
03874                               detmon_lg_config.pafname, paf_suf,which_set);
03875       }
03876    } 
03877    else 
03878    {
03879       *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03880                                      whichext);
03881 
03882 
03883       if(!flag_sets) 
03884       {
03885          paf_name=cpl_sprintf("%s_%s_ext%02d.paf",
03886                               detmon_lg_config.pafname, paf_suf,whichext);
03887       } 
03888       else 
03889       {
03890          paf_name=cpl_sprintf("%s_%s_set%02d_ext%02d.paf",
03891                               detmon_lg_config.pafname,paf_suf,
03892                               which_set, whichext);
03893       }
03894    }
03895 
03896    return paf_name;
03897 }
03898 
03899 
03900 static char*
03901 detmon_lg_set_paf_name_and_header_ext(cpl_frame* ref_frame,
03902                                          int flag_sets,int which_set,
03903                                          int whichext,
03904                                          const char* paf_suf,
03905                                          cpl_propertylist** plist)
03906 {
03907    char* paf_name=NULL;
03908 
03909    if(detmon_lg_config.exts >= 0) 
03910    {
03911       *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03912                                      detmon_lg_config.exts);
03913 
03914       if(!flag_sets) 
03915       {
03916          paf_name=cpl_sprintf("%s_%s.paf", detmon_lg_config.pafname,paf_suf);
03917       } else 
03918       {
03919          paf_name=cpl_sprintf("%s_%s_set%02d.paf",
03920                               detmon_lg_config.pafname, paf_suf,which_set);
03921       }
03922    } else 
03923    {
03924       *plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03925                                      whichext);
03926       if(!flag_sets) 
03927       {
03928          paf_name=cpl_sprintf("%s_%s_ext%02d.paf",
03929                               detmon_lg_config.pafname, paf_suf,whichext);
03930       } else 
03931       {
03932          paf_name=cpl_sprintf("%s_%s_set%02d_ext%02d.paf",
03933                               detmon_lg_config.pafname,paf_suf,
03934                               which_set, whichext);
03935       }
03936    }
03937   return paf_name;
03938 
03939 }
03940 
03941 static cpl_error_code    
03942 detmon_lg_save_paf_product(cpl_frame* ref_frame,int flag_sets,
03943                                  int which_set,int whichext,
03944                                  const char* pafregexp,
03945                                  const char* procatg,
03946                                  const char* pipeline_name,
03947                                  const char* recipe_name,
03948                                   const char* paf_suf,
03949                                   cpl_propertylist* qclist,
03950                                   const int ext)
03951 
03952 {
03953 
03954    /* Set the file name for the linearity table PAF */
03955    char* paf_name=NULL;
03956    cpl_propertylist* plist=NULL;
03957    cpl_propertylist* paflist = NULL;
03958    cpl_propertylist* mainplist=NULL;
03959 
03960    mainplist =cpl_propertylist_load(cpl_frame_get_filename(ref_frame),0);
03961    if(ext==0) {
03962       paf_name=detmon_lg_set_paf_name_and_header(ref_frame,flag_sets,
03963                                                         which_set,whichext,
03964                                                         paf_suf,&plist);
03965    } else {
03966       paf_name=detmon_lg_set_paf_name_and_header_ext(ref_frame,flag_sets,
03967                                                             which_set,whichext,
03968                                                             paf_suf,&plist);
03969    }
03970   
03971 
03972    paflist = cpl_propertylist_new();
03973    cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,procatg);
03974 
03975    /* Get the keywords for the paf file */
03976    cpl_propertylist_copy_property_regexp(paflist, plist,pafregexp, 0);
03977    cpl_propertylist_copy_property_regexp(paflist, mainplist,pafregexp, 0);
03978    cpl_propertylist_append(paflist,qclist);
03979 
03980    /* Save the PAF */
03981    cpl_dfs_save_paf(pipeline_name, recipe_name,paflist,paf_name);
03982 
03983    /* free memory */
03984    cpl_propertylist_delete(mainplist);
03985    cpl_propertylist_delete(paflist);
03986    cpl_propertylist_delete(plist);
03987    cpl_free(paf_name);
03988 
03989    return cpl_error_get_code();
03990 
03991 }
03992 
03993 
03994 
03995 /*---------------------------------------------------------------------------*/
04026 static cpl_error_code
04027 detmon_lg_save(const cpl_parameterlist * parlist,
04028                       cpl_frameset * frameset,
04029                       const char *recipe_name,
04030                       const char *pipeline_name,
04031                       const char *pafregexp,
04032               const cpl_propertylist  * pro_lintbl,
04033               const cpl_propertylist  * pro_gaintbl,
04034               const cpl_propertylist  * pro_coeffscube,
04035               const cpl_propertylist  * pro_bpm,
04036               const cpl_propertylist  * pro_corr,
04037               const cpl_propertylist  * pro_diff,
04038                       const char *package,
04039                       cpl_imagelist * coeffs,
04040                       cpl_table * gain_table,
04041                       cpl_table * linear_table,
04042                       cpl_image * bpms,
04043                       cpl_imagelist * autocorr_images,
04044                       cpl_imagelist * diff_flats,
04045                       cpl_propertylist * gaint_qclist,
04046                       cpl_propertylist * lint_qclist,
04047                       cpl_propertylist * linc_qclist,
04048                       cpl_propertylist * bpm_qclist,
04049                       const int flag_sets,
04050                       const int which_set,
04051                       const cpl_frameset * usedframes,
04052                       int whichext)
04053 {
04054 
04055     cpl_frame              *ref_frame;
04056     cpl_propertylist       *plist = NULL;
04057     cpl_propertylist       *mainplist = NULL;
04058     char*                   NAME_O=NULL;
04059     char*                   PREF_O=NULL;
04060     int                     nb_images;
04061     int                     i;
04062 
04063     cpl_propertylist *      xplist = NULL;
04064 
04065     cpl_propertylist* linc_plane_qclist=NULL;
04066     cpl_image* plane=NULL;
04067     int ip=0;
04068     char* pcatg_plane=NULL;
04069 
04070     cpl_propertylist  * mypro_lintbl     =
04071     cpl_propertylist_duplicate(pro_lintbl);
04072     cpl_propertylist  * mypro_gaintbl    =
04073     cpl_propertylist_duplicate(pro_gaintbl);
04074     cpl_propertylist  * mypro_coeffscube =
04075     cpl_propertylist_duplicate(pro_coeffscube);
04076     cpl_propertylist  * mypro_bpm        =
04077     cpl_propertylist_duplicate(pro_bpm);
04078     cpl_propertylist  * mypro_corr       =
04079     cpl_propertylist_duplicate(pro_corr);
04080     cpl_propertylist  * mypro_diff       =
04081     cpl_propertylist_duplicate(pro_diff);
04082 
04083     const char * procatg_lintbl =
04084     cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
04085 
04086     const char * procatg_gaintbl =
04087     cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
04088 
04089     const char * procatg_coeffscube =
04090     cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
04091     const char * procatg_bpm =
04092     cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
04093 
04094 
04095     /* Extract extension headers if multi-extension */
04096     detmon_lg_extract_extention_header(frameset,gaint_qclist,lint_qclist,
04097                                               linc_qclist,bpm_qclist,whichext);
04098 
04099     /* This is only used later for PAF and temporarily for COEFFS_CUBE
04100        (see if defined)*/
04101     /* Get FITS header from reference file */
04102     ref_frame = cpl_frameset_get_first(frameset);
04103 
04104     skip_if((mainplist =
04105     cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04106                   0)) == NULL);
04107 
04108     /*******************************/
04109     /*  Write the LINEARITY TABLE  */
04110     /*******************************/
04111     cpl_msg_info(cpl_func,"Write the LINEARITY TABLE");
04112     /* Set the file name for the table */
04113     if(!flag_sets) {
04114        NAME_O=cpl_sprintf("%s_linearity_table.fits", recipe_name);
04115     } else {
04116        NAME_O=cpl_sprintf("%s_linearity_table_set%02d.fits", recipe_name,
04117                            which_set);
04118     }
04119 
04120     if (detmon_lg_config.exts >= 0) {
04121        /* Save the table */
04122        cpl_propertylist_append(mypro_lintbl, lint_qclist);
04123        skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,
04124                                   linear_table,NULL, recipe_name,
04125                                   mypro_lintbl, NULL, package, NAME_O));
04126     
04127        detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
04128                                                  lint_qclist,CPL_IO_DEFAULT);
04129 
04130     } else {
04131        if(whichext == 1) {
04132           /* Save the 1. extension table */
04133           skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL, 
04134                                      linear_table,lint_qclist, recipe_name, 
04135                                      mypro_lintbl,NULL, package, NAME_O));
04136           detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
04137                                                     lint_qclist,CPL_IO_DEFAULT);
04138 
04139 
04140 
04141 
04142        } else {
04143 
04144           detmon_lg_save_table_with_pro_keys(linear_table,NAME_O,
04145                                                     lint_qclist,CPL_IO_EXTEND);
04146        }
04147     }
04148     irplib_free(&NAME_O);
04149     /**************************/
04150     /*  Write the GAIN TABLE  */
04151     /**************************/
04152     cpl_msg_info(cpl_func,"Write the GAIN TABLE");
04153     /* Set the file name for the table */
04154     if(!flag_sets) {
04155         NAME_O=cpl_sprintf("%s_gain_table.fits", recipe_name);
04156     } else {
04157         NAME_O=cpl_sprintf("%s_gain_table_set%02d.fits", recipe_name,
04158                            which_set);
04159     }
04160 
04161     if (detmon_lg_config.exts >= 0) 
04162     {
04163        /* Save the table */
04164 
04165        cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
04166        skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,
04167                                   gain_table,NULL, recipe_name, mypro_gaintbl,
04168                                   NULL, package, NAME_O));
04169        detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
04170                                                  gaint_qclist,CPL_IO_DEFAULT);
04171 
04172     } 
04173     else 
04174     {
04175        if(whichext == 1) 
04176        {
04177           /* Save the 1. extension table */
04178           skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
04179                                      gaint_qclist, recipe_name, mypro_gaintbl,
04180                                      NULL, package, NAME_O));
04181           detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
04182                                                     gaint_qclist,CPL_IO_DEFAULT);
04183 
04184        } 
04185        else 
04186        {
04187 
04188           detmon_lg_save_table_with_pro_keys(gain_table,NAME_O,
04189                                                     gaint_qclist,CPL_IO_EXTEND);
04190        }
04191     }
04192 
04193     if(detmon_lg_config.pix2pix) 
04194     {
04195 
04196       /***************************/
04197       /*  Write the COEFFS FITS  */
04198       /***************************/
04199        cpl_msg_info(cpl_func,"Write the COEFFS FITS");
04200        irplib_free(&NAME_O);
04201       if(!flag_sets) 
04202       {
04203         PREF_O=cpl_sprintf("%s_coeffs_cube", recipe_name);
04204       } else 
04205       {
04206          PREF_O=cpl_sprintf("%s_coeffs_cube_set%02d",
04207                recipe_name, which_set);
04208       }
04209       if (detmon_lg_config.split_coeffs == 0) {
04210          NAME_O=cpl_sprintf("%s.fits", PREF_O);
04211       }
04212 
04213 
04214       /* Save the imagelist */
04215       if(detmon_lg_config.split_coeffs != 0){ 
04216 
04217 
04218          nb_images = cpl_imagelist_get_size(coeffs);
04219          for(ip=0;ip<nb_images;ip++) {
04220             NAME_O=cpl_sprintf("%s_P%d.fits", PREF_O,ip);
04221             pcatg_plane=cpl_sprintf("COEFFS_CUBE_P%d",ip);
04222             cpl_propertylist_delete(mypro_coeffscube);
04223             mypro_coeffscube=cpl_propertylist_duplicate(pro_coeffscube);
04224             cpl_propertylist_set_string(mypro_coeffscube,CPL_DFS_PRO_CATG,
04225                                         pcatg_plane);
04226             linc_plane_qclist=detmon_lg_extract_qclist_4plane(linc_qclist,ip);
04227             cpl_propertylist_append(mypro_coeffscube, linc_plane_qclist);
04228             plane=cpl_imagelist_get(coeffs,ip);
04229             detmon_lg_save_plane(parlist,frameset,usedframes,whichext,
04230                                         recipe_name,mypro_coeffscube,
04231                                         linc_plane_qclist,package,NAME_O,plane);
04232           
04233             if(NULL!=linc_plane_qclist) {
04234                cpl_propertylist_delete(linc_plane_qclist);
04235             }
04236             irplib_free(&NAME_O);
04237 
04238          } /* end for loop over cube planes */
04239       } else {
04240 
04241          detmon_lg_save_cube(parlist,frameset,usedframes,whichext,
04242                                     recipe_name,mypro_coeffscube,
04243                                     linc_qclist,package,NAME_O,coeffs);
04244       }
04245 
04246       /*******************************/
04247       /*  Write the BAD PIXEL MAP    */
04248       /*******************************/
04249       cpl_msg_info(cpl_func,"Write the BAD PIXEL MAP");
04250       irplib_free(&NAME_O);
04251       /* Set the file name for the bpm */
04252       if(!flag_sets) 
04253       {
04254          NAME_O=cpl_sprintf("%s_bpm.fits", recipe_name);
04255       } else 
04256       {
04257          NAME_O=cpl_sprintf("%s_bpm_set%02d.fits", recipe_name, which_set);
04258       }
04259    
04260 
04261       /* Save the image */
04262       if(detmon_lg_config.exts == 0)       {
04263          cpl_propertylist_append(mypro_bpm, bpm_qclist);
04264          cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
04265                                  CPL_BPP_IEEE_FLOAT, recipe_name,
04266                                  mypro_bpm, NULL, package,
04267                                  NAME_O);
04268       }
04269       else if(detmon_lg_config.exts > 0) 
04270       { 
04271          skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL,  NULL,
04272                                     CPL_BPP_IEEE_FLOAT, recipe_name,
04273                                     mypro_bpm, NULL, package,
04274                                     NAME_O));
04275          detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
04276 
04277       } else 
04278       {
04279          if (whichext == 1) 
04280          {
04281             skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL,  NULL,
04282                      CPL_BPP_IEEE_FLOAT, recipe_name,
04283                      mypro_bpm, NULL, package,
04284                      NAME_O));
04285             detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
04286          } else 
04287          {
04288             detmon_lg_save_image_with_pro_keys(bpms,NAME_O,bpm_qclist);
04289          }
04290       }
04291     } /* End of if(pix2pix) */
04292 
04293     if(detmon_lg_config.intermediate) 
04294     {
04295         /******************************/
04296         /*  Write the AUTOCORRS FITS  */
04297         /******************************/
04298       cpl_msg_info(cpl_func,"Write the AUTOCORRS FITS");
04299       nb_images = cpl_imagelist_get_size(autocorr_images);
04300       cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
04301       for(i = 0; i < nb_images; i++)
04302       {
04303          cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_corr);
04304          int inull = 0;
04305          cpl_array* pnames = cpl_table_get_column_names(linear_table);
04306          double ddit = 0;
04307          if(i < cpl_table_get_nrow(linear_table))
04308          {
04309             ddit = cpl_table_get_double(linear_table,
04310             cpl_array_get_data_string_const(pnames)[0], i, &inull);
04311          }
04312          cpl_array_delete(pnames);
04313          /*cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);*/
04314             /* Set the file name for each image */
04315             irplib_free(&NAME_O);
04316             if(!flag_sets)
04317             {
04318                 NAME_O=cpl_sprintf("%s_autocorr_%d.fits", recipe_name, i);
04319                 assert(NAME_O != NULL);
04320             } else
04321             {
04322                 NAME_O=cpl_sprintf("%s_autocorr_%02d_set%02d.fits",
04323                                    recipe_name, i, which_set);
04324                 assert(NAME_O != NULL);
04325             }
04326             /* Save the image */
04327             if(detmon_lg_config.exts > 0)
04328             {
04329                cpl_propertylist* pextlist = cpl_propertylist_new();
04330                cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
04331                skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, 
04332                                           NULL,NULL,CPL_BPP_IEEE_FLOAT, 
04333                                           recipe_name, pplist, NULL,
04334                                           package, NAME_O));
04335 
04336                 detmon_lg_save_image_with_pro_keys(
04337                    cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
04338 
04339                 cpl_propertylist_delete(pextlist);
04340             } else
04341             if(detmon_lg_config.exts == 0)
04342             {
04343                 cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);            
04344                 cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,
04345                     cpl_imagelist_get(autocorr_images, i), CPL_BPP_IEEE_FLOAT,
04346                     recipe_name, pplist, NULL, package,
04347                     NAME_O);
04348 
04349             }
04350             else
04351             {
04352                cpl_propertylist* pextlist = cpl_propertylist_new();
04353                cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);
04354                if(whichext == 1)
04355                {
04356                   skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,NULL,
04357                         CPL_BPP_IEEE_FLOAT, recipe_name,
04358                         pplist, NULL,
04359                         package, NAME_O));
04360 
04361                   detmon_lg_save_image_with_pro_keys(
04362                      cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
04363 
04364                } else
04365                {
04366 
04367                   detmon_lg_save_image_with_pro_keys(
04368                      cpl_imagelist_get(autocorr_images, i),NAME_O,pextlist);
04369                }
04370                cpl_propertylist_delete(pextlist);
04371             }
04372             cpl_propertylist_delete (pplist);
04373         }
04374       irplib_free(&NAME_O);
04375 
04376 
04377         /*
04378         cpl_msg_info(cpl_func, "-----before Write the DIFFS FITS %d", __LINE__);
04379         */
04380         /***************************/
04381         /*   Write the DIFFS FITS  */
04382         /***************************/
04383       cpl_msg_info(cpl_func,"Write the DIFFS FITS");
04384 
04385       for(i = 0; i < nb_images; i++)
04386       {
04387          cpl_propertylist* pplist = cpl_propertylist_duplicate(mypro_diff);
04388          int inull = 0;
04389          cpl_array* pnames = cpl_table_get_column_names(linear_table);
04390          double ddit = 0;
04391          if(i < cpl_table_get_nrow(linear_table))
04392          {
04393             ddit = cpl_table_get_double(linear_table,
04394                                         cpl_array_get_data_string_const(pnames)[0], i, &inull);
04395          }
04396          cpl_array_delete(pnames);
04397          /*cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);*/
04398          /* Set the file name for each image */
04399          if(!flag_sets)
04400          {
04401             NAME_O=cpl_sprintf("%s_diff_flat_%d.fits", recipe_name, i);
04402          } else
04403          {
04404             NAME_O=cpl_sprintf("%s_diff_flat_%d_set%02d.fits",
04405                     recipe_name, i, which_set);
04406          }
04407          /* Save the image */
04408          if(detmon_lg_config.exts > 0)
04409          {
04410             cpl_propertylist* pextlist = cpl_propertylist_new();
04411             cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);     
04412             cpl_propertylist_append_double(mypro_diff, "ESO DET DIT", ddit);   
04413             skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, 
04414                                        NULL,NULL,CPL_BPP_IEEE_FLOAT,recipe_name,
04415                                        mypro_diff, NULL,package, NAME_O));
04416 
04417             detmon_lg_save_image_with_pro_keys(
04418                cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
04419 
04420             cpl_propertylist_delete(pextlist);
04421          }
04422          else if(detmon_lg_config.exts == 0)
04423          {
04424             cpl_propertylist_append_double(pplist, "ESO DET DIT", ddit);       
04425             cpl_dfs_save_image
04426                (frameset, NULL, parlist, usedframes, NULL,
04427                 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
04428                 recipe_name, pplist, NULL, package,
04429                 NAME_O);
04430 
04431          } else
04432          {
04433             cpl_propertylist* pextlist = cpl_propertylist_new();
04434             cpl_propertylist_append_double(pextlist, "ESO DET DIT", ddit);   
04435             if(whichext == 1)
04436             {
04437                cpl_propertylist_append_double(mypro_diff,"ESO DET DIT",ddit);   
04438 //                  cpl_propertylist_erase(mypro_diff, "ESO DET DIT");
04439                skip_if(cpl_dfs_save_image(frameset, NULL, parlist, 
04440                                           usedframes, NULL,NULL,
04441                                           CPL_BPP_IEEE_FLOAT, recipe_name,
04442                                           mypro_diff, NULL,package, NAME_O));
04443 
04444                detmon_lg_save_image_with_pro_keys(
04445                   cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
04446 
04447             } else
04448             {
04449 
04450                detmon_lg_save_image_with_pro_keys(
04451                   cpl_imagelist_get(diff_flats, i),NAME_O,pextlist);
04452 
04453             }
04454             cpl_propertylist_delete(pextlist);
04455          }
04456          cpl_propertylist_delete(pplist);
04457          irplib_free(&NAME_O);
04458       }
04459     } /* End of if(intermediate) */
04460 
04461 
04462     /*******************************/
04463     /*  Write the PAF file(s)      */
04464     /*******************************/
04465       cpl_msg_info(cpl_func,"Write the PAF file(s)");
04466 
04467     if(detmon_lg_config.pafgen) {
04468 
04469        detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
04470                                          pafregexp,procatg_gaintbl,
04471                                          pipeline_name,recipe_name,
04472                                          "qc01",gaint_qclist,0);
04473 
04474        detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,whichext,
04475                                          pafregexp,procatg_lintbl,
04476                                          pipeline_name,recipe_name,
04477                                          "qc02",lint_qclist,0);
04478 
04479        if(detmon_lg_config.pix2pix) 
04480        {
04481 
04482           detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
04483                                             whichext,pafregexp,
04484                                             procatg_coeffscube,
04485                                             pipeline_name,recipe_name,
04486                                             "qc03",linc_qclist,1);
04487 
04488           detmon_lg_save_paf_product(ref_frame,flag_sets,which_set,
04489                                             whichext,pafregexp,procatg_bpm,
04490                                             pipeline_name,recipe_name,
04491                                             "qc04",bpm_qclist,1);
04492        }
04493     }
04494 
04495     end_skip;
04496       cpl_msg_info(cpl_func,"exit");
04497 
04498     cpl_propertylist_delete(xplist);
04499     if(plist!=NULL) {
04500        cpl_propertylist_delete(plist);
04501        plist=NULL;
04502     }
04503 
04504     irplib_free(&NAME_O);
04505     cpl_free(PREF_O);
04506     cpl_free(pcatg_plane);
04507     cpl_propertylist_delete(mainplist);
04508     cpl_propertylist_delete(mypro_lintbl);
04509     cpl_propertylist_delete(mypro_gaintbl);
04510     cpl_propertylist_delete(mypro_coeffscube);
04511     cpl_propertylist_delete(mypro_bpm);
04512     cpl_propertylist_delete(mypro_corr);
04513     cpl_propertylist_delete(mypro_diff);
04514 
04515     return cpl_error_get_code();
04516 }
04517 
04518 
04519 /*---------------------------------------------------------------------------*/
04527 /*---------------------------------------------------------------------------*/
04528 static cpl_error_code
04529 detmon_opt_contamination(const cpl_imagelist * ons,
04530                 const cpl_imagelist * offs,
04531                 unsigned mode,
04532                                 cpl_propertylist * qclist)
04533 {
04534 
04535     double                  median[5] = {0, 0, 0, 0, 0};
04536 
04537     cpl_image * dif1=NULL;
04538     cpl_image * dif2=NULL;
04539     cpl_image * dif_avg=NULL;
04540     char* kname=NULL;
04541     int offsize = cpl_imagelist_get_size(offs);
04542 
04543     /* Algorithm defined: substract ON - OFF and average 2 differences */
04544     dif1 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
04545                                      cpl_imagelist_get_const(offs, 0));
04546 
04547     if (offsize == 1 || mode & IRPLIB_LIN_COLLAPSE)
04548         dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
04549                                          cpl_imagelist_get_const(offs, 0));
04550     else if (mode & IRPLIB_LIN_NO_COLLAPSE)
04551         dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
04552                                          cpl_imagelist_get_const(offs, 1));
04553 
04554     dif_avg = cpl_image_average_create(dif1, dif2);
04555 
04556     cpl_image_abs(dif_avg);
04557 
04558     median[0] = cpl_image_get_median_window(dif_avg,
04559                         detmon_lg_config.llx1,
04560                         detmon_lg_config.lly1,
04561                         detmon_lg_config.urx1,
04562                         detmon_lg_config.ury1);
04563 
04564     skip_if(0);
04565     irplib_free(&kname);
04566     kname=cpl_sprintf("%s%d", DETMON_QC_CONTAM,1);
04567 
04568     if(cpl_propertylist_has(qclist,kname)){
04569        skip_if(cpl_propertylist_update_double(qclist,kname,median[0]));
04570     } else {
04571        skip_if(cpl_propertylist_append_double(qclist,kname,median[0]));
04572        skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04573     }
04574     median[1] = cpl_image_get_median_window(dif_avg,
04575                         detmon_lg_config.llx2,
04576                         detmon_lg_config.lly2,
04577                         detmon_lg_config.urx2,
04578                         detmon_lg_config.ury2);
04579 
04580     skip_if(0);
04581     irplib_free(&kname);
04582     kname=cpl_sprintf("%s%d", DETMON_QC_CONTAM,2);
04583     if(cpl_propertylist_has(qclist,kname)){
04584        skip_if(cpl_propertylist_update_double(qclist,kname,median[1]));
04585     } else {
04586        skip_if(cpl_propertylist_append_double(qclist,kname,median[1]));
04587        skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04588     }
04589     median[2] = cpl_image_get_median_window(dif_avg,
04590                         detmon_lg_config.llx3,
04591                         detmon_lg_config.lly3,
04592                         detmon_lg_config.urx3,
04593                         detmon_lg_config.ury3);
04594     skip_if(0);
04595     irplib_free(&kname);
04596     kname=cpl_sprintf("%s%d", DETMON_QC_CONTAM,3);
04597     if(cpl_propertylist_has(qclist,kname)){
04598        skip_if(cpl_propertylist_update_double(qclist,kname,median[2]));
04599     } else {
04600        skip_if(cpl_propertylist_append_double(qclist,kname,median[2]));
04601        skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04602     }
04603 
04604     median[3] = cpl_image_get_median_window(dif_avg,
04605                         detmon_lg_config.llx4,
04606                         detmon_lg_config.lly4,
04607                         detmon_lg_config.urx4,
04608                         detmon_lg_config.ury4);
04609     skip_if(0);
04610     irplib_free(&kname);
04611     kname=cpl_sprintf("%s%d", DETMON_QC_CONTAM,4);
04612     if(cpl_propertylist_has(qclist,kname)){
04613        skip_if(cpl_propertylist_update_double(qclist,kname,median[3]));
04614     } else {
04615        skip_if(cpl_propertylist_append_double(qclist,kname,median[3]));
04616        skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04617     }
04618 
04619     median[4] = cpl_image_get_median_window(dif_avg,
04620                         detmon_lg_config.llx5,
04621                         detmon_lg_config.lly5,
04622                         detmon_lg_config.urx5,
04623                         detmon_lg_config.ury5);
04624     skip_if(0);
04625     irplib_free(&kname);
04626     kname=cpl_sprintf("%s%d", DETMON_QC_CONTAM,5);
04627     if(cpl_propertylist_has(qclist,kname)){
04628        skip_if(cpl_propertylist_update_double(qclist,kname,median[4]));
04629     } else {
04630        skip_if(cpl_propertylist_append_double(qclist,kname,median[4]));
04631        skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04632     }
04633     end_skip;
04634 
04635     cpl_image_delete(dif1);
04636     cpl_image_delete(dif2);
04637     cpl_image_delete(dif_avg);
04638     irplib_free(&kname);
04639 
04640     return cpl_error_get_code();
04641 }
04642 
04643 /*---------------------------------------------------------------------------*/
04650 /*---------------------------------------------------------------------------*/
04651 /*
04652 static cpl_error_code
04653 detmon_opt_lampcr(cpl_frameset * cur_fset, int ext)
04654 {
04655     cpl_image        * on        = NULL;
04656     cpl_image        * off       = NULL;
04657     cpl_frame        * first_off = NULL;
04658     cpl_frame        * first_on  = NULL;
04659     cpl_propertylist * plist     = NULL;
04660     double             dit;
04661 
04662     cpl_ensure_code(cur_fset != NULL, CPL_ERROR_NULL_INPUT);
04663 
04664     skip_if((first_off = cpl_frameset_get_first(cur_fset)) == NULL);
04665     skip_if((first_on  = cpl_frameset_get_next (cur_fset)) == NULL);
04666 
04667     on = cpl_image_load(cpl_frame_get_filename(first_on),
04668                         CPL_TYPE_FLOAT, 0, ext);
04669     off = cpl_image_load(cpl_frame_get_filename(first_off),
04670                          CPL_TYPE_FLOAT, 0, ext);
04671     skip_if(cpl_image_subtract(on, off));
04672 
04673     plist = cpl_propertylist_load(cpl_frame_get_filename(first_on), 0);
04674     skip_if(plist == NULL);
04675 
04676     dit = irplib_pfits_get_dit_opt(plist);
04677 
04678     detmon_lg_config.cr = cpl_image_get_mean(on) / dit;
04679 
04680     end_skip;
04681 
04682     cpl_image_delete(on);
04683     cpl_image_delete(off);
04684     cpl_propertylist_delete(plist);
04685 
04686     return cpl_error_get_code();
04687 }
04688 */
04689 /*---------------------------------------------------------------------------*/
04697 /*---------------------------------------------------------------------------*/
04698 int
04699 detmon_lg_dfs_set_groups(cpl_frameset * set,
04700                                 const char *tag_on, const char *tag_off)
04701 {
04702     cpl_frame              *cur_frame;
04703     const char             *tag;
04704     int                     nframes;
04705     int                     i;
04706 
04707     /* Check entries */
04708     if(set == NULL)
04709         return -1;
04710 
04711     /* Initialize */
04712     nframes = cpl_frameset_get_size(set);
04713 
04714     /* Loop on frames */
04715     for(i = 0; i < nframes; i++) {
04716         cur_frame = cpl_frameset_get_frame(set, i);
04717         tag = cpl_frame_get_tag(cur_frame);
04718 
04719         /* RAW frames */
04720         if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
04721             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
04722         /* CALIB frames */
04723 
04724 /*        else if (!strcmp(tag, IIINSTRUMENT_CALIB_FLAT))
04725             cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_CALIB);
04726 */
04727     }
04728     return 0;
04729 }
04730 
04731 
04732 /*---------------------------------------------------------------------------*/
04740 /*---------------------------------------------------------------------------*/
04741 static cpl_error_code
04742 detmon_lg_fits_coeffs_and_bpm2chip(cpl_imagelist ** coeffs_ptr,
04743                                           cpl_image **bpms_ptr)
04744 {
04745    cpl_image* dummy_bpm=NULL;
04746    cpl_image * dummy_coeff=NULL;
04747    cpl_imagelist * dummy_coeffs=NULL;
04748    int * db_p=NULL;
04749    int * rb_p =NULL;
04750    float ** dcs_p;
04751    float ** rcs_p;
04752    int dlength=0;
04753    int rlength=0;
04754    int shift_idx=0;
04755    int i=0;
04756    int k=0;
04757    int j=0;
04758 
04759    dummy_bpm = cpl_image_new(detmon_lg_config.nx,
04760                              detmon_lg_config.ny,
04761                              CPL_TYPE_INT);
04762    dummy_coeffs = cpl_imagelist_new();
04763 
04764    db_p = cpl_image_get_data_int(dummy_bpm);
04765    rb_p = cpl_image_get_data_int(*bpms_ptr);;  
04766    dcs_p = cpl_malloc(sizeof(float *) * (detmon_lg_config.order + 1));
04767    rcs_p = cpl_malloc(sizeof(float *) * (detmon_lg_config.order + 1));
04768    dlength = detmon_lg_config.nx;
04769    rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
04770    for (i = 0; i <= detmon_lg_config.order; i++) 
04771    {
04772       dummy_coeff = cpl_image_new(detmon_lg_config.nx,
04773                                   detmon_lg_config.ny,
04774                                   CPL_TYPE_FLOAT);
04775 
04776       cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
04777       dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
04778       rcs_p[i] = cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
04779    }
04780    /*copy the coefficients from temporary image to the dummy_bpm*/  
04781    for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++) 
04782    {
04783       for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++) 
04784       {
04785          shift_idx=(i - detmon_lg_config.lly + 1) * rlength +
04786             j - detmon_lg_config.llx + 1;
04787          *(db_p + i * dlength + j) = *(rb_p + shift_idx);
04788          for (k = 0; k <= detmon_lg_config.order; k++) 
04789          {
04790             *(dcs_p[k] + i * dlength + j) =
04791                *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
04792                  j - detmon_lg_config.llx + 1);
04793          }
04794       }
04795    }
04796    cpl_imagelist_delete(*coeffs_ptr);
04797    cpl_image_delete(*bpms_ptr);
04798    *coeffs_ptr = dummy_coeffs;
04799    *bpms_ptr = dummy_bpm;
04800    cpl_free(dcs_p);
04801    cpl_free(rcs_p);
04802 
04803    return cpl_error_get_code();
04804 }
04805 
04806 /* Not used so we temporaryly comment it out
04807 static cpl_error_code
04808 detmon_lg_qclog_lin_coeff(cpl_imagelist* coeffs_ptr, const int order, cpl_propertylist* linc_qclist)
04809 {
04810   cpl_image* image=NULL;
04811   int i=0;
04812   double coeff=0;
04813   double * pcoeffs = cpl_malloc(sizeof(double)*(order + 1));
04814   char* name_o1=NULL;
04815   char* name_o2=NULL;
04816 
04817   for(i = 0; i <= order; i++)
04818   {
04819     image = cpl_imagelist_get(coeffs_ptr, i);
04820     coeff = cpl_image_get_median(image);
04821     pcoeffs[i] = coeff;
04822     name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
04823     name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
04824     assert(name_o1 != NULL);
04825     assert(name_o2 != NULL);
04826     cpl_propertylist_append_double(linc_qclist, name_o1, coeff);
04827     cpl_propertylist_set_comment(linc_qclist,name_o1,DETMON_QC_LIN_COEF_C);
04828     cpl_free(name_o1);
04829     name_o1= NULL;
04830     cpl_propertylist_append_double(linc_qclist, name_o2,cpl_image_get_stdev(image));
04831     cpl_propertylist_set_comment(linc_qclist,name_o2,DETMON_QC_LIN_COEF_ERR_C);
04832     cpl_free(name_o2);
04833     name_o2= NULL;
04834   }
04835   cpl_free(pcoeffs);
04836 
04837   return cpl_error_get_code();
04838 }
04839 */
04840 
04841 /*---------------------------------------------------------------------------*/
04855 /*---------------------------------------------------------------------------*/
04856 static cpl_error_code
04857 detmon_lg_reduce_all(const cpl_table * linear_table,
04858     cpl_propertylist * gaint_qclist,
04859     cpl_propertylist * lint_qclist,
04860     cpl_propertylist * linc_qclist,
04861     cpl_propertylist * bpm_qclist,
04862     cpl_imagelist ** coeffs_ptr,
04863     cpl_image ** bpms_ptr,
04864     const cpl_imagelist * linearity_inputs,
04865     const cpl_table * gain_table,
04866     int which_ext, cpl_boolean opt_nir)
04867 {
04868 
04869   int                     nbpixs = 0;
04870   const int               nsets = cpl_table_get_nrow(linear_table);
04871   double autocorr;
04872   cpl_polynomial         *poly_linfit = NULL;
04873   cpl_image              *fiterror = NULL;
04874   char * name_o1 = NULL;
04875   char * name_o2 = NULL;
04876   double * pcoeffs = cpl_malloc(sizeof(double)*(detmon_lg_config.order + 1));
04877   unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
04878   double min_val=0;
04879   double max_val=0;
04880   cpl_vector *x =NULL;
04881   const cpl_vector *y =NULL;
04882 
04883 
04884   const cpl_image * first = NULL;
04885   int sizex = 0;
04886   int sizey = 0;
04887 
04888   int vsize = 0;
04889   cpl_size deg=0;
04890   /* FIXME: This should go before the x and y vectors.
04891        Checking for all the inputs */
04892   cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
04893   cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
04894   cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
04895   cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
04896 
04897   skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
04898       detmon_lg_config.method));
04899   skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
04900       DETMON_QC_METHOD_C));
04901 
04902   if (!strcmp(detmon_lg_config.method, "PTC")) {
04903     /* Computation of GAIN via polynomial fit */
04904     if (detmon_lg_config.exts >= 0) {
04905       cpl_msg_info(cpl_func,
04906           "Polynomial fitting for the GAIN (constant term method)");
04907     } else {
04908       cpl_msg_info(cpl_func,
04909           "Polynomial fitting for the GAIN (constant term method)"
04910           " for extension nb %d", which_ext);
04911     }
04912     skip_if(detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
04913   } else {
04914     skip_if(detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
04915   }
04916 
04917   /*^FIXME: This shouldn't be written when no applied */
04918   /* Lamp flux */
04919   if(detmon_lg_config.lamp_ok) {
04920     skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
04921         detmon_lg_config.cr));
04922     skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
04923         DETMON_QC_LAMP_FLUX_C));
04924   }
04925 
04926   /*^FIXME: This shouldn't be written when no applied */
04927   if(detmon_lg_config.autocorr == TRUE) {
04928     autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
04929     skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
04930         autocorr));
04931     skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
04932         DETMON_QC_AUTOCORR_C));
04933   }
04934   if (detmon_lg_config.exts >= 0) {
04935     cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix");
04936   } else {
04937     cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix"
04938         " for extension nb %d", which_ext);
04939   }
04940 
04941   if(!detmon_lg_config.pix2pix) {
04942     double mse = 0;
04943     /* Computation of LINEARITY via polynomial fit */
04944     y = cpl_vector_wrap(nsets,
04945         (double *)cpl_table_get_data_double_const(linear_table,
04946             "MED"));
04947 
04948     if (opt_nir == NIR) {
04949       x = cpl_vector_wrap(nsets,
04950           (double *)cpl_table_get_data_double_const(linear_table,
04951               "DIT"));
04952     } else {
04953       x = cpl_vector_wrap(nsets,
04954           (double *)cpl_table_get_data_double_const(linear_table,
04955               "EXPTIME"));
04956     }
04957 
04958     if(x == NULL || y == NULL) {
04959       cpl_vector_unwrap((cpl_vector *)x);
04960       cpl_vector_unwrap((cpl_vector *)y);
04961       /*
04962        * As x and y are const vectors, if they would be defined at the
04963        * beginning of the function (required for skip_if - end_skip
04964        * scheme), they couldn't be initialised to NULL (required too).
04965        * Therefore, they are considered apart from the scheme.
04966        */
04967       skip_if(1);
04968     }
04969 
04970     cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
04971     poly_linfit = irplib_polynomial_fit_1d_create(x, y,
04972         detmon_lg_config.order,
04973         &mse);
04974 
04975     if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
04976       cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
04977       mse = 0;
04978     }
04979 
04980     if(poly_linfit == NULL) {
04981       cpl_vector_unwrap((cpl_vector *)x);
04982       cpl_vector_unwrap((cpl_vector *)y);
04983       /* See comment in previous error checking if() statement */
04984       skip_if(1);
04985     }
04986 
04987 
04988     min_val=cpl_vector_get_min(y);
04989     max_val=cpl_vector_get_max(y);
04990 
04991     cpl_vector_unwrap((cpl_vector *)x);
04992     cpl_vector_unwrap((cpl_vector *)y);
04993 
04994     for(deg = 0; deg <= detmon_lg_config.order; deg++) {
04995       const double            coeff =
04996           cpl_polynomial_get_coeff(poly_linfit, &deg);
04997       char                   *name_o =
04998           cpl_sprintf("ESO QC LIN COEF%" CPL_SIZE_FORMAT "", deg);
04999       assert(name_o != NULL);
05000       skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
05001       skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
05002           DETMON_QC_LIN_COEF_C));
05003 
05004       cpl_free(name_o);
05005       pcoeffs[deg] = coeff;
05006     }
05007     skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
05008     skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
05009         DETMON_QC_ERRFIT_MSE_C));
05010 
05011 
05012   } else { 
05013     /* pix2pix == TRUE */
05014     y = cpl_vector_wrap(nsets,
05015         (double *)cpl_table_get_data_double_const(linear_table,
05016             "MED"));
05017 
05018     if (opt_nir == NIR)
05019     {
05020       x = cpl_vector_wrap(nsets,
05021           (double *)cpl_table_get_data_double_const(linear_table,
05022               "DIT"));
05023     } else {
05024       x = cpl_vector_wrap(nsets,
05025           (double *)cpl_table_get_data_double_const(linear_table,
05026               "EXPTIME"));
05027 
05028     }
05029 
05030     first = cpl_imagelist_get_const(linearity_inputs, 0);
05031     sizex = cpl_image_get_size_x(first);
05032     sizey = cpl_image_get_size_y(first);
05033     vsize = cpl_vector_get_size(x);
05034     fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
05035     *coeffs_ptr =
05036         cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
05037             detmon_lg_config.order, FALSE,
05038             CPL_TYPE_FLOAT, fiterror);
05039     min_val=cpl_vector_get_min(y);
05040     max_val=cpl_vector_get_max(y);
05041     cpl_vector_unwrap((cpl_vector*)x);
05042     cpl_vector_unwrap((cpl_vector*)y);
05043 
05044     irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
05045         "Failed polynomial fit");
05046     //detmon_lg_qclog_lin_coeff(*coeffs_ptr, detmon_lg_config.order,linc_qclist);
05047 
05048     for(deg = 0; deg <= detmon_lg_config.order; deg++)
05049     {
05050         cpl_image *image = cpl_imagelist_get(*coeffs_ptr, deg);
05051        const double coeff = cpl_image_get_median(image);
05052        pcoeffs[deg] = coeff;
05053        name_o1 = cpl_sprintf("ESO QC LIN COEF%d", (int)deg);
05054        name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", (int)deg);
05055         assert(name_o1 != NULL);
05056         assert(name_o2 != NULL);
05057         skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
05058         skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
05059          DETMON_QC_LIN_COEF_C));
05060         cpl_free(name_o1);
05061        name_o1= NULL;
05062         skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
05063          cpl_image_get_stdev(image)));
05064         skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
05065          DETMON_QC_LIN_COEF_ERR_C));
05066         cpl_free(name_o2);
05067        name_o2= NULL;
05068     }
05069 
05070 
05071     if(detmon_lg_config.order == vsize - 1)
05072     {
05073       cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
05074       skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
05075           0.0));
05076       skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
05077           DETMON_QC_ERRFIT_C));
05078     } else
05079     {
05080       skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
05081           cpl_image_get_median(fiterror)));
05082       skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
05083           DETMON_QC_ERRFIT_C));
05084     }
05085   } /* end case pix2pix == TRUE */
05086 
05087   skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
05088       min_val));
05089   skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
05090       DETMON_QC_COUNTS_MIN_C));
05091   skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
05092       max_val));
05093   skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
05094       DETMON_QC_COUNTS_MAX_C));
05095   skip_if(detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
05096       detmon_lg_config.order));
05097   /* Detection of bad pixels */
05098   if (detmon_lg_config.exts >= 0)
05099   {
05100     cpl_msg_info(cpl_func, "Bad pixel detection");
05101   } else
05102   {
05103     cpl_msg_info(cpl_func, "Bad pixel detection"
05104         " for extension nb %d", which_ext);
05105   }
05106   if(detmon_lg_config.pix2pix)
05107   {
05108 
05109     *bpms_ptr = detmon_bpixs(*coeffs_ptr, detmon_lg_config.bpmbin,
05110         detmon_lg_config.kappa, &nbpixs);
05111 
05112 /*
05113     *bpms_ptr = detmon_bpixs2(x,linearity_inputs,*coeffs_ptr,gain_table,
05114         detmon_lg_config.order,detmon_lg_config.bpmbin,detmon_lg_config.kappa,&nbpixs);
05115 */
05116     /*
05117     cpl_vector_unwrap((cpl_vector*)x);
05118     cpl_vector_unwrap((cpl_vector*)y);
05119     */
05120     skip_if(*bpms_ptr == NULL);
05121     /* we still have to unwrapp x & y that we kept for bpixs2 function */ 
05122   }
05123 
05124 
05125   skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
05126   skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
05127       DETMON_QC_NUM_BPM_C));
05128   if(detmon_lg_config.lamp_stability != 0.0)
05129   {
05130     skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
05131         detmon_lg_config.lamp_stability));
05132     skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
05133         DETMON_QC_LAMP_STAB_C));
05134   }
05135   /* Fit COEFFS_CUBE and BPM outputs to whole-chip size images (DFS05711) */
05136   if (!detmon_lg_config.wholechip && detmon_lg_config.pix2pix)
05137   {
05138     detmon_lg_fits_coeffs_and_bpm2chip(coeffs_ptr,bpms_ptr);
05139   }
05140   end_skip;
05141 
05142   cpl_free(pcoeffs);
05143   cpl_free(name_o1);
05144    cpl_free(name_o2);
05145   cpl_image_delete(fiterror);
05146   cpl_polynomial_delete(poly_linfit);
05147 
05148 
05149 
05150   return cpl_error_get_code();
05151 }
05152 
05153 /*---------------------------------------------------------------------------*/
05161 /*---------------------------------------------------------------------------*/
05162 static cpl_error_code
05163 detmon_lg_lineff(double * pcoeffs,
05164                         cpl_propertylist * qclist,
05165                         int ref_level,
05166                         int order)
05167 {
05168     double           lineff = 0;
05169     double           root = 0;
05170     double residual, slope;
05171     int i;
05172     cpl_size deg=0;
05173     cpl_polynomial * poly = cpl_polynomial_new(1);
05174 
05175 
05176     /*
05177      * Construction of the polynomial F_m(F_r) from F_m(t),
05178      * using F_r = a_1 * t.
05179      */
05180     /*
05181     for (deg = 0; deg <= order; deg++) {
05182        cpl_msg_info(cpl_func,"coef[%d]=%g",deg,pcoeffs[deg]);
05183     }
05184     */
05185 
05186 
05187     pcoeffs[0] -= ref_level;
05188 
05189     for (i = 2; i <= order; i++)
05190     {
05191         int j;
05192         for(j = 0; j < i; j++)
05193         {
05194             pcoeffs[i] /= pcoeffs[1];
05195         }
05196     }
05197 
05198     pcoeffs[1] = 1;
05199 
05200     for (deg = 0; deg <= order; deg++) {
05201        /*cpl_msg_info(cpl_func,"coef[%d]=%g",deg,pcoeffs[deg]);*/
05202     skip_if(cpl_polynomial_set_coeff(poly, &deg, pcoeffs[deg]));
05203     }
05204 
05205     /*
05206      * Verification of validity of first guess (0).
05207      * The root to be found will be in the same interval of monotony
05208      * of the first guess; therefore, slope must be greater than 0.
05209      * Slope > 0 and poly(root) = 0 force also residual to be negative.
05210      */
05211     residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
05212 
05213     if (slope <= 0.0 && residual >= 0.0) {
05214     cpl_msg_warning(cpl_func, "Reference level (--ref_level) outside"
05215             " linearity range of the detector. Cannot compute"
05216             " linearity efficiency (QC.LINEFF).");
05217     lineff = -1;
05218     }
05219     else
05220     {
05221         cpl_error_code err = cpl_polynomial_solve_1d(poly, 0.0, &root, 1);
05222         /*
05223            cpl_msg_info(cpl_func,"root=%g ref_level=%d lin_eff=%d",
05224                         root,ref_level,ref_level);
05225                         */
05226         if (err == CPL_ERROR_NONE)
05227         {
05228 
05229             lineff = (root - ref_level) / ref_level;
05230         }
05231         else
05232         {
05233             cpl_error_reset();
05234             cpl_msg_warning(cpl_func,
05235                     "Cannot compute linearity efficiency (QC.LINEFF)"
05236                     "for the current combination "
05237                     " of (--ref-level equal %d) and (--order equal %d) parameters. Try "
05238                     "to decrease (--ref-level) value.", ref_level, order);
05239         }
05240     }
05241     cpl_msg_warning(cpl_func, "DETMON_QC_LIN_EFF=%f",lineff );
05242     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
05243                        lineff));
05244     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
05245                      DETMON_QC_LIN_EFF_C));
05246 
05247     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
05248                        ref_level));
05249     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
05250                      DETMON_QC_LIN_EFF_FLUX_C));
05251 
05252     end_skip;
05253 
05254     cpl_polynomial_delete(poly);
05255 
05256     return cpl_error_get_code();
05257 }
05258 
05259 /*---------------------------------------------------------------------------*/
05266 /*---------------------------------------------------------------------------*/
05267 static cpl_error_code
05268 detmon_lg_qc_ptc(const cpl_table  * gain_table,
05269             cpl_propertylist * qclist, unsigned mode, int rows_in_gain)
05270 {
05271     double                  mse = 0;
05272     cpl_polynomial         *poly_fit = NULL;
05273     cpl_polynomial         *poly_fit2 = NULL;
05274     cpl_size i;
05275     const int               nsets = rows_in_gain;
05276 
05277     cpl_vector             *x = NULL;
05278     cpl_vector             *y = NULL;
05279 
05280     cpl_errorstate                prestate;
05281     double coef = 0;
05282     cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
05283     cpl_ensure_code(qclist     != NULL, CPL_ERROR_NULL_INPUT);
05284 
05285     x = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
05286 
05287     y = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
05288 
05289     skip_if(x == NULL || y == NULL);
05290    if (0 == detmon_lg_check_before_gain(x, y))
05291    {
05292       if (x)
05293       {
05294          cpl_vector_unwrap(x);
05295       }
05296       if (y)
05297       {
05298          cpl_vector_unwrap(y);
05299       }   
05300       return CPL_ERROR_NONE;
05301    }
05302     /*it is not really a MSE, but chi square of the fit, see cpl_vector_fill_polynomial_fit_residual for details*/
05303     poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
05304     skip_if(poly_fit == NULL);
05305 
05306     /* Write the QC params corresponding to the fitting of the GAIN */
05307     i = 1;
05308     prestate = cpl_errorstate_get();
05309     coef = cpl_polynomial_get_coeff(poly_fit, &i);
05310     skip_if (!cpl_errorstate_is_equal(prestate) || coef==0);
05311     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
05312     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
05313                      DETMON_QC_CONAD_C));
05314    if (coef != 0)
05315    {
05316       skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
05317                        1 / coef));
05318       skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
05319                      DETMON_QC_GAIN_C));
05320     }          
05321 /*  MSE is removed - see DFS07358 for details
05322     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE, mse));
05323     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
05324                      DETMON_QC_GAIN_MSE_C));
05325                      */
05326     i = 0;
05327 /* QC.RON computation is disabled, see DFS05852 for details*/
05328 
05329 /* *     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_RON,
05330                        cpl_polynomial_get_coeff(poly_fit, &i)));
05331     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_RON,
05332                      DETMON_QC_RON_C));
05333 */
05334    if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
05335    const cpl_vector             *x2 =
05336       cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT_CORR"));
05337    const cpl_vector             *y2 =
05338       cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
05339 
05340     if(x2 == NULL || y2 == NULL) {
05341         cpl_vector_unwrap((cpl_vector *)x2);
05342         cpl_vector_unwrap((cpl_vector *)y2);
05343         /*
05344          * As x and y are const vectors, if they would be defined at the
05345          * beginning of the function (required for skip_if - end_skip
05346          * scheme), they couldn't be initialised to NULL (required too).
05347          * Therefore, they are considered apart from the scheme.
05348          */
05349         skip_if(1);
05350     }
05351 
05352     /* Revise mse, maybe used afterwards */
05353     poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
05354     if(poly_fit2 == NULL) {
05355         cpl_vector_unwrap((cpl_vector *)x2);
05356         cpl_vector_unwrap((cpl_vector *)y2);
05357 
05358         cpl_msg_error(cpl_func, "Error during polynomial fit, err[%s]", cpl_error_get_where());
05359         /* See comment in previous error checking if() statement */
05360         skip_if(1);
05361     }
05362     skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
05363     cpl_vector_unwrap((cpl_vector *)x2);
05364     cpl_vector_unwrap((cpl_vector *)y2);
05365     skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
05366     /* Write the QC params corresponding to the fitting of the GAIN */
05367     i = 1;
05368     prestate = cpl_errorstate_get();
05369     coef = cpl_polynomial_get_coeff(poly_fit2, &i);
05370     skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
05371     skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
05372 
05373     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
05374                            coef));
05375     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
05376                          DETMON_QC_CONAD_CORR_C));
05377 
05378     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
05379                            1 / coef));
05380     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
05381                          DETMON_QC_GAIN_CORR_C));
05382     }
05383 
05384     end_skip;
05385 
05386    /*cleanup*/
05387     cpl_vector_unwrap(x);
05388     cpl_vector_unwrap(y);
05389     cpl_polynomial_delete(poly_fit);
05390     cpl_polynomial_delete(poly_fit2);
05391 
05392     return cpl_error_get_code();
05393 }
05394 
05401 static int detmon_lg_check_before_gain(const cpl_vector* x, const cpl_vector* y)
05402 {
05403    const double TOLERANCE = 1e-37;/*MINDOUBLE is not everywhere defined (Mac);*/
05404    double xmin = cpl_vector_get_min(x);
05405    double xmax = cpl_vector_get_max(x);
05406    double ymin = cpl_vector_get_min(y);
05407    double ymax = cpl_vector_get_max(y);
05408    double ystdev = cpl_vector_get_stdev(y);
05409    double xstdev = cpl_vector_get_stdev(x);   
05410    int retval = 1;
05411    if (fabs(xmax-xmin) < TOLERANCE && 
05412        fabs(ymax - ymin) < TOLERANCE &&
05413        xstdev < TOLERANCE &&
05414        ystdev < TOLERANCE)
05415    {
05416       cpl_msg_warning(cpl_func, "An empty frame has been detected, linearity, coeffs, gain, FPN values will not be computed.");
05417       retval = 0;
05418    }
05419    return retval;
05420 }
05421 /*---------------------------------------------------------------------------*/
05430 /*---------------------------------------------------------------------------*/
05431 static cpl_error_code
05432 detmon_lg_qc_med(const cpl_table * gain_table,
05433                 cpl_propertylist * qclist, int rows_in_gain)
05434 {
05435 
05436    double gain=0;
05437    int q_STUB; /* dummy variable to remove warning "unused var" */
05438    cpl_vector             *x = NULL;
05439    cpl_vector             *y = NULL;   
05440    int check_result = 0;
05441    
05442    q_STUB = rows_in_gain;
05443    
05444     x = cpl_vector_wrap(rows_in_gain, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
05445     y = cpl_vector_wrap(rows_in_gain, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
05446     check_result = detmon_lg_check_before_gain(x, y);
05447    if (x)
05448    {
05449       cpl_vector_unwrap(x);
05450    }
05451    if (y)
05452    {
05453       cpl_vector_unwrap(y);
05454    }   
05455    if (0 == check_result)
05456    {
05457       return CPL_ERROR_NONE;
05458    }
05459 
05460    gain=cpl_table_get_column_median(gain_table, "GAIN");
05461 
05462    skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
05463 
05464    skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
05465                                         DETMON_QC_GAIN_C));
05466 
05467    skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
05468                                           cpl_table_get_column_stdev
05469                                           (gain_table, "GAIN")));
05470    skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
05471                                         DETMON_QC_GAIN_MSE_C));
05472 
05473    skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
05474    skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
05475                                         DETMON_QC_CONAD_C));
05476 
05477 
05478    gain=cpl_table_get_column_median(gain_table, "GAIN_CORR");
05479 
05480    skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
05481                                           gain));
05482    skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
05483                                         DETMON_QC_GAIN_CORR_C));
05484 
05485 
05486    skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
05487    skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
05488                                         DETMON_QC_CONAD_CORR_C));
05489 
05490 
05491     end_skip;
05492 
05493     return cpl_error_get_code();
05494 }
05495 
05496 
05497 /*---------------------------------------------------------------------------*/
05506 /*---------------------------------------------------------------------------*/
05507 static cpl_error_code
05508 detmon_lg_rescale(cpl_imagelist * to_rescale)
05509 {
05510     double                  med1 =
05511         cpl_image_get_median(cpl_imagelist_get(to_rescale, 0));
05512     double                  med2 =
05513         cpl_image_get_median(cpl_imagelist_get(to_rescale, 1));
05514 
05515     skip_if(0);
05516 
05517     if(fabs(med1 / med2 - 1) > 0.001) {
05518         if(med1 > med2)
05519             skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
05520                                             med1 / med2));
05521         else
05522             skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
05523                                             med2 / med1));
05524     }
05525 
05526     end_skip;
05527 
05528     return cpl_error_get_code();
05529 }
05530 
05531 static cpl_error_code
05532 detmon_pair_extract_next(const cpl_frameset * set,
05533                            int* iindex,
05534                            int* next_element,
05535                            double* dit_array,
05536                            cpl_frameset ** pair,
05537                                 double tolerance) /* detmon_lg_config.tolerance */
05538 {
05539     double dit = -100;
05540     double dit_next = -100;
05541     cpl_size* selection;
05542     int nsets_extracted = 0;
05543     cpl_ensure_code(set             != NULL, CPL_ERROR_NULL_INPUT);
05544     cpl_ensure_code(dit_array       != NULL, CPL_ERROR_NULL_INPUT);
05545     cpl_ensure_code(iindex          != NULL, CPL_ERROR_NULL_INPUT);
05546     cpl_ensure_code(pair            != NULL, CPL_ERROR_NULL_INPUT);
05547 
05548     nsets_extracted = cpl_frameset_get_size(set);
05549     selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
05550     memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
05551 
05552 
05553     dit = dit_array[*next_element ];
05554 /*  cpl_msg_info(cpl_func, "%d: dit %f",*next_element, dit ); */
05555     if (*next_element < nsets_extracted - 1)
05556     {
05557         dit_next = dit_array[*next_element + 1 ];
05558                 /* cpl_msg_info(cpl_func, "%d: dit %f",*next_element + 1, dit_next ); */
05559     }
05560     /* one element would be returned always */
05561     selection[iindex[*next_element] ] = 1;
05562     if (fabs(dit - dit_next) < tolerance)
05563     {
05564            /* return a second element of the pair */
05565         selection[iindex[*next_element + 1] ] = 1;
05566         (*next_element)++;
05567     }
05568     else
05569     {
05570         cpl_msg_warning(cpl_func, "DIT for the second frame in the pair is above tolerance level - could not be taken, dit1[%f] dit2[%f] next_element: %d . Check input data set and tolerance value", dit, dit_next, *next_element);
05571     }
05572     (*next_element)++;
05573     /* prepare frameset */
05574     cpl_frameset_delete(*pair);
05575     *pair = cpl_frameset_extract(set, selection, 1);
05576 
05577 
05578     cpl_free(selection);
05579     return cpl_error_get_code();
05580 }
05581 static cpl_error_code
05582 detmon_single_extract_next(const cpl_frameset * set,
05583                            int* iindex,
05584                            int* next_element,
05585                            double* dit_array,
05586                            cpl_frameset ** pair)
05587 {
05588     double dit = -100;
05589     cpl_size* selection;
05590     int nsets_extracted = 0;
05591     cpl_ensure_code(set             != NULL, CPL_ERROR_NULL_INPUT);
05592     cpl_ensure_code(dit_array       != NULL, CPL_ERROR_NULL_INPUT);
05593     cpl_ensure_code(iindex          != NULL, CPL_ERROR_NULL_INPUT);
05594     cpl_ensure_code(pair            != NULL, CPL_ERROR_NULL_INPUT);
05595 
05596     nsets_extracted = cpl_frameset_get_size(set);
05597     selection = cpl_malloc(sizeof(cpl_size) * nsets_extracted);
05598     memset(&selection[0], 0, sizeof(cpl_size) * nsets_extracted);
05599 
05600     nsets_extracted = cpl_frameset_get_size(set);
05601     dit = dit_array[iindex[*next_element] ];
05602     /* only one element would be returned */
05603     selection[iindex[*next_element] ] = 1;
05604     (*next_element)++;
05605     /* prepare frameset */
05606     cpl_frameset_delete(*pair);
05607     *pair = cpl_frameset_extract(set, selection, 1);
05608 
05609     cpl_free(selection);
05610     return cpl_error_get_code();
05611 }
05612 
05613 
05614 /*---------------------------------------------------------------------------*/
05703 /*---------------------------------------------------------------------------*/
05704 
05705 cpl_table *
05706 detmon_gain(const cpl_imagelist  * imlist_on,
05707            const cpl_imagelist  * imlist_off,
05708            const cpl_vector     * exptimes,
05709            const cpl_vector     * ndit,
05710            double                 tolerance,
05711            int                    llx,
05712            int                    lly,
05713            int                    urx,
05714            int                    ury,
05715                    double                 kappa,
05716                    int                    nclip,
05717                    int                    xshift,
05718                    int                    yshift,
05719            cpl_propertylist     * qclist,
05720            unsigned               mode,
05721            cpl_imagelist       ** diff_imlist,
05722            cpl_imagelist       ** autocorr_imlist)
05723 {
05724     cpl_table     * gain_table   = NULL;
05725     cpl_imagelist * difflist     = NULL;
05726     cpl_imagelist * autocorrlist = NULL;
05727     cpl_imagelist * c_onlist     = NULL;
05728     cpl_imagelist * c_offlist    = NULL;
05729     cpl_vector    * diffdits     = NULL;
05730     cpl_vector    * diffndits     = NULL;
05731     int rows_in_gain = 0;
05732     int             ndiffdits, ndits;
05733     int             i, j;
05734     cpl_boolean     opt_nir      = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
05735     const char    * method       = mode & IRPLIB_GAIN_PTC ? "PTC" : "MED";
05736 
05737     cpl_ensure(imlist_on  != NULL, CPL_ERROR_NULL_INPUT, NULL);
05738     cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
05739     cpl_ensure(exptimes   != NULL, CPL_ERROR_NULL_INPUT, NULL);
05740     cpl_ensure(qclist     != NULL, CPL_ERROR_NULL_INPUT, NULL);
05741 
05742     /* Create table with columns */
05743     gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
05744     skip_if(detmon_gain_table_create(gain_table, opt_nir));
05745 
05746 
05747     /* Search for different EXPTIME values */
05748     skip_if(detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,&diffndits));
05749     ndiffdits = cpl_vector_get_size(diffdits);
05750 
05751     ndits     = cpl_vector_get_size(exptimes);
05752 
05753     /* AUTOCORR processing requires both. They will become outputs later. */
05754     if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
05755     difflist     = cpl_imagelist_new();
05756     autocorrlist = cpl_imagelist_new();
05757     }
05758 
05759     if (mode & IRPLIB_GAIN_COLLAPSE) {
05760         if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05761         c_offlist = cpl_imagelist_duplicate(imlist_off);
05762         skip_if(detmon_lg_rescale(c_offlist));
05763         } else {
05764             c_offlist = (cpl_imagelist *) imlist_off;
05765         }
05766     }
05767 
05768     /* Loop over the different DITs found in EXPTIMEs */
05769     for (i = 0; i < ndiffdits; i++) {
05770         int c_nons;
05771         int c_noffs = 0; /* False (uninit) warning */
05772 
05773     double c_dit = 0;
05774     int c_ndit = 1;
05775 
05776         c_dit=cpl_vector_get(diffdits, i);
05777 
05778     if(opt_nir) {
05779       c_ndit=(int)cpl_vector_get(diffndits, i);
05780     }
05781 
05782     c_onlist  = cpl_imagelist_new();
05783     c_nons = 0;
05784 
05785     if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05786         c_offlist = cpl_imagelist_new();
05787         c_noffs = 0;
05788     }
05789 
05790     /* Extraction of images of EXPTIME i */
05791     for(j = 0; j < ndits; j++) {
05792         if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
05793                 /*
05794                  * First we get the corresponding image from the ON imlist.
05795                  * The option IRPLIB_GAIN_WITH_RESCALE requires to modify
05796                  * the input pixel buffer; therefore we must duplicate it.
05797                  * On the other hand, if this option is not required, there
05798                  * is no need for that duplication. We must only care that
05799                  * c_onlist must not be deleted but only unset.
05800                  */
05801                 cpl_image * im_on;
05802                 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05803                     const cpl_image * im =
05804                         cpl_imagelist_get_const(imlist_on, j);
05805                     im_on = cpl_image_duplicate(im);
05806                 } else {
05807                     im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
05808                 }
05809                 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
05810                 c_nons++;
05811 
05812                 /*
05813                  * Same explanation as above but for OFF imlist.
05814                  * Only necessary when IRPLIB_GAIN_NO_COLLAPSE required.
05815                  */
05816         if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05817                     cpl_image * im_off;
05818                     if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05819                         const cpl_image * im =
05820                           cpl_imagelist_get_const(imlist_off, j);
05821                         im_off = cpl_image_duplicate(im);
05822                     } else {
05823                         im_off =
05824                           (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
05825                     }
05826             skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
05827             c_noffs++;
05828         }
05829         }
05830     }
05831 
05832     /* If NO_COLLAPSE, must be the same number of images! */
05833     if (mode & IRPLIB_GAIN_NO_COLLAPSE)
05834         skip_if (c_nons != c_noffs);
05835 
05836     /* There must be pairs! */
05837     skip_if (c_nons == 0 || c_nons % 2 != 0);
05838 
05839     /* Rescaling */
05840     if(mode & IRPLIB_GAIN_WITH_RESCALE) {
05841         skip_if(detmon_lg_rescale(c_onlist));
05842         if (mode & IRPLIB_GAIN_NO_COLLAPSE)
05843         skip_if(detmon_lg_rescale(c_offlist));
05844     }
05845 
05846     /* The following loop is necessary for the case of multiple pairs
05847        of same EXPTIME values */
05848     while(c_nons > 0) {
05849         int rows_affected = 1;
05850         skip_if(detmon_gain_table_fill_row(gain_table,
05851                               c_dit,c_ndit,
05852                               autocorrlist,
05853                               difflist, c_onlist,
05854                               c_offlist, kappa, nclip,
05855                                                       llx, lly, urx, ury,
05856                                                       xshift, yshift,1E10,  i,
05857 mode, &rows_affected));
05858         if (rows_affected)
05859         {
05860             rows_in_gain++;
05861         }
05862             if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05863                 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05864                 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05865                 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05866                   cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05867                   cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05868                 }
05869             } else {
05870             cpl_imagelist_unset(c_onlist, 0);
05871                 skip_if(0);
05872                 cpl_imagelist_unset(c_onlist, 0);
05873                 skip_if(0);
05874                 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05875                   cpl_imagelist_unset(c_offlist, 0);
05876                   skip_if(0);
05877                   cpl_imagelist_unset(c_offlist, 0);
05878                   skip_if(0);
05879                 }
05880             }
05881             skip_if(0);
05882         c_nons -= 2;
05883     }
05884 
05885     cpl_imagelist_delete(c_onlist);
05886     if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05887           cpl_imagelist_delete(c_offlist);
05888     }
05889     }
05890 
05891     skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
05892     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
05893                      DETMON_QC_METHOD_C));
05894 
05895     /* Computation of GAIN via polynomial fit */
05896     if (mode & IRPLIB_GAIN_PTC) {
05897       skip_if(detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
05898     } else {
05899     skip_if(detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
05900     }
05901 
05902     if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
05903         double autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
05904     skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
05905                            autocorr));
05906     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
05907                          DETMON_QC_AUTOCORR_C));
05908     }
05909 
05910     if (diff_imlist != NULL) *diff_imlist = difflist;
05911     if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
05912 
05913     end_skip;
05914 
05915     cpl_vector_delete(diffdits);
05916     cpl_vector_delete(diffndits);
05917 
05918     return gain_table;
05919 }
05920 
05921 static cpl_error_code
05922 detmon_gain_table_create(cpl_table * gain_table,
05923                                 const cpl_boolean opt_nir)
05924 {
05925     if (opt_nir == NIR) {
05926     skip_if(cpl_table_new_column(gain_table, "DIT",     CPL_TYPE_DOUBLE));
05927     skip_if(cpl_table_new_column(gain_table, "NDIT",     CPL_TYPE_INT));
05928     } else { /* OPT */
05929     skip_if(cpl_table_new_column(gain_table, "EXPTIME", CPL_TYPE_DOUBLE));
05930     }
05931     skip_if(cpl_table_new_column(gain_table, "MEAN_ON1",    CPL_TYPE_DOUBLE));
05932     skip_if(cpl_table_new_column(gain_table, "MEAN_ON2",    CPL_TYPE_DOUBLE));
05933     skip_if(cpl_table_new_column(gain_table, "MEAN_OFF1",   CPL_TYPE_DOUBLE));
05934     skip_if(cpl_table_new_column(gain_table, "MEAN_OFF2",   CPL_TYPE_DOUBLE));
05935     skip_if(cpl_table_new_column(gain_table, "SIG_ON_DIF",  CPL_TYPE_DOUBLE));
05936     skip_if(cpl_table_new_column(gain_table, "SIG_OFF_DIF", CPL_TYPE_DOUBLE));
05937     skip_if(cpl_table_new_column(gain_table, "GAIN",        CPL_TYPE_DOUBLE));
05938     skip_if(cpl_table_new_column(gain_table, "AUTOCORR",    CPL_TYPE_DOUBLE));
05939     skip_if(cpl_table_new_column(gain_table, "GAIN_CORR",   CPL_TYPE_DOUBLE));
05940     skip_if(cpl_table_new_column(gain_table, "ADU",         CPL_TYPE_DOUBLE));
05941     skip_if(cpl_table_new_column(gain_table, "X_FIT",       CPL_TYPE_DOUBLE));
05942     skip_if(cpl_table_new_column(gain_table, "X_FIT_CORR",  CPL_TYPE_DOUBLE));
05943     skip_if(cpl_table_new_column(gain_table, "Y_FIT",       CPL_TYPE_DOUBLE));
05944     skip_if(cpl_table_new_column(gain_table, "Y_FIT_CORR",  CPL_TYPE_DOUBLE));
05945     skip_if(cpl_table_new_column(gain_table, "FLAG",  CPL_TYPE_INT));
05946 
05947     end_skip;
05948 
05949     return cpl_error_get_code();
05950 }
05951 
05952 static cpl_error_code
05953 detmon_lin_table_create(cpl_table * lin_table,
05954                                const cpl_boolean opt_nir)
05955 {
05956     if (opt_nir == NIR) {
05957     skip_if(cpl_table_new_column(lin_table, "DIT",     CPL_TYPE_DOUBLE));
05958     } else { /* OPT */
05959     skip_if(cpl_table_new_column(lin_table, "EXPTIME", CPL_TYPE_DOUBLE));
05960     }
05961     skip_if(cpl_table_new_column(lin_table, "MED",      CPL_TYPE_DOUBLE));
05962     skip_if(cpl_table_new_column(lin_table, "MEAN",     CPL_TYPE_DOUBLE));
05963     skip_if(cpl_table_new_column(lin_table, "MED_DIT",  CPL_TYPE_DOUBLE));
05964     skip_if(cpl_table_new_column(lin_table, "MEAN_DIT", CPL_TYPE_DOUBLE));
05965     skip_if(cpl_table_new_column(lin_table, "ADL",      CPL_TYPE_DOUBLE));
05966     end_skip;
05967 
05968     return cpl_error_get_code();
05969 }
05970 
05971 static cpl_vector *
05972 detmon_lg_find_dits(const cpl_vector * exptimes,
05973                            double             tolerance)
05974 {
05975     cpl_vector * dits  = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
05976     int          ndits = 0;
05977 
05978     int          i, j;
05979 
05980     /* First different EXPTIME */
05981     cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
05982     ndits = 1;
05983 
05984     /* Search for all different EXPTIMEs */
05985     for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
05986       int ndiffs = 0;
05987     for (j = 0; j < ndits; j++) {
05988         if (fabs(cpl_vector_get(exptimes, i) -
05989              cpl_vector_get(dits,     j)) > tolerance)
05990               ndiffs++;
05991     }
05992         if(ndiffs == ndits) {
05993           cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
05994           ndits++;
05995         }
05996     }
05997 
05998     cpl_vector_set_size(dits, ndits);
05999 
06000     return dits;
06001 }
06002 
06003 
06004 
06005 
06006 static cpl_error_code
06007 detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
06008                const cpl_vector * vec_ndits,
06009                            double             tolerance,
06010                            cpl_vector** diff_dits,
06011                cpl_vector** diff_ndits)
06012 {
06013     int          ndits = 0;
06014 
06015     int          i, j;
06016     int size=0;
06017 
06018 
06019     * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
06020     * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
06021 
06022     /* First different EXPTIME */
06023     cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
06024     cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
06025 
06026     ndits = 1;
06027     size=cpl_vector_get_size(exptimes);
06028     /* Search for all different EXPTIMEs */
06029     for(i = 1; i < size; i++) {
06030       int ndiffs = 0;
06031     for (j = 0; j < ndits; j++) {
06032         if (fabs(cpl_vector_get(exptimes, i) -
06033              cpl_vector_get(*diff_dits,j)) > tolerance)
06034               ndiffs++;
06035     }
06036         if(ndiffs == ndits) {
06037           cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
06038           cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
06039           ndits++;
06040         }
06041     }
06042 
06043     cpl_vector_set_size(*diff_dits, ndits);
06044     cpl_vector_set_size(*diff_ndits, ndits);
06045 
06046 
06047     return cpl_error_get_code();
06048 }
06049 
06050 
06051 /*---------------------------------------------------------------------------*/
06132 /*---------------------------------------------------------------------------*/
06133 
06134 cpl_table *
06135 detmon_lin(const cpl_imagelist  * imlist_on,
06136           const cpl_imagelist  * imlist_off,
06137           const cpl_vector     * exptimes,
06138           double                 tolerance,
06139           int                    llx,
06140           int                    lly,
06141           int                    urx,
06142           int                    ury,
06143           int                    order,
06144                   int                    ref_level,
06145                   double kappa,
06146                   cpl_boolean bpmbin,
06147           cpl_propertylist     * qclist,
06148           unsigned               mode,
06149           cpl_imagelist       ** coeffs_cube,
06150           cpl_image           ** bpm)
06151 {
06152     cpl_table     * lin_table    = NULL;
06153     cpl_imagelist * c_onlist     = NULL;
06154     cpl_imagelist * c_offlist    = NULL;
06155     cpl_vector    * diffdits     = NULL;
06156     cpl_imagelist * lin_inputs   = NULL;
06157     cpl_polynomial * poly_linfit = NULL;
06158     cpl_image     * fiterror     = NULL;
06159     cpl_vector    * vcoeffs      = NULL;
06160     double        * pcoeffs      = NULL;
06161     int             ndiffdits, ndits;
06162     int             i, j;
06163     cpl_boolean     opt_nir      = mode & IRPLIB_LIN_OPT ? OPT : NIR;
06164     const cpl_vector *x = NULL;
06165     const cpl_vector *y = NULL;
06166 
06167     const cpl_image * first = NULL;
06168     int sizex = 0;
06169     int sizey = 0;
06170 
06171     cpl_size deg;
06172     double vsize = 0;
06173 
06174 
06175     cpl_ensure(imlist_on  != NULL, CPL_ERROR_NULL_INPUT, NULL);
06176     cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
06177     cpl_ensure(exptimes   != NULL, CPL_ERROR_NULL_INPUT, NULL);
06178     cpl_ensure(qclist     != NULL, CPL_ERROR_NULL_INPUT, NULL);
06179     cpl_ensure(order      >  0   , CPL_ERROR_ILLEGAL_INPUT, NULL);
06180 
06181     vcoeffs      = cpl_vector_new(order + 1);
06182     pcoeffs      = cpl_vector_get_data(vcoeffs);
06183 
06184     /* This mode requires optional outputs */
06185     if (mode & IRPLIB_LIN_PIX2PIX) {
06186     lin_inputs = cpl_imagelist_new();
06187     cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
06188     cpl_ensure(bpm         != NULL, CPL_ERROR_NULL_INPUT, NULL);
06189     }
06190 
06191     /* Create table with columns */
06192     lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
06193     skip_if(detmon_lin_table_create(lin_table, opt_nir));
06194 
06195     /* Search for different EXPTIME values */
06196     /* Search for different EXPTIME values */
06197     diffdits  = detmon_lg_find_dits(exptimes, tolerance);
06198     ndiffdits = cpl_vector_get_size(diffdits);
06199 
06200     ndits     = cpl_vector_get_size(exptimes);
06201 
06202 
06203 
06204 
06205 
06206 
06207 /* TO BE IMPLEMENTED SIMILARLY TO UPPER LEVEL FUNCTION (search for nskip)
06208    if(filter > 0) {
06209     double med1 =
06210         cpl_image_get_median_window(cpl_imagelist_get(imlist_on, 0),
06211                     llx,lly,urx,ury);
06212     double med2 =
06213            cpl_image_get_median_window(cpl_imagelist_get(imlist_on, 1),
06214                     llx,lly,urx,ury);
06215     if ( med1 > (double)filter ||
06216          med2 > (double)filter) {
06217         follow = CPL_FALSE;
06218         cpl_table_select_row(lin_table, dit_nb);
06219             dit_nskip++;
06220         cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
06221                 "will not be taken into account for computation "
06222                 "as they are above --filter threshold", dit_nb);
06223     }
06224     }
06225 */
06226 
06227 
06228 
06229 
06230     if (mode & IRPLIB_LIN_COLLAPSE) {
06231     /*
06232      * The master bias is required only for
06233      * linearity computation in the OPT domain
06234      */
06235     cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
06236     skip_if(collapse == NULL);
06237 
06238     c_offlist = cpl_imagelist_new();
06239     skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
06240     }
06241 
06242     /* Loop over the different DITs found in EXPTIMEs */
06243     for (i = 0; i < ndiffdits; i++) {
06244         int c_nons;
06245         int c_noffs = 0; /* False (uninit) warning */
06246 
06247     double c_dit = cpl_vector_get(diffdits, i);
06248 
06249     c_onlist  = cpl_imagelist_new();
06250     c_nons = 0;
06251 
06252     if (mode & IRPLIB_LIN_NO_COLLAPSE) {
06253         c_offlist = cpl_imagelist_new();
06254         c_noffs = 0;
06255     }
06256 
06257     for(j = 0; j < ndits; j++) {
06258         if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
06259                 /*
06260                  * First we get the corresponding image from the ON imlist.
06261                  * The option IRPLIB_GAIN_WITH_RESCALE requires to modify
06262                  * the input pixel buffer; therefore we must duplicate it.
06263                  * On the other hand, if this option is not required, there
06264                  * is no need for that duplication. We must only care that
06265                  * c_onlist must not be deleted but only unset.
06266                  */
06267                 cpl_image * im_on;
06268                 if (mode & IRPLIB_LIN_WITH_RESCALE) {
06269                     const cpl_image * im =
06270                         cpl_imagelist_get_const(imlist_on, j);
06271                     im_on = cpl_image_duplicate(im);
06272                 } else {
06273                     im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
06274                 }
06275                 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
06276                 c_nons++;
06277 
06278                 /*
06279                  * Same explanation as above but for OFF imlist.
06280                  * Only necessary when IRPLIB_GAIN_NO_COLLAPSE required.
06281                  */
06282         if (mode & IRPLIB_LIN_NO_COLLAPSE) {
06283                     cpl_image * im_off;
06284                     if (mode & IRPLIB_LIN_WITH_RESCALE) {
06285                         const cpl_image * im =
06286                           cpl_imagelist_get_const(imlist_off, j);
06287                         im_off = cpl_image_duplicate(im);
06288                     } else {
06289                         im_off =
06290                           (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
06291                     }
06292             skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
06293             c_noffs++;
06294         }
06295         }
06296     }
06297 
06298     /* If NO_COLLAPSE, must be the same number of images! */
06299     if (mode & IRPLIB_LIN_NO_COLLAPSE)
06300         skip_if (c_nons != c_noffs);
06301 
06302     /* There must be pairs! */
06303     skip_if (c_nons == 0 || c_nons % 2 != 0);
06304 
06305     /* Rescaling */
06306     if(mode & IRPLIB_LIN_WITH_RESCALE) {
06307         skip_if(detmon_lg_rescale(c_onlist));
06308         if (mode & IRPLIB_LIN_NO_COLLAPSE)
06309         skip_if(detmon_lg_rescale(c_offlist));
06310     }
06311 
06312     /* The following loop is necessary for the case of multiple pairs
06313        of same EXPTIME values */
06314     while(c_nons > 0) {
06315 
06316         skip_if(detmon_lin_table_fill_row(lin_table, c_dit,
06317                              lin_inputs,
06318                              c_onlist, c_offlist,
06319                              llx, lly, urx, ury,
06320                              i, 0, mode));
06321 
06322             if (mode & IRPLIB_LIN_WITH_RESCALE) {
06323                 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
06324                 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
06325                 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
06326                   cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
06327                   cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
06328                 }
06329             } else {
06330             cpl_imagelist_unset(c_onlist, 0);
06331                 skip_if(0);
06332                 cpl_imagelist_unset(c_onlist, 0);
06333                 skip_if(0);
06334                 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
06335                   cpl_imagelist_unset(c_offlist, 0);
06336                   skip_if(0);
06337                   cpl_imagelist_unset(c_offlist, 0);
06338                   skip_if(0);
06339                 }
06340             }
06341             skip_if(0);
06342         c_nons -= 2;
06343     }
06344 
06345     cpl_imagelist_delete(c_onlist);
06346     if (mode & IRPLIB_LIN_NO_COLLAPSE) {
06347           cpl_imagelist_delete(c_offlist);
06348     }
06349     }
06350 
06351     skip_if(detmon_add_adl_column(lin_table, opt_nir));
06352 
06353     if(!(mode & IRPLIB_LIN_PIX2PIX)) {
06354     double mse = 0;
06355         /* Computation of LINEARITY via polynomial fit */
06356     y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
06357                 (double *)cpl_table_get_data_double_const(lin_table,
06358                                   "MED"));
06359         if (opt_nir == NIR) {
06360            x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
06361                              (double *)cpl_table_get_data_double_const(lin_table,                                                                                                 "DIT"));
06362         } else {
06363            x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
06364                              (double *)cpl_table_get_data_double_const(lin_table,                                                                                                 "EXPTIME"));
06365         }
06366         if(x == NULL || y == NULL) {
06367         cpl_vector_unwrap((cpl_vector *)x);
06368         cpl_vector_unwrap((cpl_vector *)y);
06369         /*
06370          * As x and y are const vectors, if they would be defined at the
06371          * beginning of the function (required for skip_if - end_skip
06372          * scheme), they couldn't be initialised to NULL (required too).
06373          * Therefore, they are considered apart from the scheme.
06374          */
06375         skip_if(1);
06376     }
06377 
06378         cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
06379         poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
06380 
06381     if(order == cpl_vector_get_size(x) - 1) {
06382         cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
06383         mse = 0;
06384     }
06385 
06386     if(poly_linfit == NULL) {
06387         cpl_vector_unwrap((cpl_vector *)x);
06388         cpl_vector_unwrap((cpl_vector *)y);
06389         /* See comment in previous error checking if() statement */
06390         skip_if(1);
06391     }
06392 
06393     cpl_vector_unwrap((cpl_vector *)x);
06394     cpl_vector_unwrap((cpl_vector *)y);
06395 
06396         for(deg = 0; deg <= order; deg++) {
06397             const double            coeff =
06398                 cpl_polynomial_get_coeff(poly_linfit, &deg);
06399             char                   *name_o =
06400                 cpl_sprintf("ESO QC LIN COEF%" CPL_SIZE_FORMAT "", deg);
06401             assert(name_o != NULL);
06402             skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
06403             skip_if(cpl_propertylist_set_comment(qclist,name_o,
06404                          DETMON_QC_LIN_COEF_C));
06405             cpl_free(name_o);
06406         pcoeffs[deg] = coeff;
06407         }
06408     skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
06409             skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
06410                          DETMON_QC_ERRFIT_MSE_C));
06411 
06412 
06413     } else {
06414        if (opt_nir == NIR) {
06415           x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
06416                 (double *)cpl_table_get_data_double_const(lin_table,
06417                                                                       "DIT"));
06418        } else {
06419           x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
06420                 (double *)cpl_table_get_data_double_const(lin_table,
06421                                                                       "EXPTIME"));
06422        }
06423 
06424 
06425        first = cpl_imagelist_get_const(lin_inputs, 0);
06426        sizex = cpl_image_get_size_x(first);
06427        sizey = cpl_image_get_size_y(first);
06428 
06429        vsize = cpl_vector_get_size(x);
06430 
06431     fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
06432 
06433         *coeffs_cube =
06434             cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
06435                                          order, FALSE, CPL_TYPE_FLOAT,
06436                      fiterror);
06437 
06438     cpl_vector_unwrap((cpl_vector*)x);
06439     irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
06440               "Failed polynomial fit");
06441 
06442         for(i = 0; i <= order; i++) {
06443             cpl_image              *image = cpl_imagelist_get(*coeffs_cube, i);
06444         const double coeff = cpl_image_get_median(image);
06445             char * name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
06446             char * name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
06447         pcoeffs[i] = coeff;
06448             assert(name_o1 != NULL);
06449             assert(name_o2 != NULL);
06450             skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
06451             skip_if(cpl_propertylist_set_comment(qclist,name_o1,
06452                          DETMON_QC_LIN_COEF_C));
06453             cpl_free(name_o1);
06454         name_o1= NULL;
06455             skip_if(cpl_propertylist_append_double(qclist, name_o2,
06456                        cpl_image_get_stdev(image)));
06457             skip_if(cpl_propertylist_set_comment(qclist,name_o2,
06458                          DETMON_QC_LIN_COEF_ERR_C));
06459             cpl_free(name_o2);
06460         name_o2= NULL;
06461         }
06462 
06463     if(order == vsize - 1) {
06464         cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
06465         skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
06466                            0.0));
06467             skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
06468                          DETMON_QC_ERRFIT_C));
06469 
06470 
06471     } else {
06472         skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
06473                            cpl_image_get_median(fiterror)));
06474             skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
06475                          DETMON_QC_ERRFIT_C));
06476 
06477     }
06478     }
06479 
06480     skip_if(detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
06481 
06482     if(mode & IRPLIB_LIN_PIX2PIX) {
06483     int nbpixs;
06484         *bpm = detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
06485     skip_if(*bpm == NULL);
06486     skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
06487                         nbpixs));
06488     skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
06489                          DETMON_QC_NUM_BPM_C));
06490     }
06491 
06492     end_skip;
06493 
06494     cpl_vector_delete(diffdits);
06495     cpl_polynomial_delete(poly_linfit);
06496     cpl_imagelist_delete(lin_inputs);
06497     cpl_vector_delete(vcoeffs);
06498     cpl_image_delete(fiterror);
06499 
06500     return lin_table;
06501 
06502 }
06503 
06504 /*--------------------------------------------------------------------------*/
06528 /*--------------------------------------------------------------------------*/
06529 static cpl_error_code
06530 detmon_lin_table_fill_row(cpl_table * lin_table, double c_dit,
06531                  cpl_imagelist * linearity_inputs,
06532                  const cpl_imagelist * ons,
06533                  const cpl_imagelist * offs,
06534                  int llx,
06535                  int lly,
06536                  int urx,
06537                  int ury,
06538                  const int pos,
06539                                  const int nskip,
06540                  unsigned mode)
06541 {
06542     cpl_image              * dif1=NULL;
06543     cpl_image              * dif2=NULL;
06544     cpl_image              * dif_avg=NULL;
06545 
06546     double                   med_dit=0;
06547     double                   mean_dit=0;
06548     cpl_error_code           error;
06549     cpl_image * extracted=NULL;
06550     int offsize=0;
06551 
06552     cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
06553     cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
06554     cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
06555 
06556     if (mode & IRPLIB_LIN_PIX2PIX) {
06557        cpl_msg_debug(cpl_func,"checking linearity inputs");
06558     cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
06559     }
06560 
06561 
06562     if (mode & IRPLIB_LIN_NIR) {
06563     cpl_table_set(lin_table, "DIT", pos, c_dit);
06564     } else if (mode & IRPLIB_LIN_OPT) { /*OPT */
06565         cpl_table_set(lin_table, "EXPTIME", pos, c_dit);
06566     } else {
06567     cpl_msg_error(cpl_func, "Mandatory mode not given");
06568     }
06569 
06570     offsize = cpl_imagelist_get_size(offs);
06571 
06572     /* Algorithm defined: substract ON - OFF and average 2 differences */
06573     dif1 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
06574                                      cpl_imagelist_get_const(offs, 0));
06575 
06576     if (mode & IRPLIB_LIN_NO_COLLAPSE && offsize > 1)
06577         dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
06578                                          cpl_imagelist_get_const(offs, 1));
06579     else
06580         dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
06581                                          cpl_imagelist_get_const(offs, 0));
06582 
06583     dif_avg = cpl_image_average_create(dif1, dif2);
06584 
06585     cpl_image_abs(dif_avg);
06586     extracted = cpl_image_extract(dif_avg, llx, lly, urx, ury);
06587 
06588     cpl_ensure_code(extracted != NULL, cpl_error_get_code());
06589 
06590     cpl_table_set(lin_table, "MED", pos, cpl_image_get_median(extracted));
06591     cpl_table_set(lin_table, "MEAN", pos, cpl_image_get_mean(extracted));
06592     med_dit = cpl_image_get_median(extracted) / c_dit;
06593     mean_dit = cpl_image_get_mean(extracted)  / c_dit;
06594 
06595     cpl_table_set(lin_table, "MED_DIT", pos, med_dit);
06596     cpl_table_set(lin_table, "MEAN_DIT", pos, mean_dit);
06597 
06598     cpl_image_delete(dif1);
06599     cpl_image_delete(dif2);
06600 
06601     /* Insert to the imagelist used to fit the polynomial */
06602     if(mode & IRPLIB_LIN_PIX2PIX) {
06603         error = cpl_imagelist_set(linearity_inputs, extracted, pos-nskip);
06604         cpl_ensure_code(!error, error);
06605     } else {
06606         cpl_image_delete(extracted);
06607     }
06608 
06609 
06610     cpl_image_delete(dif_avg);
06611 
06612     return cpl_error_get_code();
06613 }
06614 
06615 static double irplib_calculate_total_noise_smooth(const cpl_image* pimage, int pattern_x, int pattern_y)
06616 {
06617     cpl_image * p_tmp_image = 0;
06618     cpl_image * psmooth_image = 0;
06619     double ret_noise = -1;
06620     cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
06621     cpl_mask_not(mask);
06622     p_tmp_image = cpl_image_duplicate(pimage);
06623     cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
06624     cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
06625     psmooth_image  = cpl_image_divide_create(pimage,p_tmp_image);
06626     ret_noise = irplib_calculate_total_noise(psmooth_image);
06627     cpl_mask_delete(mask);
06628     cpl_image_delete(psmooth_image);
06629     cpl_image_delete(p_tmp_image);
06630     return ret_noise;
06631 }
06632 static double irplib_calculate_total_noise(const cpl_image* pimage)
06633 {
06634     double total_noise = -1;
06635     unsigned long max_bin_size = 1E5;
06636     const double  hstart = cpl_image_get_min(pimage);
06637     const double  hrange = cpl_image_get_max(pimage) - hstart;
06638     const unsigned long nbins  = max_bin_size;
06639     cpl_error_code err = CPL_ERROR_NONE;
06640     /* apply histogram method */
06641     irplib_hist * phist = 0;
06642     phist = irplib_hist_new();
06643     /* 2 extra-bins for possible out-of-range values */
06644 
06645     irplib_hist_init(phist, nbins, hstart, hrange);
06646     err = irplib_hist_fill(phist, pimage);
06647     if (err == CPL_ERROR_NONE)
06648     {
06649         unsigned int i = 0;
06650         double x0 = 0;
06651         double area = 0;
06652         double offset = 0;
06653 
06654         /* prepare vector */
06655         unsigned long n_bins = irplib_hist_get_nbins(phist);
06656         double start = irplib_hist_get_start(phist);
06657         double bin_size = irplib_hist_get_bin_size(phist);
06658         cpl_vector* pdata_vector = cpl_vector_new(n_bins);
06659         cpl_vector* ppos_vector = cpl_vector_new(n_bins);
06660         cpl_table* ptable = cpl_table_new(n_bins);
06661         cpl_table_new_column(ptable, "bin", CPL_TYPE_DOUBLE);
06662         cpl_table_new_column(ptable, "value", CPL_TYPE_DOUBLE);
06663         for(i = 0; i < n_bins; i++)
06664         {
06665             unsigned int value = irplib_hist_get_value(phist, i);
06666             double dvalue = (double)(value);
06667             cpl_vector_set(pdata_vector, i, dvalue);
06668             cpl_vector_set(ppos_vector, i, start + i * bin_size);
06669 
06670             cpl_table_set(ptable, "bin", i, start + i * bin_size);
06671             cpl_table_set(ptable, "value", i, dvalue);
06672         }
06673         err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
06674         if (err == CPL_ERROR_NONE)
06675         {
06676             cpl_msg_info(cpl_func, "FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
06677         }
06678         else
06679         {
06680             cpl_msg_warning(cpl_func, "FPN could not be computed due failed Gaussian Fit,  err msg [%s]", cpl_error_get_message());
06681             cpl_error_reset();
06682         }
06683         cpl_table_delete(ptable);
06684         cpl_vector_delete(ppos_vector);
06685         cpl_vector_delete(pdata_vector);
06686     }
06687     else
06688     {
06689         cpl_msg_warning(cpl_func, "FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
06690         cpl_error_reset();
06691     }
06692     irplib_hist_delete(phist);
06693 
06694     return total_noise;
06695 }
06696 
06697 static double irplib_compute_err(double gain, double ron, double FA)
06698 {
06699     double int_gain = (gain * gain - 1) / 12;
06700     if (int_gain < 0)
06701     {
06702         int_gain = 0;
06703     }
06704     return sqrt(ron * ron + FA / gain + int_gain);
06705 }
06706 static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain ,
06707         FPN_METHOD fpn_method, int smooth_size, double* mse)
06708 {
06709     cpl_image* im_diff = 0;
06710     const cpl_image* im_f1 = f1;
06711     cpl_image* im_inrange1 = 0;
06712     double FA = 0;
06713     double s_tot = 0; /* absolute total noise */
06714     double s_fpn = 0; /* fixed pattern noise */
06715     double sr_fpn = 0; /* relative structural noise */
06716     /*che cinput*/
06717     if (gain<=0) {
06718      /* put dummy values Negative to indicate a problem occurred
06719        (FPN should be always positive) */
06720        cpl_msg_warning(cpl_func,"gain[%f]<0", gain);
06721        cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06722        s_fpn=-999.;
06723        sr_fpn=-999;
06724        return sr_fpn;
06725     }
06726     if (range)
06727     {
06728         im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
06729         im_f1 = im_inrange1;
06730     }
06731     FA = cpl_image_get_median(im_f1);
06732 
06733     /* apply histogram method */
06734         /* Is this irplib function giving the right result?? */
06735     switch (fpn_method)
06736     {
06737     case FPN_SMOOTH:
06738         cpl_msg_info(cpl_func,"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
06739         s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
06740         break;
06741     case FPN_HISTOGRAM:
06742         cpl_msg_info(cpl_func,"HISTOGRAM method is used for FPN");
06743         s_tot = irplib_calculate_total_noise(im_f1);
06744         break;
06745     default:
06746         s_tot = -1;
06747         sr_fpn = -1;
06748         cpl_msg_warning(cpl_func,"fpn_method is not defined");
06749         break;
06750     }
06751     if (s_tot > 0)
06752     {
06753         if (FA<0)
06754         {
06755           /* put dummy values Negative to indicate a problem occurred
06756            (FPN should be always positive) */
06757            cpl_msg_warning(cpl_func,"Median flux on sum of flats<0");
06758            cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06759            s_fpn=-999.;
06760            sr_fpn=-999;
06761         }
06762 
06763         if ((s_tot * s_tot - FA / gain) > 0)
06764         {
06765            s_fpn = sqrt(s_tot * s_tot - FA / gain);
06766            sr_fpn = s_fpn / FA;
06767            *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
06768         } else {
06769           /* put dummy values Negative to indicate a problem occurred
06770            (FPN should be always positive) */
06771            cpl_msg_warning(cpl_func,"s_tot * s_tot < FA / gain");
06772            cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06773            s_fpn=-999.;
06774            sr_fpn=-999;
06775            *mse = -1;
06776         }
06777 /*
06778         cpl_msg_debug(cpl_func, "FPN Calculation: FA[%f] s_tot[%f] photon_noise[%f] s_fpn[%f] sr_fpn[%f] mse[%f]", FA, s_tot, photon_noise, s_fpn, sr_fpn, *mse);
06779 */
06780     }
06781     cpl_image_delete(im_diff);
06782     if (range)
06783     {
06784         cpl_image_delete(im_inrange1);
06785     }
06786     return sr_fpn;
06787 }
06788 
06789 static cpl_imagelist * irplib_load_fset_wrp(const cpl_frameset * pframeset, cpl_type type , int whichext)
06790 {
06791     cpl_imagelist * ret = 0;
06792     ret =  cpl_imagelist_load_frameset(pframeset, type,
06793             1, whichext);
06794     if (ret)
06795     {
06796         /* check the images for size*/
06797         int sz = cpl_imagelist_get_size(ret);
06798         int i = 0;
06799         for(i = 0; i < sz; i ++)
06800         {
06801             cpl_image* pimage = 0;
06802             pimage = cpl_imagelist_get(ret, i);
06803             if (pimage)
06804             {
06805                 int size_x = 0;
06806                 int size_y = 0;
06807                 size_x = cpl_image_get_size_x(pimage);
06808                 size_y = cpl_image_get_size_y(pimage);
06809                 if (detmon_lg_config.nx != size_x || detmon_lg_config.ny != size_y)
06810                 {
06811                     cpl_msg_error(cpl_func, "All images in the input should have the same size,\n" \
06812                             " image #%d has size x[%d] y[%d], expected size  x[%d] y[%d]", i, size_x, size_y,
06813                             detmon_lg_config.nx, detmon_lg_config.ny);
06814                     cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
06815                     cpl_imagelist_delete(ret);
06816                     ret = 0;
06817                 }
06818             }
06819         }
06820     }
06821     return ret;
06822 }
06823 
06824 static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset * pframeset, cpl_type type , int whichext)
06825 {
06826    int i = whichext; /* fake code to avoid compiler warning */
06827     cpl_imagelist* offs = cpl_imagelist_new();
06828     detmon_lg_config.load_fset(pframeset, type, offs);
06829     i++;
06830     return offs;
06831 }
06832 
06833 static cpl_error_code irplib_table_create_column(cpl_table* ptable, cpl_propertylist* plist)
06834 {
06835     if (ptable && plist)
06836     {
06837         int size = cpl_propertylist_get_size(plist);
06838         int i = 0;
06839         for (i = 0; i < size; i++)
06840         {
06841             cpl_property* pprop = cpl_propertylist_get(plist,i);
06842             if (pprop)
06843             {
06844                 const char* pname = cpl_property_get_name(pprop);
06845                 if (pname)
06846                 {
06847                     cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
06848                     if (cpl_error_get_code() != CPL_ERROR_NONE)
06849                     {
06850                         cpl_msg_warning(cpl_func, "cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
06851                         break; /* leave the cycle */
06852                     }
06853                 }
06854             }
06855         }
06856     }
06857     return cpl_error_get_code();
06858 }
06859 
06860 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable, cpl_propertylist* plist, int row)
06861 {
06862     cpl_error_code err = CPL_ERROR_NONE;
06863     if (ptable && plist)
06864     {
06865         int size = cpl_propertylist_get_size(plist);
06866         int i = 0;
06867         for (i = 0; i < size; i++)
06868         {
06869             cpl_property* pprop = cpl_propertylist_get(plist,i);
06870             if (pprop)
06871             {
06872                 const char* pname = cpl_property_get_name(pprop);
06873                 double  value = cpl_property_get_double(pprop);
06874                 if (pname)
06875                 {
06876                     cpl_table_set_double(ptable, pname, row, value);
06877                     if (cpl_error_get_code() != CPL_ERROR_NONE)
06878                     {
06879                         cpl_msg_warning(cpl_func, "cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
06880                         cpl_error_reset();
06881                         break; /* leave the cycle */
06882                     }
06883                 }
06884             }
06885         }
06886     }
06887     return err;
06888 }
06889 cpl_error_code detmon_check_order(const double *exptime, int sz, double tolerance, int order)
06890 {
06891     int nsets = 0;
06892     int i = 0;
06893     /* 1. Determine number of groups */
06894 /*   cpl_msg_warning(cpl_func, "detmon_check_order sz[%i]", sz);*/
06895     do
06896     {
06897 /*      cpl_msg_warning(cpl_func, "detmon_check_order i[%i] exptime[%g]", i, exptime[i]);   */
06898         nsets++;
06899         do
06900         {
06901             i++;
06902             if(i == sz - 1)
06903             {
06904                 break;
06905             }
06906         } while(fabs(exptime[i-1] - exptime[i]) < tolerance);
06907     } while(i < sz - 1);
06908     /* the very last adjustment for the last group */
06909     if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
06910     if(nsets <= order)
06911     {
06912              cpl_error_set_message(cpl_func,CPL_ERROR_INCOMPATIBLE_INPUT,
06913                                    "Not enough frames for the polynomial"
06914                                    " fitting. nsets = %d <= %d order",
06915                                    nsets,order);
06916     }
06917     return cpl_error_get_code();
06918 }
06919 
06920 static cpl_error_code detmon_lg_dfs_save_imagelist(
06921         cpl_frameset * frameset,
06922         const cpl_parameterlist * parlist,
06923         const cpl_frameset *usedframes,
06924         const cpl_imagelist *coeffs,
06925         const char *recipe_name,
06926         const cpl_propertylist *mypro_coeffscube,
06927         const char * package,
06928         const char * name_o)
06929 {
06930        return(cpl_dfs_save_imagelist
06931            (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
06932         recipe_name, mypro_coeffscube, NULL, package,
06933         name_o));
06934 }
06935 static void detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos)
06936 {
06937     const cpl_image* first = cpl_imagelist_get(imlist, 0);
06938     if (first)
06939     {
06940           int x = cpl_image_get_size_x(first);
06941           int y = cpl_image_get_size_y(first);
06942           cpl_type type = cpl_image_get_type(first);
06943           cpl_image * blank = cpl_image_new(x, y, type);
06944           cpl_imagelist_set(imlist, blank, pos);
06945     }
06946 }
06947 
06948 
06949 
06950 cpl_error_code
06951 detmon_lg_set_tag(cpl_frameset* set, const char** tag_on, const char** tag_off)
06952 {
06953   int ntag_old=0;
06954   int ntag_new=0;
06955 
06956   ntag_old=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_OLD);
06957   ntag_new=cpl_frameset_count_tags(set,DETMON_LG_ON_RAW_NEW);
06958   if(ntag_old) {
06959     *tag_on=DETMON_LG_ON_RAW_OLD;
06960     *tag_off=DETMON_LG_OFF_RAW_OLD;
06961   } else if (ntag_new) {
06962     *tag_on=DETMON_LG_ON_RAW_NEW;
06963     *tag_off=DETMON_LG_OFF_RAW_NEW;
06964   } else {
06965     cpl_msg_error(cpl_func,"Provide %s and %s (or %s and %s) input frames",
06966           DETMON_LG_ON_RAW_NEW,DETMON_LG_OFF_RAW_NEW,
06967           DETMON_LG_ON_RAW_OLD,DETMON_LG_OFF_RAW_OLD);
06968   }
06969 
06970 
06971   return cpl_error_get_code();
06972 }

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