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