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