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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 #ifdef HAVE_CONFIG_H
00144 #include <config.h>
00145 #endif
00146
00147
00148
00149
00150
00151 #include <complex.h>
00152
00153
00154 #include <math.h>
00155 #include <string.h>
00156 #include <assert.h>
00157
00158 #include <cpl.h>
00159 #include <cpl_fft.h>
00160 #include "irplib_detmon.h"
00161 #include "irplib_detmon_lg.h"
00162 #include "irplib_detmon_lg_impl.h"
00163
00164 #include "irplib_utils.h"
00165 #include "irplib_hist.h"
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 enum _FPN_METHOD
00179 {
00180 FPN_UNKNOWN,
00181 FPN_HISTOGRAM,
00182 FPN_SMOOTH,
00183 };
00184 typedef enum _FPN_METHOD FPN_METHOD;
00185 static struct
00186 {
00187 const char * method;
00188
00189 int order;
00190 double kappa;
00191 int niter;
00192 int threshold_min;
00193 int threshold_max;
00194 int llx;
00195 int lly;
00196 int urx;
00197 int ury;
00198 int ref_level;
00199 int threshold;
00200 int m;
00201 int n;
00202 int llx1;
00203 int lly1;
00204 int urx1;
00205 int ury1;
00206 int llx2;
00207 int lly2;
00208 int urx2;
00209 int ury2;
00210 int llx3;
00211 int lly3;
00212 int urx3;
00213 int ury3;
00214 int llx4;
00215 int lly4;
00216 int urx4;
00217 int ury4;
00218 int llx5;
00219 int lly5;
00220 int urx5;
00221 int ury5;
00222 int nx;
00223 int ny;
00224 cpl_boolean wholechip;
00225 cpl_boolean autocorr;
00226 cpl_boolean intermediate;
00227 cpl_boolean collapse;
00228 cpl_boolean rescale;
00229 cpl_boolean pix2pix;
00230 cpl_boolean bpmbin;
00231 int filter;
00232 double tolerance;
00233 const char * pafname;
00234
00235 double cr;
00236 int exts;
00237 int nb_extensions;
00238 double lamp_stability;
00239 cpl_boolean lamp_ok;
00240
00241 int (* load_fset) (
00242 const cpl_frameset *, cpl_type, cpl_imagelist *
00243 );
00244 cpl_imagelist * (* load_fset_wrp) (
00245 const cpl_frameset *, cpl_type, int
00246 );
00247 FPN_METHOD fpn_method;
00248 int fpn_smooth;
00249 double saturation_limit;
00250 } detmon_lg_config;
00251
00252
00253
00254
00255
00256
00257
00258
00259 static cpl_error_code
00260 irplib_detmon_lg_retrieve_parlist(const char *,
00261 const char *, const cpl_parameterlist *,
00262 cpl_boolean);
00263
00264
00265 static cpl_error_code
00266 irplib_detmon_lg_split_onoff(const cpl_frameset *,
00267 cpl_frameset *,
00268 cpl_frameset *,
00269 const char *, const char * );
00270
00271 static cpl_error_code
00272 irplib_detmon_lg_reduce(const cpl_frameset *,
00273 const cpl_frameset *,
00274
00275
00276 int* index_on, int* index_off, double* exptime_on, double* exptime_off,
00277 int *next_index_on, int* next_index_off,
00278 cpl_imagelist **,
00279 cpl_table *,
00280 cpl_table *,
00281 cpl_image **,
00282 cpl_imagelist *,
00283 cpl_imagelist *,
00284 cpl_propertylist *,
00285 cpl_propertylist *,
00286 cpl_propertylist *,
00287 cpl_propertylist *,
00288 int (* load_fset) (const cpl_frameset *,
00289 cpl_type,
00290 cpl_imagelist *),
00291 const cpl_boolean, int);
00292
00293 static cpl_error_code
00294 irplib_detmon_lin_table_fill_row(cpl_table *, double,
00295 cpl_imagelist *,
00296 const cpl_imagelist *,
00297 const cpl_imagelist *,
00298 int, int, int, int,
00299 const int,
00300 const int,
00301 unsigned);
00302
00303 static cpl_error_code
00304 irplib_detmon_gain_table_fill_row(cpl_table * gain_table,
00305 double c_dit,int c_ndit,
00306 cpl_imagelist * autocorr_images,
00307 cpl_imagelist * diff_flats,
00308 const cpl_imagelist * ons,
00309 const cpl_imagelist * offs,
00310 double kappa, int nclip,
00311 int llx, int lly, int urx, int ury,
00312 int m, int n,
00313 double saturation_limit,
00314 const int pos, unsigned mode, int* rows_affected);
00315
00316 static cpl_error_code
00317 irplib_detmon_lg_save(const cpl_parameterlist *,
00318 cpl_frameset *,
00319 const char *,
00320 const char *,
00321 const char *,
00322 const cpl_propertylist *,
00323 const cpl_propertylist *,
00324 const cpl_propertylist *,
00325 const cpl_propertylist *,
00326 const cpl_propertylist *,
00327 const cpl_propertylist *,
00328 const char *,
00329 cpl_imagelist *,
00330 cpl_table *,
00331 cpl_table *,
00332 cpl_image *,
00333 cpl_imagelist *,
00334 cpl_imagelist *,
00335 cpl_propertylist *,
00336 cpl_propertylist *,
00337 cpl_propertylist *,
00338 cpl_propertylist *,
00339 const int, const int, const cpl_frameset *,
00340 int);
00341
00342 static cpl_error_code
00343 irplib_detmon_lg_qc_ptc(const cpl_table *,
00344 cpl_propertylist *, unsigned, int);
00345
00346 static cpl_error_code
00347 irplib_detmon_lg_qc_med(const cpl_table *,
00348 cpl_propertylist *, int);
00349
00350
00351 static double
00352 irplib_pfits_get_dit(const cpl_propertylist *);
00353
00354 static double
00355 irplib_pfits_get_dit_opt(const cpl_propertylist *);
00356 static double
00357 irplib_pfits_get_prop_double(const cpl_propertylist * plist, const char* prop_name);
00358
00359 static cpl_image *irplib_detmon_bpixs(const cpl_imagelist *, cpl_boolean, const double, int *);
00360
00361 static double
00362 irplib_detmon_autocorr_factor(const cpl_image *,
00363 cpl_image **, int, int);
00364
00365
00366
00367 static cpl_error_code
00368 irplib_detmon_opt_contamination(const cpl_imagelist *,
00369 const cpl_imagelist *,
00370 unsigned mode, cpl_propertylist *);
00371
00372 #if 0
00373 irplib_detmon_opt_lampcr(cpl_frameset *, int);
00374 #endif
00375
00376 int
00377 irplib_detmon_lg_dfs_set_groups(cpl_frameset *, const char *, const char *);
00378
00379 static cpl_error_code
00380 irplib_detmon_lg_reduce_all(const cpl_table *,
00381 cpl_propertylist *,
00382 cpl_propertylist *
00383 , cpl_propertylist *,
00384 cpl_propertylist *,
00385 cpl_imagelist **,
00386 cpl_image **,
00387 const cpl_imagelist *,
00388 const cpl_table *, int, cpl_boolean);
00389
00390 static cpl_error_code
00391 irplib_detmon_lg_check_defaults(const cpl_image *);
00392
00393 static cpl_error_code
00394 irplib_detmon_lg_rescale(cpl_imagelist *);
00395
00396 static cpl_error_code
00397 irplib_detmon_lg_reduce_init(cpl_table *,
00398 cpl_table *,
00399 cpl_imagelist **,
00400 const cpl_boolean);
00401
00402
00403
00404 static cpl_error_code
00405 irplib_detmon_add_adl_column(cpl_table *, cpl_boolean);
00406
00407 static cpl_error_code
00408 irplib_detmon_lg_lamp_stab(const cpl_frameset *,
00409 const cpl_frameset *,
00410 cpl_boolean, int);
00411
00412
00413 static cpl_error_code
00414 irplib_detmon_lg_reduce_dit(const cpl_frameset * set_on,
00415 int* index_on, double* exptime_on,
00416 const int dit_nb,
00417 int * dit_nskip,
00418 const cpl_frameset * set_off,
00419 int * index_off, double* exptime_off,
00420 int* next_on, int* next_off,
00421 cpl_table * linear_table,
00422 cpl_table * gain_table,
00423 cpl_imagelist * linearity_inputs,
00424 cpl_propertylist * qclist,
00425 cpl_boolean opt_nir,
00426 cpl_imagelist * autocorr_images,
00427 cpl_imagelist * diff_flats,
00428 cpl_imagelist * opt_offs,
00429 int whichext,
00430 int * rows_affected);
00431
00432 static cpl_error_code
00433 irplib_detmon_lg_core(cpl_frameset * cur_fset_on,
00434 cpl_frameset * cur_fset_off,
00435 int * index_on,
00436 int * index_off,
00437 double * exptime_on,
00438 double * exptime_off,
00439 int whichext,
00440 int whichset,
00441 const char * recipe_name,
00442 const char * pipeline_name,
00443 const char * pafregexp,
00444 const cpl_propertylist * pro_lintbl,
00445 const cpl_propertylist * pro_gaintbl,
00446 const cpl_propertylist * pro_coeffscube,
00447 const cpl_propertylist * pro_bpm,
00448 const cpl_propertylist * pro_corr,
00449 const cpl_propertylist * pro_diff,
00450 const char * package,
00451 int (* load_fset) (const cpl_frameset *,
00452 cpl_type,
00453 cpl_imagelist *),
00454 int nsets, cpl_boolean opt_nir,
00455 cpl_frameset * frameset, const cpl_parameterlist * parlist,
00456 cpl_frameset * cur_fset);
00457
00458 static cpl_error_code
00459 irplib_detmon_lg_lineff(double *, cpl_propertylist *, int, int);
00460
00461
00462
00463
00464
00465
00466 static cpl_error_code
00467 irplib_detmon_gain_table_create(cpl_table *,
00468 const cpl_boolean);
00469
00470
00471 static cpl_error_code
00472 irplib_detmon_lin_table_create(cpl_table *,
00473 const cpl_boolean);
00474
00475 static cpl_vector *
00476 irplib_detmon_lg_find_dits(const cpl_vector *,
00477 double );
00478
00479 static cpl_error_code
00480 irplib_detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
00481 const cpl_vector * vec_ndits,
00482 double tolerance,
00483 cpl_vector** diff_dits,
00484 cpl_vector** diff_ndits);
00485
00486 static cpl_error_code
00487 irplib_detmon_fpn_compute(const cpl_frameset *set_on,
00488 int * index_on,
00489 int last_best,
00490 cpl_propertylist *lint_qclist,
00491 int llx,
00492 int lly,
00493 int urx,
00494 int ury,
00495 double gain,
00496 int whichext,
00497 FPN_METHOD fpn_method,
00498 int smooth_size);
00499 static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain,
00500 FPN_METHOD fpn_method, int, double* mse);
00501 static double irplib_calculate_total_noise(const cpl_image* pimage);
00502
00503 static cpl_imagelist* irplib_load_fset_wrp(const cpl_frameset *, cpl_type, int whichext);
00504 static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset *, cpl_type, int);
00505
00506 static cpl_error_code irplib_table_create_column(cpl_table* ptable, cpl_propertylist* plist);
00507 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable, cpl_propertylist* plist, int row);
00508
00509 static cpl_error_code
00510 irplib_detmon_pair_extract_next(const cpl_frameset * set,
00511 int* index,
00512 int* next_element,
00513 double* dit_array,
00514
00515
00516 cpl_frameset ** pair,
00517 double tolerance);
00518 static cpl_error_code
00519 irplib_detmon_single_extract_next(const cpl_frameset * set,
00520 int* index,
00521 int* next_element,
00522 double* dit_array,
00523 cpl_frameset ** pair);
00524
00525
00526
00527
00528
00529
00530 static cpl_error_code irplib_detmon_table_fill_invalid(cpl_table* ptable, double code);
00531 static void irplib_detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos);
00532
00539
00540 static int irplib_pfits_get_ndit(const cpl_propertylist * plist)
00541 {
00542 return cpl_propertylist_get_int(plist,"ESO DET NDIT");
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 static cpl_error_code irplib_detmon_lg_reduce_set(int i, cpl_frameset * frameset, int nsets,
00586 const char * tag_on,
00587 const char * tag_off,
00588 const char * recipe_name,
00589 const char * pipeline_name,
00590 const char * pafregexp,
00591 const cpl_propertylist * pro_lintbl,
00592 const cpl_propertylist * pro_gaintbl,
00593 const cpl_propertylist * pro_coeffscube,
00594 const cpl_propertylist * pro_bpm,
00595 const cpl_propertylist * pro_corr,
00596 const cpl_propertylist * pro_diff,
00597 const char * package,
00598 int (* load_fset)
00599 (const cpl_frameset *, cpl_type, cpl_imagelist *),
00600 const cpl_boolean opt_nir,
00601 const cpl_parameterlist * parlist,
00602 int* selection
00603 );
00604 static double irplib_compute_err(double gain, double ron, double photon_noise);
00605
00606 static cpl_error_code irplib_detmon_lg_dfs_save_imagelist(
00607 cpl_frameset * frameset,
00608 const cpl_parameterlist * parlist,
00609 const cpl_frameset *usedframes,
00610 const cpl_imagelist *coeffs,
00611 const char *recipe_name,
00612 const cpl_propertylist *mypro_coeffscube,
00613 const char * package,
00614 const char * name_o);
00615
00616
00617 static cpl_error_code irplib_detmon_lg_reduce_set(int i, cpl_frameset * frameset, int nsets,
00618 const char * tag_on,
00619 const char * tag_off,
00620 const char * recipe_name,
00621 const char * pipeline_name,
00622 const char * pafregexp,
00623 const cpl_propertylist * pro_lintbl,
00624 const cpl_propertylist * pro_gaintbl,
00625 const cpl_propertylist * pro_coeffscube,
00626 const cpl_propertylist * pro_bpm,
00627 const cpl_propertylist * pro_corr,
00628 const cpl_propertylist * pro_diff,
00629 const char * package,
00630 int (* load_fset)
00631 (const cpl_frameset *, cpl_type, cpl_imagelist *),
00632 const cpl_boolean opt_nir,
00633 const cpl_parameterlist * parlist,
00634 int* selection
00635 )
00636 {
00637 int j;
00638 int nexts = detmon_lg_config.nb_extensions;
00639
00640 double* exptime_on = 0;
00641 double* exptime_off = 0;
00642 int* index_on = 0;
00643 int* index_off = 0;
00644 cpl_frameset * cur_fset = NULL;
00645 cpl_frameset* cur_fset_on = 0;
00646 cpl_frameset* cur_fset_off = 0;
00647
00648
00649
00650
00651 cur_fset =
00652 (nsets == 1) ?
00653 cpl_frameset_duplicate(frameset) : cpl_frameset_extract(frameset, selection, i);
00654
00655
00656 skip_if(cur_fset == NULL);
00657
00658
00659 cur_fset_on = cpl_frameset_new();
00660 cur_fset_off = cpl_frameset_new();
00661 cpl_msg_info(cpl_func, "Splitting into ON and OFF sub-framesets");
00662 skip_if (irplib_detmon_lg_split_onoff(cur_fset,
00663 cur_fset_on, cur_fset_off,
00664 tag_on, tag_off ));
00665 if (cpl_frameset_get_size(cur_fset_on) == 0)
00666 {
00667 cpl_msg_error(cpl_func, "No lamp frames in input");
00668 skip_if(1);
00669 }
00670
00671 if (cpl_frameset_get_size(cur_fset_off) == 0)
00672 {
00673 cpl_msg_error(cpl_func, "No dark / bias frames in input");
00674 skip_if(1);
00675 }
00676 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));
00677
00678
00679
00680
00681
00682
00683
00684 exptime_on = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_on));
00685 exptime_off = cpl_malloc(sizeof(double)*cpl_frameset_get_size(cur_fset_off));
00686
00687 index_on = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_on));
00688 index_off = cpl_malloc(sizeof(int)*cpl_frameset_get_size(cur_fset_off));
00689 irplib_frameset_sort(cur_fset_on, index_on, exptime_on);
00690 irplib_frameset_sort(cur_fset_off, index_off, exptime_off);
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 skip_if(irplib_detmon_check_order(exptime_on, cpl_frameset_get_size(cur_fset_on), detmon_lg_config.tolerance, detmon_lg_config.order));
00704
00705 if(detmon_lg_config.exts >= 0)
00706 {
00707
00708
00709
00710
00711
00712 #if 0
00713 if (detmon_lg_config.lamp_ok) {
00714 skip_if(irplib_detmon_opt_lampcr(cur_fset, 0));
00715 }
00716 #endif
00717 skip_if(irplib_detmon_lg_core(cur_fset_on, cur_fset_off,
00718 index_on,
00719 index_off,
00720 exptime_on,
00721 exptime_off,
00722 detmon_lg_config.exts,
00723 i,
00724 recipe_name, pipeline_name, pafregexp,
00725 pro_lintbl, pro_gaintbl, pro_coeffscube, pro_bpm, pro_corr, pro_diff,
00726 package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
00727 } else {
00728 for(j = 1; j <= nexts; j++) {
00729
00730
00731
00732
00733
00734 #if 0
00735 if (detmon_lg_config.lamp_ok) {
00736 skip_if(irplib_detmon_opt_lampcr(cur_fset, j));
00737 }
00738 #endif
00739
00740 skip_if(irplib_detmon_lg_core(cur_fset_on, cur_fset_off,
00741 index_on,
00742 index_off,
00743 exptime_on,
00744 exptime_off,
00745 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));
00746 }
00747 }
00748 end_skip;
00749
00750 cpl_frameset_delete(cur_fset);
00751 cpl_frameset_delete(cur_fset_on);
00752 cpl_frameset_delete(cur_fset_off);
00753 cpl_free(index_on);
00754 cpl_free(index_off);
00755 cpl_free(exptime_on);
00756 cpl_free(exptime_off);
00757 return cpl_error_get_code();
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833 cpl_error_code
00834 irplib_detmon_lg(cpl_frameset * frameset,
00835 const cpl_parameterlist * parlist,
00836 const char * tag_on,
00837 const char * tag_off,
00838 const char * recipe_name,
00839 const char * pipeline_name,
00840 const char * pafregexp,
00841 const cpl_propertylist * pro_lintbl,
00842 const cpl_propertylist * pro_gaintbl,
00843 const cpl_propertylist * pro_coeffscube,
00844 const cpl_propertylist * pro_bpm,
00845 const cpl_propertylist * pro_corr,
00846 const cpl_propertylist * pro_diff,
00847 const char * package,
00848 int (* compare) (const cpl_frame *,
00849 const cpl_frame *),
00850 int (* load_fset) (const cpl_frameset *,
00851 cpl_type,
00852 cpl_imagelist *),
00853 const cpl_boolean opt_nir)
00854 {
00855 int nsets;
00856 int * selection = NULL;
00857 int i;
00858 cpl_frame * first = NULL;
00859 cpl_image * reference = NULL;
00860
00861
00862
00863
00864
00865
00866
00867
00868 cpl_frameset * cur_fset = NULL;
00869 cpl_frameset * cur_fset_on = NULL;
00870 cpl_frameset * cur_fset_off = NULL;
00871
00872
00873 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
00874 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
00875 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
00876 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
00877 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
00878 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
00879 cpl_ensure_code(pro_lintbl != NULL, CPL_ERROR_NULL_INPUT);
00880 cpl_ensure_code(pro_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
00881 cpl_ensure_code(pro_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
00882 cpl_ensure_code(pro_bpm != NULL, CPL_ERROR_NULL_INPUT);
00883 cpl_ensure_code(pro_corr != NULL, CPL_ERROR_NULL_INPUT);
00884 cpl_ensure_code(pro_diff != NULL, CPL_ERROR_NULL_INPUT);
00885 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
00886
00887 cpl_msg_info(cpl_func,"frameset size [%d]", cpl_frameset_get_size(frameset));
00888
00889
00890 skip_if (irplib_detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
00891
00892
00893
00894
00895
00896
00897 skip_if (irplib_detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
00898 parlist, opt_nir));
00899
00900
00901
00902
00903
00904
00905 first = cpl_frameset_get_first(frameset);
00906 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT, "Empty data set!");
00907
00908 detmon_lg_config.load_fset = load_fset;
00909 detmon_lg_config.load_fset_wrp = load_fset ? irplib_load_fset_wrp_ext : irplib_load_fset_wrp;
00910
00911
00912 if (detmon_lg_config.exts < 0) {
00913 reference = cpl_image_load(cpl_frame_get_filename(first),
00914 CPL_TYPE_FLOAT, 0, 1);
00915 } else {
00916 if (load_fset != NULL) {
00917 cpl_frameset * new = cpl_frameset_new();
00918 cpl_imagelist * p = cpl_imagelist_new();
00919 cpl_frameset_insert(new, cpl_frame_duplicate(first));
00920 (*load_fset)(new, CPL_TYPE_FLOAT, p);
00921 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
00922 cpl_imagelist_delete(p);
00923 cpl_frameset_delete(new);
00924 } else {
00925 cpl_msg_info(cpl_func,"name=%s",cpl_frame_get_filename(first));
00926 reference = cpl_image_load(cpl_frame_get_filename(first),
00927 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
00928 }
00929 }
00930 skip_if (reference == NULL);
00931
00932 skip_if (irplib_detmon_lg_check_defaults(reference));
00933
00934
00935
00936
00937
00938
00939
00940
00941 if (compare == NULL) {
00942 nsets = 1;
00943 } else {
00944 cpl_msg_info(cpl_func, "Identifying different settings");
00945 selection = cpl_frameset_labelise(frameset, compare, &nsets);
00946 skip_if (selection == NULL);
00947 }
00948
00949
00950 detmon_lg_config.nb_extensions = 1;
00951 if (detmon_lg_config.exts < 0)
00952 {
00953 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
00954 }
00955
00956 for(i = 0; i < nsets; i++)
00957 {
00958
00959 int fr_size = cpl_frameset_get_size(frameset);
00960 int fr_size_new = 0;
00961 cpl_msg_info(cpl_func, "Reduce data set nb %d out of %d",
00962 i + 1, nsets);
00963 skip_if(irplib_detmon_lg_reduce_set(i, frameset, nsets, tag_on, tag_off,
00964 recipe_name,
00965 pipeline_name,
00966 pafregexp,
00967 pro_lintbl,
00968 pro_gaintbl,
00969 pro_coeffscube,
00970 pro_bpm,
00971 pro_corr,
00972 pro_diff,
00973 package,
00974 load_fset,
00975 opt_nir,
00976 parlist,
00977 selection));
00978 fr_size_new = cpl_frameset_get_size(frameset);
00979
00980
00981
00982
00983
00984 if (fr_size_new > fr_size)
00985 {
00986 selection = cpl_realloc(selection, fr_size_new * sizeof(selection[0]));
00987 memset(selection + fr_size, -1, (fr_size_new - fr_size) * sizeof(selection[0]));
00988 }
00989 }
00990
00991 end_skip;
00992
00993 cpl_frameset_delete(cur_fset);
00994 cpl_frameset_delete(cur_fset_on);
00995 cpl_frameset_delete(cur_fset_off);
00996 cpl_free(selection);
00997 cpl_image_delete(reference);
00998
00999 return cpl_error_get_code();
01000 }
01001
01002
01033
01034
01035 static cpl_error_code
01036 irplib_detmon_lg_core(cpl_frameset * cur_fset_on,
01037 cpl_frameset * cur_fset_off,
01038 int * index_on,
01039 int * index_off,
01040 double * exptime_on,
01041 double * exptime_off,
01042 int whichext,
01043 int whichset,
01044 const char * recipe_name,
01045 const char * pipeline_name,
01046 const char * pafregexp,
01047 const cpl_propertylist * pro_lintbl,
01048 const cpl_propertylist * pro_gaintbl,
01049 const cpl_propertylist * pro_coeffscube,
01050 const cpl_propertylist * pro_bpm,
01051 const cpl_propertylist * pro_corr,
01052 const cpl_propertylist * pro_diff,
01053 const char * package,
01054 int (* load_fset) (const cpl_frameset *,
01055 cpl_type,
01056 cpl_imagelist *),
01057 int nsets, cpl_boolean opt_nir,
01058 cpl_frameset * frameset, const cpl_parameterlist * parlist,
01059 cpl_frameset * cur_fset)
01060 {
01061 cpl_table * gain_table = cpl_table_new(cpl_frameset_get_size(cur_fset_on)/2);
01062 cpl_table * linear_table = cpl_table_new(cpl_frameset_get_size(cur_fset_on)/2);
01063 cpl_imagelist * coeffs = NULL;
01064 cpl_image * bpm = NULL;
01065 cpl_imagelist * autocorr_images = NULL;
01066 cpl_imagelist * diff_flats = NULL;
01067 cpl_propertylist * gaint_qclist = NULL;
01068 cpl_propertylist * lint_qclist = NULL;
01069 cpl_propertylist * linc_qclist = NULL;
01070 cpl_propertylist * bpm_qclist = NULL;
01071
01072 int next_index_on = 0;
01073 int next_index_off = 0;
01074
01075
01076
01077 cpl_msg_info(cpl_func, "Reduce extension nb %d ",
01078 whichext);
01079
01080
01081
01082 if (detmon_lg_config.intermediate) {
01083 autocorr_images = cpl_imagelist_new();
01084 diff_flats = cpl_imagelist_new();
01085 }
01086
01087 gaint_qclist = cpl_propertylist_new();
01088 lint_qclist = cpl_propertylist_new();
01089 linc_qclist = cpl_propertylist_new();
01090 bpm_qclist = cpl_propertylist_new();
01091
01092
01093 cpl_msg_info(cpl_func, "Starting data reduction");
01094 skip_if(irplib_detmon_lg_reduce(cur_fset_on, cur_fset_off,
01095 index_on, index_off, exptime_on, exptime_off,
01096 &next_index_on, &next_index_off,
01097 &coeffs, gain_table,
01098 linear_table, &bpm, autocorr_images,
01099 diff_flats, gaint_qclist, lint_qclist,
01100 linc_qclist, bpm_qclist, load_fset,
01101 opt_nir, whichext));
01102
01103
01104 cpl_msg_info(cpl_func, "Saving the products");
01105 if(nsets == 1) {
01106 skip_if(irplib_detmon_lg_save(parlist, frameset, recipe_name,
01107 pipeline_name, pafregexp,
01108 pro_lintbl, pro_gaintbl,
01109 pro_coeffscube, pro_bpm,
01110 pro_corr, pro_diff, package,
01111 coeffs, gain_table, linear_table,
01112 bpm, autocorr_images, diff_flats,
01113 gaint_qclist, lint_qclist, linc_qclist,
01114 bpm_qclist, 0, 0, cur_fset, whichext));
01115 } else {
01116 skip_if(irplib_detmon_lg_save(parlist, frameset, recipe_name,
01117 pipeline_name, pafregexp,
01118 pro_lintbl, pro_gaintbl,
01119 pro_coeffscube, pro_bpm,
01120 pro_corr, pro_diff, package,
01121 coeffs, gain_table, linear_table,
01122 bpm, autocorr_images, diff_flats,
01123 gaint_qclist, lint_qclist, linc_qclist,
01124 bpm_qclist, 1, whichset+ 1, cur_fset,
01125 whichext));
01126 }
01127
01128 end_skip;
01129
01130
01131 cpl_table_delete(gain_table);
01132 cpl_table_delete(linear_table);
01133 cpl_imagelist_delete(coeffs);
01134 cpl_propertylist_delete(gaint_qclist);
01135 cpl_propertylist_delete(lint_qclist);
01136 cpl_propertylist_delete(linc_qclist);
01137 cpl_propertylist_delete(bpm_qclist);
01138 cpl_image_delete(bpm);
01139 cpl_imagelist_delete(autocorr_images);
01140 cpl_imagelist_delete(diff_flats);
01141
01142 return cpl_error_get_code();
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 cpl_image *
01165 irplib_detmon_image_correlate(const cpl_image * image1,
01166 const cpl_image * image2,
01167 const int m, const int n)
01168 {
01169 cpl_image *image1_padded = NULL;
01170 cpl_image *image2_padded = NULL;
01171 int nx, ny;
01172 int nx2, ny2;
01173 int i,j;
01174
01175 cpl_image *corr_image = NULL;
01176 cpl_image *corr_image_window = NULL;
01177 cpl_image *reorganised= NULL;
01178 cpl_image *image= NULL;
01179
01180 cpl_image* image_ri_inv = NULL;
01181 cpl_image* image_in_inv = NULL;
01182 cpl_error_code err = CPL_ERROR_NONE;
01183
01184
01185 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01186 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01187
01188 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
01189 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
01190
01191 nx = cpl_image_get_size_x(image1);
01192 ny = cpl_image_get_size_y(image1);
01193
01194 nx2 = cpl_image_get_size_x(image2);
01195 ny2 = cpl_image_get_size_y(image2);
01196
01197
01198 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
01199
01200
01201 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
01202 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
01203
01204 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
01205 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
01206
01207
01208 nx = nx + 2 * m;
01209 ny = ny + 2 * n;
01210
01211 cpl_image* image_ri1 = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
01212 cpl_image* image_ri2 = cpl_image_new(nx, ny , CPL_TYPE_FLOAT_COMPLEX);
01213
01214 cpl_fft_image(image_ri1, image1_padded, CPL_FFT_FORWARD);
01215 cpl_fft_image(image_ri2, image2_padded, CPL_FFT_FORWARD);
01216 err = cpl_error_get_code();
01217 cpl_image_delete(image1_padded);
01218 image1_padded = NULL;
01219 cpl_image_delete(image2_padded);
01220 image2_padded = NULL;
01221 if (err == CPL_ERROR_NONE)
01222 {
01223
01224 image_ri_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01225 image_in_inv = cpl_image_new(nx, ny, CPL_TYPE_FLOAT_COMPLEX);
01226
01227 for (i = 1; i <= nx; i++)
01228 {
01229 for (j = 1; j <= ny; j++)
01230 {
01231 int rej = 0;
01232 complex value1 = cpl_image_get_complex(image_ri1, i, j, &rej);
01233 complex value2 = cpl_image_get_complex(image_ri2, i, j, &rej);;
01234 complex value = conjf(value1) * value2;
01235 cpl_image_set_complex(image_in_inv, i, j, value);
01236 }
01237 }
01238 cpl_image_delete(image_ri1);
01239 image_ri1 = NULL;
01240 cpl_image_delete(image_ri2);
01241 image_ri2 = NULL;
01242
01243 err = cpl_error_get_code();
01244 if (err == CPL_ERROR_NONE)
01245 {
01246
01247
01248 cpl_fft_image(image_ri_inv, image_in_inv,CPL_FFT_BACKWARD);
01249 cpl_image_delete(image_in_inv);
01250
01251
01252 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01253 for (i = 1; i <= nx; i++)
01254 {
01255 for (j = 1; j <= ny; j++)
01256 {
01257 int rej = 0;
01258 double value = cpl_image_get(image_ri_inv, i, j, &rej);
01259 cpl_image_set(corr_image, i, j, value);
01260 }
01261 }
01262 cpl_image_delete(image_ri_inv);
01263
01264 cpl_error_code err = cpl_error_get_code();
01265 if (err == CPL_ERROR_NONE)
01266 {
01267
01268 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01269
01270 image = cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
01271 cpl_image_copy(reorganised, image, 1, 1);
01272 cpl_image_delete(image);
01273 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
01274 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
01275 cpl_image_delete(image);
01276
01277 cpl_image_delete(corr_image);
01278
01279 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
01280 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
01281 cpl_image_copy(corr_image, image, 1, 1);
01282 cpl_image_delete(image);
01283
01284 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
01285 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
01286 cpl_image_delete(image);
01287
01288 corr_image_window = cpl_image_extract(corr_image,
01289 nx / 2 + 1 - m,
01290 ny / 2 + 1 - n,
01291 nx / 2 + 1 + m, ny / 2 + 1 + n);
01292 }
01293
01294 }
01295 cpl_image_delete(reorganised);
01296 cpl_image_delete(corr_image);
01297
01298 if(cpl_image_divide_scalar(corr_image_window,
01299 cpl_image_get_max(corr_image_window))) {
01300 cpl_image_delete(corr_image_window);
01301 return NULL;
01302 }
01303 }
01304 cpl_image_delete (image_ri1);
01305 cpl_image_delete (image_ri2);
01306 cpl_image_delete (image1_padded);
01307 cpl_image_delete (image2_padded);
01308 return corr_image_window;
01309 }
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330 cpl_image *
01331 irplib_detmon_autocorrelate(const cpl_image * input2, const int m,
01332 const int n)
01333 {
01334 cpl_image *im_re = NULL;
01335 cpl_image *im_im = NULL;
01336 int nx, ny;
01337 cpl_image *ifft_re = NULL;
01338 cpl_image *ifft_im = NULL;
01339 cpl_image *autocorr = NULL;
01340 cpl_image *autocorr_norm_double = NULL;
01341 cpl_image *autocorr_norm = NULL;
01342 cpl_image *reorganised = NULL;
01343 cpl_image *image = NULL;
01344 int p;
01345 cpl_error_code error;
01346 cpl_image *input;
01347
01348 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01349
01350 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
01351 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
01352
01353 nx = cpl_image_get_size_x(input2) + 2 * m;
01354 ny = cpl_image_get_size_y(input2) + 2 * n;
01355
01356 p = 128;
01357 while(nx > p || ny > p) {
01358 p *= 2;
01359 }
01360
01361 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
01362
01363 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01364 error = cpl_image_copy(im_re, input, 1, 1);
01365 cpl_ensure(!error, error, NULL);
01366
01367 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01368
01369 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
01370 cpl_ensure(!error, error, NULL);
01371
01372 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01373 error = cpl_image_power(im_re, 2);
01374 cpl_ensure(!error, error, NULL);
01375
01376 error = cpl_image_add(ifft_re, im_re);
01377 cpl_ensure(!error, error, NULL);
01378
01379 cpl_image_delete(im_re);
01380
01381 error = cpl_image_power(im_im, 2);
01382 cpl_ensure(!error, error, NULL);
01383
01384 error = cpl_image_add(ifft_re, im_im);
01385 cpl_ensure(!error, error, NULL);
01386
01387 cpl_image_delete(im_im);
01388
01389 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01390
01391 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
01392 cpl_ensure(!error, error, NULL);
01393
01394 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01395
01396 error = cpl_image_power(ifft_re, 2);
01397 cpl_ensure(!error, error, NULL);
01398
01399 error = cpl_image_add(autocorr, ifft_re);
01400 cpl_ensure(!error, error, NULL);
01401
01402 cpl_image_delete(ifft_re);
01403
01404 error = cpl_image_power(ifft_im, 2);
01405 cpl_ensure(!error, error, NULL);
01406
01407 error = cpl_image_add(autocorr, ifft_im);
01408 cpl_ensure(!error, error, NULL);
01409
01410 cpl_image_delete(ifft_im);
01411
01412
01413 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01414
01415 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
01416 cpl_image_copy(reorganised, image, 1, 1);
01417 cpl_image_delete(image);
01418
01419 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
01420 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
01421 cpl_image_delete(image);
01422
01423 cpl_image_delete(autocorr);
01424
01425 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01426
01427 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
01428 cpl_image_copy(autocorr, image, 1, 1);
01429 cpl_image_delete(image);
01430
01431 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
01432 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
01433 cpl_image_delete(image);
01434
01435 cpl_image_delete(reorganised);
01436
01437 autocorr_norm_double =
01438 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
01439 p / 2 + 1 + m, p / 2 + 1 + n);
01440
01441 cpl_image_delete(autocorr);
01442
01443 if(cpl_image_divide_scalar(autocorr_norm_double,
01444 cpl_image_get_max(autocorr_norm_double))) {
01445 cpl_image_delete(autocorr_norm_double);
01446 cpl_ensure(0, cpl_error_get_code(), NULL);
01447 }
01448
01449
01450 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
01451 cpl_image_delete(autocorr_norm_double);
01452
01453 cpl_image_delete(input);
01454
01455 return autocorr_norm;
01456 }
01457
01458
01469
01470 cpl_error_code
01471 irplib_detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
01472 const char *recipe_name,
01473 const char *pipeline_name)
01474 {
01475 const cpl_error_code error =
01476 irplib_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01477 "PTC",
01478 3,
01479 3.,
01480 5,
01481 -1,
01482 -1,
01483 -1,
01484 -1,
01485 10000,
01486 "CPL_FALSE",
01487 "CPL_FALSE",
01488 "CPL_FALSE",
01489 "CPL_TRUE",
01490 "CPL_TRUE",
01491 "CPL_FALSE",
01492 -1,
01493 26,
01494 26,
01495 1e-3,
01496 recipe_name,
01497 -1,
01498 -1,
01499 -1,
01500 -1,
01501 -1,
01502 -1,
01503 -1,
01504 -1,
01505 -1,
01506 -1,
01507 -1,
01508 -1,
01509 -1,
01510 -1,
01511 -1,
01512 -1,
01513 -1,
01514 -1,
01515 -1,
01516 -1,
01517 0,
01518 NIR);
01519
01520
01521 cpl_ensure_code(!error, error);
01522
01523 return cpl_error_get_code();
01524 }
01525
01526
01537
01538 cpl_error_code
01539 irplib_detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
01540 const char *recipe_name,
01541 const char *pipeline_name)
01542 {
01543 const cpl_error_code error =
01544 irplib_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01545 "PTC",
01546 3,
01547 3.,
01548 5,
01549 -1,
01550 -1,
01551 -1,
01552 -1,
01553 10000,
01554 "CPL_FALSE",
01555 "CPL_FALSE",
01556 "CPL_TRUE",
01557 "CPL_TRUE",
01558 "CPL_FALSE",
01559 "CPL_FALSE",
01560 -1,
01561 26,
01562 26,
01563 1e-3,
01564 recipe_name,
01565 -1,
01566 -1,
01567 -1,
01568 -1,
01569 -1,
01570 -1,
01571 -1,
01572 -1,
01573 -1,
01574 -1,
01575 -1,
01576 -1,
01577 -1,
01578 -1,
01579 -1,
01580 -1,
01581 -1,
01582 -1,
01583 -1,
01584 -1,
01585 0,
01586 OPT);
01587
01588 cpl_ensure_code(!error, error);
01589
01590 return cpl_error_get_code();
01591 }
01592
01593
01647
01648 cpl_error_code
01649 irplib_detmon_lg_fill_parlist(cpl_parameterlist * parlist,
01650 const char *recipe_name, const char *pipeline_name,
01651 const char *method,
01652 int order,
01653 double kappa,
01654 int niter,
01655 int llx,
01656 int lly,
01657 int urx,
01658 int ury,
01659 int ref_level,
01660 const char *intermediate,
01661 const char *autocorr,
01662 const char *collapse,
01663 const char *rescale,
01664 const char *pix2pix,
01665 const char *bpmbin,
01666 int filter,
01667 int m,
01668 int n,
01669 double tolerance,
01670 const char * pafname,
01671 int llx1,
01672 int lly1,
01673 int urx1,
01674 int ury1,
01675 int llx2,
01676 int lly2,
01677 int urx2,
01678 int ury2,
01679 int llx3,
01680 int lly3,
01681 int urx3,
01682 int ury3,
01683 int llx4,
01684 int lly4,
01685 int urx4,
01686 int ury4,
01687 int llx5, int lly5, int urx5, int ury5, int exts,
01688 cpl_boolean opt_nir)
01689 {
01690 const cpl_error_code error =
01691 irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 24,
01692 "method",
01693 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
01694 "CPL_TYPE_STRING", method,
01695
01696 "order",
01697 "Polynomial order for the fit (Linearity)",
01698 "CPL_TYPE_INT", order,
01699 "kappa",
01700 "Kappa value for the kappa-sigma clipping (Gain)",
01701 "CPL_TYPE_DOUBLE", kappa,
01702 "niter",
01703 "Number of iterations to compute rms (Gain)",
01704 "CPL_TYPE_INT", niter,
01705 "llx",
01706 "x coordinate of the lower-left "
01707 "point of the region of interest. If not modified, default value will be 1.",
01708 "CPL_TYPE_INT", llx,
01709 "lly",
01710 "y coordinate of the lower-left "
01711 "point of the region of interest. If not modified, default value will be 1.",
01712 "CPL_TYPE_INT", lly,
01713 "urx",
01714 "x coordinate of the upper-right "
01715 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
01716 "CPL_TYPE_INT", urx,
01717 "ury",
01718 "y coordinate of the upper-right "
01719 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
01720 "CPL_TYPE_INT", ury,
01721 "ref_level",
01722 "User reference level",
01723 "CPL_TYPE_INT", ref_level,
01724 "intermediate",
01725 "De-/Activate intermediate products",
01726 "CPL_TYPE_BOOL", intermediate,
01727 "autocorr",
01728 "De-/Activate the autocorr option",
01729 "CPL_TYPE_BOOL", autocorr,
01730 "collapse",
01731 "De-/Activate the collapse option",
01732 "CPL_TYPE_BOOL", collapse,
01733 "rescale",
01734 "De-/Activate the image rescale option",
01735 "CPL_TYPE_BOOL", rescale,
01736 "pix2pix",
01737 "De-/Activate the computation with pixel to pixel accuracy",
01738 "CPL_TYPE_BOOL", pix2pix,
01739 "bpmbin",
01740 "De-/Activate the binary bpm option",
01741 "CPL_TYPE_BOOL", bpmbin,
01742 "m",
01743 "Maximum x-shift for the autocorr",
01744 "CPL_TYPE_INT", m,
01745 "filter",
01746 "Upper limit of Median flux to be filtered",
01747 "CPL_TYPE_INT", filter,
01748 "n",
01749 "Maximum y-shift for the autocorr",
01750 "CPL_TYPE_INT", n,
01751 "tolerance",
01752 "Tolerance for pair discrimination",
01753 "CPL_TYPE_DOUBLE", tolerance,
01754 "pafname",
01755 "Specific name for PAF file",
01756 "CPL_TYPE_STRING", pafname,
01757
01758 "exts",
01759 "Activate the multi-exts option",
01760 "CPL_TYPE_INT", exts,
01761
01762 "fpn_method",
01763 "Method for computing Fixed Pattern Noise (SMOOTH or HISTOGRAM)",
01764 "CPL_TYPE_STRING", "HISTOGRAM",
01765
01766 "fpn_smooth",
01767 "template size in pixels for smoothing during FPN computation (only for SMOOTH method)",
01768 "CPL_TYPE_INT", 13,
01769
01770 "saturation_limit",
01771 "all frames with mean saturation above the limit would not be used in calculation",
01772 "CPL_TYPE_DOUBLE", 65535.0
01773 );
01774
01775
01776 if(opt_nir == FALSE) {
01777 const cpl_error_code erroropt =
01778 irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
01779 "llx1",
01780 "x coord of the lower-left point of the first "
01781 "field used for contamination measurement. If not modified, default value will be 1.",
01782 "CPL_TYPE_INT", llx1,
01783 "lly1",
01784 "y coord of the lower-left point of the first "
01785 "field used for contamination measurement. If not modified, default value will be 1.",
01786 "CPL_TYPE_INT", lly1,
01787 "urx1",
01788 "x coord of the upper-right point of the first "
01789 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
01790 "CPL_TYPE_INT", urx1,
01791 "ury1",
01792 "y coord of the upper-right point of the first "
01793 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01794 "CPL_TYPE_INT", ury1,
01795 "llx2",
01796 "x coord of the lower-left point of the second "
01797 "field used for contamination measurement. If not modified, default value will be 1.",
01798 "CPL_TYPE_INT", llx2,
01799 "lly2",
01800 "y coord of the lower-left point of the second "
01801 "field used for contamination measurement. If not modified, default value will be 1.",
01802 "CPL_TYPE_INT", lly2,
01803 "urx2",
01804 "x coord of the upper-right point of the second "
01805 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01806 "CPL_TYPE_INT", urx2,
01807 "ury2",
01808 "y coord of the upper-right point of the second "
01809 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01810 "CPL_TYPE_INT", ury2,
01811 "llx3",
01812 "x coord of the lower-left point of the third "
01813 "field used for contamination measurement. If not modified, default value will be 1.",
01814 "CPL_TYPE_INT", llx3,
01815 "lly3",
01816 "y coord of the lower-left point of the third "
01817 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01818 "CPL_TYPE_INT", lly3,
01819 "urx3",
01820 "x coord of the upper-right point of the third "
01821 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01822 "CPL_TYPE_INT", urx3,
01823 "ury3",
01824 "y coord of the upper-right point of the third "
01825 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
01826 "CPL_TYPE_INT", ury3,
01827 "llx4",
01828 "x coord of the lower-left point of the fourth "
01829 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01830 "CPL_TYPE_INT", llx4,
01831 "lly4",
01832 "y coord of the lower-left point of the fourth "
01833 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01834 "CPL_TYPE_INT", lly4,
01835 "urx4",
01836 "x coord of the upper-right point of the fourth "
01837 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01838 "CPL_TYPE_INT", urx4,
01839 "ury4",
01840 "y coord of the upper-right point of the fourth "
01841 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01842 "CPL_TYPE_INT", ury4,
01843 "llx5",
01844 "x coord of the lower-left point of the fifth "
01845 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01846 "CPL_TYPE_INT", llx5,
01847 "lly5",
01848 "y coord of the lower-left point of the fifth "
01849 "field used for contamination measurement. If not modified, default value will be 1.",
01850 "CPL_TYPE_INT", lly5,
01851 "urx5",
01852 "x coord of the upper-right point of the fifth "
01853 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01854 "CPL_TYPE_INT", urx5,
01855
01856 "ury5",
01857 "y coord of the upper-right point of the fifth "
01858 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
01859 "CPL_TYPE_INT", ury5);
01860 cpl_ensure_code(!erroropt, erroropt);
01861 }
01862
01863 cpl_ensure_code(!error, error);
01864
01865 return cpl_error_get_code();
01866 }
01867
01868
01877
01878 static cpl_error_code
01879 irplib_detmon_lg_retrieve_parlist(const char * pipeline_name,
01880 const char * recipe_name,
01881 const cpl_parameterlist * parlist,
01882 cpl_boolean opt_nir)
01883 {
01884
01885 char * par_name;
01886 cpl_parameter * par;
01887
01888
01889 par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
01890 assert(par_name != NULL);
01891 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01892 detmon_lg_config.method = cpl_parameter_get_string(par);
01893 cpl_free(par_name);
01894
01895
01896 detmon_lg_config.order =
01897 irplib_detmon_retrieve_par_int("order", pipeline_name, recipe_name,
01898 parlist);
01899
01900
01901 detmon_lg_config.kappa =
01902 irplib_detmon_retrieve_par_double("kappa", pipeline_name, recipe_name,
01903 parlist);
01904
01905
01906 detmon_lg_config.niter =
01907 irplib_detmon_retrieve_par_int("niter", pipeline_name, recipe_name,
01908 parlist);
01909
01910
01911 detmon_lg_config.llx =
01912 irplib_detmon_retrieve_par_int("llx", pipeline_name, recipe_name,
01913 parlist);
01914
01915
01916 detmon_lg_config.lly =
01917 irplib_detmon_retrieve_par_int("lly", pipeline_name, recipe_name,
01918 parlist);
01919
01920
01921 detmon_lg_config.urx =
01922 irplib_detmon_retrieve_par_int("urx", pipeline_name, recipe_name,
01923 parlist);
01924
01925
01926 detmon_lg_config.ury =
01927 irplib_detmon_retrieve_par_int("ury", pipeline_name, recipe_name,
01928 parlist);
01929
01930
01931 detmon_lg_config.ref_level =
01932 irplib_detmon_retrieve_par_int("ref_level", pipeline_name, recipe_name,
01933 parlist);
01934
01935
01936 par_name =
01937 cpl_sprintf("%s.%s.intermediate", pipeline_name, recipe_name);
01938 assert(par_name != NULL);
01939 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01940 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
01941 cpl_free(par_name);
01942
01943
01944 par_name = cpl_sprintf("%s.%s.autocorr", pipeline_name, recipe_name);
01945 assert(par_name != NULL);
01946 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01947 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
01948 cpl_free(par_name);
01949
01950
01951 par_name = cpl_sprintf("%s.%s.collapse", pipeline_name, recipe_name);
01952 assert(par_name != NULL);
01953 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01954 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
01955 cpl_free(par_name);
01956
01957
01958 par_name = cpl_sprintf("%s.%s.rescale", pipeline_name, recipe_name);
01959 assert(par_name != NULL);
01960 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01961 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
01962 cpl_free(par_name);
01963
01964
01965 par_name = cpl_sprintf("%s.%s.pix2pix", pipeline_name, recipe_name);
01966 assert(par_name != NULL);
01967 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01968 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
01969 cpl_free(par_name);
01970
01971
01972 par_name = cpl_sprintf("%s.%s.bpmbin", pipeline_name, recipe_name);
01973 assert(par_name != NULL);
01974 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01975 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
01976 cpl_free(par_name);
01977
01978
01979 detmon_lg_config.filter =
01980 irplib_detmon_retrieve_par_int("filter", pipeline_name,
01981 recipe_name, parlist);
01982
01983
01984 detmon_lg_config.m =
01985 irplib_detmon_retrieve_par_int("m", pipeline_name, recipe_name, parlist);
01986
01987
01988 detmon_lg_config.n =
01989 irplib_detmon_retrieve_par_int("n", pipeline_name, recipe_name, parlist);
01990
01991
01992 par_name = cpl_sprintf("%s.%s.tolerance", pipeline_name, recipe_name);
01993 assert(par_name != NULL);
01994 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01995 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
01996 cpl_free(par_name);
01997
01998
01999 par_name = cpl_sprintf("%s.%s.pafname", pipeline_name, recipe_name);
02000 assert(par_name != NULL);
02001 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
02002 detmon_lg_config.pafname = cpl_parameter_get_string(par);
02003 cpl_free(par_name);
02004
02005 if(opt_nir == OPT) {
02006
02007 detmon_lg_config.llx1 =
02008 irplib_detmon_retrieve_par_int("llx1", pipeline_name, recipe_name,
02009 parlist);
02010
02011
02012 detmon_lg_config.lly1 =
02013 irplib_detmon_retrieve_par_int("lly1", pipeline_name, recipe_name,
02014 parlist);
02015
02016
02017 detmon_lg_config.urx1 =
02018 irplib_detmon_retrieve_par_int("urx1", pipeline_name, recipe_name,
02019 parlist);
02020
02021
02022 detmon_lg_config.ury1 =
02023 irplib_detmon_retrieve_par_int("ury1", pipeline_name, recipe_name,
02024 parlist);
02025
02026
02027 detmon_lg_config.llx2 =
02028 irplib_detmon_retrieve_par_int("llx2", pipeline_name, recipe_name,
02029 parlist);
02030
02031
02032 detmon_lg_config.lly2 =
02033 irplib_detmon_retrieve_par_int("lly2", pipeline_name, recipe_name,
02034 parlist);
02035
02036
02037 detmon_lg_config.urx2 =
02038 irplib_detmon_retrieve_par_int("urx2", pipeline_name, recipe_name,
02039 parlist);
02040
02041
02042 detmon_lg_config.ury2 =
02043 irplib_detmon_retrieve_par_int("ury2", pipeline_name, recipe_name,
02044 parlist);
02045
02046
02047 detmon_lg_config.llx3 =
02048 irplib_detmon_retrieve_par_int("llx3", pipeline_name, recipe_name,
02049 parlist);
02050
02051
02052 detmon_lg_config.lly3 =
02053 irplib_detmon_retrieve_par_int("lly3", pipeline_name, recipe_name,
02054 parlist);
02055
02056
02057 detmon_lg_config.urx3 =
02058 irplib_detmon_retrieve_par_int("urx3", pipeline_name, recipe_name,
02059 parlist);
02060
02061
02062 detmon_lg_config.ury3 =
02063 irplib_detmon_retrieve_par_int("ury3", pipeline_name, recipe_name,
02064 parlist);
02065
02066
02067 detmon_lg_config.llx4 =
02068 irplib_detmon_retrieve_par_int("llx4", pipeline_name, recipe_name,
02069 parlist);
02070
02071
02072 detmon_lg_config.lly4 =
02073 irplib_detmon_retrieve_par_int("lly4", pipeline_name, recipe_name,
02074 parlist);
02075
02076
02077 detmon_lg_config.urx4 =
02078 irplib_detmon_retrieve_par_int("urx4", pipeline_name, recipe_name,
02079 parlist);
02080
02081
02082 detmon_lg_config.ury4 =
02083 irplib_detmon_retrieve_par_int("ury4", pipeline_name, recipe_name,
02084 parlist);
02085
02086
02087 detmon_lg_config.llx5 =
02088 irplib_detmon_retrieve_par_int("llx5", pipeline_name, recipe_name,
02089 parlist);
02090
02091
02092 detmon_lg_config.lly5 =
02093 irplib_detmon_retrieve_par_int("lly5", pipeline_name, recipe_name,
02094 parlist);
02095
02096
02097 detmon_lg_config.urx5 =
02098 irplib_detmon_retrieve_par_int("urx5", pipeline_name, recipe_name,
02099 parlist);
02100
02101
02102 detmon_lg_config.ury5 =
02103 irplib_detmon_retrieve_par_int("ury5", pipeline_name, recipe_name,
02104 parlist);
02105 }
02106
02107
02108 detmon_lg_config.exts =
02109 irplib_detmon_retrieve_par_int("exts", pipeline_name, recipe_name,
02110 parlist);
02111
02112 {
02113 const char* str_method = 0;
02114 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
02115 par_name =
02116 cpl_sprintf("%s.%s.fpn_method", pipeline_name, recipe_name);
02117 assert(par_name != NULL);
02118 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
02119 if (par)
02120 {
02121 str_method = cpl_parameter_get_string(par);
02122 if (strcmp(str_method, "SMOOTH") == 0)
02123 {
02124 detmon_lg_config.fpn_method = FPN_SMOOTH;
02125 }
02126 else if (strcmp(str_method, "HISTOGRAM") == 0)
02127 {
02128 detmon_lg_config.fpn_method = FPN_HISTOGRAM;
02129 }
02130 }
02131 cpl_free(par_name);
02132 }
02133
02134 detmon_lg_config.fpn_smooth =
02135 irplib_detmon_retrieve_par_int("fpn_smooth", pipeline_name, recipe_name,
02136 parlist);
02137
02138 {
02139 detmon_lg_config.saturation_limit = 65535;
02140 par_name =
02141 cpl_sprintf("%s.%s.saturation_limit", pipeline_name, recipe_name);
02142 assert(par_name != NULL);
02143 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
02144 if (par)
02145 {
02146 detmon_lg_config.saturation_limit = cpl_parameter_get_double(par);
02147 }
02148 cpl_free(par_name);
02149 }
02150 if(cpl_error_get_code())
02151 {
02152 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
02153 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
02154 }
02155
02156
02157 return cpl_error_get_code();
02158 }
02159
02160
02166
02167 static cpl_error_code
02168 irplib_detmon_lg_check_defaults(const cpl_image * reference)
02169 {
02170 const int nx = cpl_image_get_size_x(reference);
02171 const int ny = cpl_image_get_size_y(reference);
02172
02173 detmon_lg_config.nx = nx;
02174 detmon_lg_config.ny = ny;
02175
02176 detmon_lg_config.wholechip = CPL_FALSE;
02177
02178 if(detmon_lg_config.llx == -1)
02179 detmon_lg_config.llx = 1;
02180 if(detmon_lg_config.lly == -1)
02181 detmon_lg_config.lly = 1;
02182 if(detmon_lg_config.urx == -1)
02183 detmon_lg_config.urx = nx;
02184 if(detmon_lg_config.ury == -1)
02185 detmon_lg_config.ury = ny;
02186
02187 if (detmon_lg_config.llx == 1 &&
02188 detmon_lg_config.lly == 1 &&
02189 detmon_lg_config.urx == nx &&
02190 detmon_lg_config.ury == ny)
02191 detmon_lg_config.wholechip = CPL_TRUE;
02192
02193 if(detmon_lg_config.llx1 == -1)
02194 detmon_lg_config.llx1 = 1;
02195 if(detmon_lg_config.lly1 == -1)
02196 detmon_lg_config.lly1 = 1;
02197 if(detmon_lg_config.urx1 == -1)
02198 detmon_lg_config.urx1 = nx;
02199 if(detmon_lg_config.ury1 == -1)
02200 detmon_lg_config.ury1 = ny;
02201
02202 if(detmon_lg_config.llx2 == -1)
02203 detmon_lg_config.llx2 = 1;
02204 if(detmon_lg_config.lly2 == -1)
02205 detmon_lg_config.lly2 = 1;
02206 if(detmon_lg_config.urx2 == -1)
02207 detmon_lg_config.urx2 = nx / 2;
02208 if(detmon_lg_config.ury2 == -1)
02209 detmon_lg_config.ury2 = ny / 2;
02210
02211 if(detmon_lg_config.llx3 == -1)
02212 detmon_lg_config.llx3 = 1;
02213 if(detmon_lg_config.lly3 == -1)
02214 detmon_lg_config.lly3 = ny / 2;
02215 if(detmon_lg_config.urx3 == -1)
02216 detmon_lg_config.urx3 = nx / 2;
02217 if(detmon_lg_config.ury3 == -1)
02218 detmon_lg_config.ury3 = ny;
02219
02220 if(detmon_lg_config.llx4 == -1)
02221 detmon_lg_config.llx4 = nx / 2;
02222 if(detmon_lg_config.lly4 == -1)
02223 detmon_lg_config.lly4 = ny / 2;
02224 if(detmon_lg_config.urx4 == -1)
02225 detmon_lg_config.urx4 = nx;
02226 if(detmon_lg_config.ury4 == -1)
02227 detmon_lg_config.ury4 = ny;
02228
02229 if(detmon_lg_config.llx5 == -1)
02230 detmon_lg_config.llx5 = nx / 2;
02231 if(detmon_lg_config.lly5 == -1)
02232 detmon_lg_config.lly5 = 1;
02233 if(detmon_lg_config.urx5 == -1)
02234 detmon_lg_config.urx5 = nx;
02235 if(detmon_lg_config.ury5 == -1)
02236 detmon_lg_config.ury5 = ny / 2;
02237
02238 if(detmon_lg_config.intermediate == TRUE) {
02239 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.");
02240 detmon_lg_config.autocorr = TRUE;
02241 }
02242
02243
02244 detmon_lg_config.lamp_stability = 0.0;
02245
02246 detmon_lg_config.lamp_ok = FALSE;
02247
02248 detmon_lg_config.cr = 0.0;
02249
02250 return cpl_error_get_code();
02251 }
02252
02253
02264
02265 static cpl_error_code
02266 irplib_detmon_lg_split_onoff(const cpl_frameset * cur_fset,
02267 cpl_frameset * cur_fset_on,
02268 cpl_frameset * cur_fset_off,
02269 const char *tag_on,
02270 const char *tag_off)
02271 {
02272 int nframes;
02273 int i;
02274
02275 const cpl_frame * first;
02276 const cpl_frame * second;
02277
02278 const char * first_tag;
02279 const char * second_tag;
02280
02281 cpl_frame * cur_frame_dup = NULL;
02282
02283 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
02284 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
02285
02286 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
02287 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
02288
02289 #if 0
02290 if (opt_nir == OPT &&
02291 ((!strcmp(first_tag, tag_on ) && !strcmp(second_tag, tag_off)) ||
02292 (!strcmp(first_tag, tag_off) && !strcmp(second_tag, tag_on )))) {
02293 detmon_lg_config.lamp_ok = TRUE;
02294 }
02295 #endif
02296
02297 nframes = cpl_frameset_get_size(cur_fset);
02298 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
02299 const cpl_frame * cur_frame =
02300 cpl_frameset_get_frame_const(cur_fset, i);
02301 char * tag;
02302
02303
02304 cur_frame_dup = cpl_frame_duplicate(cur_frame);
02305 tag = (char *) cpl_frame_get_tag(cur_frame_dup);
02306
02307
02308 if(!strcmp(tag, tag_on)) {
02309 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
02310 } else if(!strcmp(tag, tag_off)) {
02311 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
02312 } else {
02313 cpl_frame_delete(cur_frame_dup);
02314 cur_frame_dup = NULL;
02315 }
02316 }
02317 cur_frame_dup = NULL;
02318
02319 end_skip;
02320
02321 cpl_frame_delete(cur_frame_dup);
02322
02323 return cpl_error_get_code();
02324 }
02325
02326
02348
02349
02350 static cpl_error_code
02351 irplib_detmon_lg_reduce(const cpl_frameset * set_on,
02352 const cpl_frameset * set_off,
02353 int* index_on, int* index_off, double* exptime_on, double* exptime_off,
02354 int *next_index_on, int* next_index_off,
02355 cpl_imagelist ** coeffs_ptr,
02356 cpl_table * gain_table,
02357 cpl_table * linear_table,
02358 cpl_image ** bpm_ptr,
02359 cpl_imagelist * autocorr_images,
02360 cpl_imagelist * diff_flats,
02361 cpl_propertylist * gaint_qclist,
02362 cpl_propertylist * lint_qclist,
02363 cpl_propertylist * linc_qclist,
02364 cpl_propertylist * bpm_qclist,
02365 int (* load_fset) (const cpl_frameset *,
02366 cpl_type,
02367 cpl_imagelist *),
02368 const cpl_boolean opt_nir,
02369 int whichext)
02370 {
02371 const double D_INVALID_VALUE = -999;
02372 int i;
02373 cpl_imagelist * linearity_inputs = NULL;
02374 cpl_imagelist * opt_offs = NULL;
02375 int nsets;
02376 cpl_propertylist * reflist = NULL;
02377 int dit_nskip=0;
02378 int rows_affected = 1;
02379 int last_best = 0;
02380
02381 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02382 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02383
02384 nsets = cpl_frameset_get_size(set_on) / 2;
02385
02386 detmon_lg_config.load_fset = load_fset;
02387
02388 if(detmon_lg_config.collapse) {
02389
02390
02391
02392
02393
02394
02395 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
02396 cpl_frame *dup_first = cpl_frame_duplicate(first);
02397
02398 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
02399 cpl_frame *dup_second = cpl_frame_duplicate(second);
02400
02401 cpl_frameset *raw_offs = cpl_frameset_new();
02402
02403 cpl_frameset_insert(raw_offs, dup_first);
02404 cpl_frameset_insert(raw_offs, dup_second);
02405
02406 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
02407 0, whichext);
02408
02409 cpl_frameset_delete(raw_offs);
02410
02411 }
02412
02413 skip_if(irplib_detmon_lg_reduce_init(gain_table,
02414 linear_table,
02415 &linearity_inputs,
02416 opt_nir));
02417
02418 if (!strcmp(detmon_lg_config.method, "PTC"))
02419 {
02420 cpl_msg_warning(cpl_func, "PTC method incompatible with lamp stability computation");
02421 }
02422 else if(!detmon_lg_config.collapse)
02423 {
02424 skip_if(irplib_detmon_lg_lamp_stab(set_on, set_off,
02425 opt_nir, whichext));
02426 }
02427
02428 skip_if(cpl_table_unselect_all(linear_table));
02429 skip_if(cpl_table_unselect_all(gain_table));
02430
02431
02432
02433
02434
02435
02436
02437 for(i = 0; i < nsets ; i++)
02438 {
02439 skip_if(irplib_detmon_lg_reduce_dit(set_on,
02440 index_on, exptime_on,
02441 i,
02442 &dit_nskip,
02443 set_off,
02444 index_off, exptime_off,
02445 next_index_on, next_index_off,
02446 linear_table,
02447 gain_table, linearity_inputs,
02448 lint_qclist, opt_nir,
02449 autocorr_images, diff_flats,
02450 opt_offs, whichext,
02451 &rows_affected));
02452 if (rows_affected == 0)
02453 {
02454 cpl_msg_warning(cpl_func, "The rest frames would not be taken into calculation, check the messages above");
02455 cpl_table_select_row(linear_table, i);
02456 }
02457 else
02458 {
02459 last_best = i;
02460 }
02461 }
02462
02463 skip_if(irplib_detmon_add_adl_column(linear_table, opt_nir));
02464
02465
02466
02467
02468
02469 skip_if(cpl_table_erase_selected(gain_table));
02470 skip_if(cpl_table_erase_selected(linear_table));
02471
02472 reflist = cpl_propertylist_new();
02473 skip_if(cpl_propertylist_append_bool(reflist, "ADU", FALSE));
02474 skip_if(cpl_table_sort(gain_table, reflist));
02475
02476
02477
02478
02479
02480
02481 skip_if(irplib_detmon_lg_reduce_all(linear_table,
02482 gaint_qclist, lint_qclist, linc_qclist,
02483 bpm_qclist, coeffs_ptr, bpm_ptr,
02484 linearity_inputs,
02485 gain_table, whichext, opt_nir));
02486
02487 {
02488
02489 double gain = cpl_propertylist_get_double(gaint_qclist, DETMON_QC_GAIN);
02490 cpl_error_code cplerr = cpl_error_get_code();
02491 if (cplerr != CPL_ERROR_NONE)
02492 {
02493 cpl_msg_warning(cpl_func, "Cannot read gain from QC parameters - FPN would not be computed");
02494 cpl_error_reset();
02495 }
02496 else
02497 {
02498 irplib_detmon_fpn_compute(set_on, index_on, last_best, lint_qclist,
02499 detmon_lg_config.llx,
02500 detmon_lg_config.lly,
02501 detmon_lg_config.urx,
02502 detmon_lg_config.ury,
02503 gain,
02504 whichext,
02505 detmon_lg_config.fpn_method,
02506 detmon_lg_config.fpn_smooth);
02507 }
02508 }
02509
02510 irplib_detmon_table_fill_invalid(gain_table, D_INVALID_VALUE);
02511 end_skip;
02512
02513 cpl_imagelist_delete(linearity_inputs);
02514 cpl_imagelist_delete(opt_offs);
02515 cpl_propertylist_delete(reflist);
02516
02517 return cpl_error_get_code();
02518 }
02519
02520 static cpl_error_code irplib_detmon_table_fill_invalid(cpl_table* ptable, double code)
02521 {
02522 int ncols = cpl_table_get_ncol(ptable);
02523 cpl_array* pnames = cpl_table_get_column_names(ptable);
02524 int nrows = cpl_table_get_nrow(ptable);
02525 int i = 0;
02526 for (i=0; i < ncols; i++)
02527 {
02528 int j = 0;
02529 for (j = 0; j< nrows; j++)
02530 {
02531 const char* colname = cpl_array_get_data_string_const(pnames)[i];
02532 int isnull;
02533 cpl_type type = cpl_table_get_column_type(ptable, colname);
02534 cpl_table_get(ptable, colname, j, &isnull);
02535 if(isnull == 1)
02536 {
02537 if (type == CPL_TYPE_DOUBLE)
02538 {
02539 cpl_table_set(ptable,colname,j, code);
02540 }
02541 else if (type == CPL_TYPE_FLOAT)
02542 {
02543 cpl_table_set_float(ptable,colname,j, (float)code);
02544 }
02545 }
02546 }
02547 }
02548 cpl_array_delete(pnames);
02549 return cpl_error_get_code();
02550 }
02551
02552 static cpl_error_code
02553 irplib_detmon_fpn_compute(const cpl_frameset *set_on,
02554 int * index_on,
02555 int last_best,
02556 cpl_propertylist *lint_qclist,
02557 int llx,
02558 int lly,
02559 int urx,
02560 int ury,
02561 double gain,
02562 int whichext,
02563 FPN_METHOD fpn_method,
02564 int smooth_size)
02565 {
02566 double fpn = 0;
02567 const cpl_image* im1 = 0;
02568 int range[4];
02569 cpl_imagelist* ons = 0;
02570 cpl_frameset * pair_on = 0;
02571 int nsets_extracted = cpl_frameset_get_size(set_on);
02572 int * selection = 0;
02573 double mse = 0;
02574 range[0] = llx;
02575 range[1] = lly;
02576 range[2] = urx;
02577 range[3] = ury;
02578
02579
02580
02581 selection = cpl_malloc(sizeof(int) * nsets_extracted);
02582 memset(&selection[0], 0, sizeof(int) * nsets_extracted);
02583
02584 selection[index_on[last_best*2 + 0] ] = 1;
02585 selection[index_on[last_best*2 + 1] ] = 1;
02586 pair_on = cpl_frameset_extract(set_on, selection, 1);
02587 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
02588
02589 skip_if(ons == NULL);
02590 skip_if((im1 = cpl_imagelist_get_const(ons, 0)) == NULL);
02591
02592 fpn = irplib_fpn_lg(im1, range, gain, fpn_method, smooth_size, &mse);
02593 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_FPN,
02594 fpn));
02595 skip_if(cpl_propertylist_append_double(lint_qclist, "ESO QC GAIN ERR",
02596 mse));
02597
02598 cleanup:
02599 cpl_frameset_delete(pair_on);
02600 cpl_imagelist_delete(ons);
02601 cpl_free(selection);
02602 return cpl_error_get_code();
02603 }
02604
02605
02613
02614 static cpl_error_code
02615 irplib_detmon_lg_lamp_stab(const cpl_frameset * lamps,
02616 const cpl_frameset * darks,
02617 cpl_boolean opt_nir,
02618 int whichext)
02619 {
02620
02621
02622
02623
02624
02625
02626 int nb_lamps;
02627
02628 cpl_vector * selection = NULL;
02629 cpl_propertylist * plist;
02630 double dit_lamp, dit_dark;
02631 int dit_stab;
02632 cpl_imagelist * lamps_data = NULL;
02633 cpl_imagelist * darks_data = NULL;
02634 double * stab_levels = NULL;
02635 int i, j;
02636 double * ditvals = NULL;
02637 int last_stab = 0;
02638
02639
02640 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
02641 CPL_ERROR_ILLEGAL_INPUT);
02642 cpl_ensure_code(cpl_frameset_get_size(darks) == nb_lamps,
02643 CPL_ERROR_ILLEGAL_INPUT);
02644
02645
02646 cpl_msg_info(__func__, "Checking DIT consistency");
02647 selection = cpl_vector_new(nb_lamps);
02648 ditvals = cpl_malloc(nb_lamps * sizeof(double));
02649 dit_stab = 0;
02650 for (i = 0; i < nb_lamps; i++) {
02651 const cpl_frame * c_lamp;
02652 const cpl_frame * c_dark;
02653
02654 skip_if (cpl_error_get_code());
02655
02656
02657 c_lamp = cpl_frameset_get_frame_const(lamps, i);
02658 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
02659 if(opt_nir)
02660 dit_lamp = (double)irplib_pfits_get_dit(plist);
02661 else
02662 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
02663 cpl_propertylist_delete(plist);
02664 skip_if (cpl_error_get_code());
02665
02666
02667 c_dark = cpl_frameset_get_frame_const(darks, i);
02668 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
02669 if(opt_nir)
02670 dit_dark = (double)irplib_pfits_get_dit(plist);
02671 else
02672 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
02673 cpl_propertylist_delete(plist);
02674 skip_if (cpl_error_get_code());
02675
02676
02677 if (fabs(dit_dark-dit_lamp) > 1e-3) {
02678 cpl_msg_error(__func__, "DIT not consistent between LAMP and DARK");
02679
02680 skip_if(1);
02681 }
02682 ditvals[i] = dit_lamp;
02683
02684 if (i==0) {
02685 cpl_vector_set(selection, i, -1.0);
02686 dit_stab ++;
02687 last_stab = 0;
02688 } else {
02689
02690
02691
02692
02693 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
02694 cpl_vector_set(selection, i, -1.0);
02695 dit_stab ++;
02696 last_stab = i;
02697 } else {
02698 cpl_vector_set(selection, i, 1.0);
02699 }
02700 }
02701 }
02702
02703
02704 if (dit_stab < 2) {
02705 cpl_msg_info(__func__, "Not enough frames for stability check");
02706 } else {
02707
02708
02709 cpl_msg_info(__func__, "Compute the differences lamp - dark");
02710 lamps_data = cpl_imagelist_load_frameset(lamps, CPL_TYPE_FLOAT, 1,
02711 whichext);
02712 darks_data = cpl_imagelist_load_frameset(darks, CPL_TYPE_FLOAT, 1,
02713 whichext);
02714 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
02715
02716
02717 cpl_msg_info(__func__, "Check the lamp stability");
02718 stab_levels = cpl_malloc(dit_stab * sizeof(double));
02719 j = 0;
02720 for (i=0; i<nb_lamps; i++) {
02721 if (cpl_vector_get(selection, i) < 0) {
02722 stab_levels[j] =
02723 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
02724 j++;
02725 }
02726 }
02727
02728
02729 for (i=1; i<dit_stab; i++) {
02730 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
02731 detmon_lg_config.lamp_stability)
02732 detmon_lg_config.lamp_stability =
02733 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
02734 }
02735
02736
02737
02738 if (detmon_lg_config.lamp_stability > 0.01) {
02739 cpl_msg_warning(__func__,
02740 "level difference too high - proceed anyway");
02741 }
02742 }
02743 end_skip;
02744
02745 cpl_free(ditvals);
02746 cpl_vector_delete(selection);
02747 cpl_imagelist_delete(lamps_data);
02748 cpl_imagelist_delete(darks_data);
02749 cpl_free(stab_levels);
02750
02751 return cpl_error_get_code();
02752 }
02753
02754
02777
02778 static cpl_error_code
02779 irplib_detmon_lg_reduce_dit(const cpl_frameset * set_on,
02780 int* index_on, double* exptime_on,
02781 const int dit_nb,
02782 int * dit_nskip,
02783 const cpl_frameset * set_off,
02784 int * index_off, double* exptime_off,
02785 int* next_on, int* next_off,
02786 cpl_table * linear_table,
02787 cpl_table * gain_table,
02788 cpl_imagelist * linearity_inputs,
02789 cpl_propertylist * qclist,
02790 cpl_boolean opt_nir,
02791 cpl_imagelist * autocorr_images,
02792 cpl_imagelist * diff_flats,
02793 cpl_imagelist * opt_offs,
02794 int whichext,
02795 int* rows_affected)
02796 {
02797 cpl_frameset * pair_on = NULL;
02798 cpl_frameset * pair_off = NULL;
02799 cpl_imagelist * ons = NULL;
02800 cpl_imagelist * offs = NULL;
02801 cpl_boolean follow = CPL_TRUE;
02802 cpl_imagelist * masterl = NULL;
02803 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
02804 double c_dit;
02805 int c_ndit;
02806
02807 double current_dit = 0;
02808
02809 const char * filename;
02810
02811 cpl_propertylist * plist = NULL;
02812 cpl_propertylist* pDETlist = NULL;
02813
02814 mode = detmon_lg_config.collapse ?
02815 mode | IRPLIB_GAIN_COLLAPSE | IRPLIB_LIN_COLLAPSE:
02816 mode | IRPLIB_GAIN_NO_COLLAPSE | IRPLIB_LIN_NO_COLLAPSE;
02817 mode = detmon_lg_config.pix2pix ?
02818 mode | IRPLIB_LIN_PIX2PIX : mode;
02819 mode = opt_nir ?
02820 mode | IRPLIB_GAIN_NIR | IRPLIB_LIN_NIR :
02821 mode | IRPLIB_GAIN_OPT | IRPLIB_LIN_OPT ;
02822
02823
02824
02825 skip_if(irplib_detmon_pair_extract_next(set_on, index_on, next_on, exptime_on, &pair_on, detmon_lg_config.tolerance));
02826 current_dit = exptime_on[*next_on - 1];
02827
02828
02829 ons = detmon_lg_config.load_fset_wrp(pair_on, CPL_TYPE_FLOAT, whichext);
02830 skip_if(ons == NULL);
02831 cpl_msg_debug(cpl_func, "Loaded ON images: %d, exptime[%f]",cpl_imagelist_get_size(ons), current_dit );
02832 if(cpl_imagelist_get_size(ons) != 2)
02833 {
02834 cpl_msg_error(cpl_func, "cannot take ON pair, number of images[%d]", cpl_imagelist_get_size(ons));
02835 skip_if(TRUE);
02836 }
02837 if(detmon_lg_config.filter > 0)
02838 {
02839 double med1 =
02840 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
02841 detmon_lg_config.llx,
02842 detmon_lg_config.lly,
02843 detmon_lg_config.urx,
02844 detmon_lg_config.ury);
02845 double med2 =
02846 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
02847 detmon_lg_config.llx,
02848 detmon_lg_config.lly,
02849 detmon_lg_config.urx,
02850 detmon_lg_config.ury);
02851 if ( med1 > (double)detmon_lg_config.filter ||
02852 med2 > (double)detmon_lg_config.filter)
02853 {
02854 follow = CPL_FALSE;
02855 cpl_table_select_row(gain_table, dit_nb);
02856 cpl_table_select_row(linear_table, dit_nb);
02857 (*dit_nskip)++;
02858 cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
02859 "will not be taken into account for computation "
02860 "as they are above --filter threshold", dit_nb);
02861 }
02862 }
02863
02864 if (follow || detmon_lg_config.filter < 0)
02865 {
02866
02867
02868
02869
02870
02871
02872 if(!detmon_lg_config.collapse)
02873 {
02874 if (!strcmp(detmon_lg_config.method, "MED") ||
02875 cpl_frameset_get_size(set_on) == cpl_frameset_get_size(set_off))
02876 {
02877 skip_if(irplib_detmon_pair_extract_next(set_off, index_off, next_off, exptime_off, &pair_off, detmon_lg_config.tolerance));
02878 }
02879 else
02880 {
02881 skip_if(irplib_detmon_single_extract_next(set_off, index_off, next_off, exptime_off, &pair_off));
02882 }
02883
02884 cpl_msg_debug(cpl_func, "Load the OFF images, ext[%d], exptime[%f]", whichext, exptime_off[*next_off - 1]);
02885 offs = detmon_lg_config.load_fset_wrp(pair_off, CPL_TYPE_FLOAT, whichext);
02886
02887 skip_if(offs == NULL);
02888 skip_if(cpl_error_get_code());
02889 } else
02890 {
02891
02892
02893
02894
02895 cpl_image * collapse;
02896 masterl = cpl_imagelist_load_frameset(set_off, CPL_TYPE_FLOAT,
02897 1, whichext);
02898 skip_if(masterl == NULL);
02899 skip_if(cpl_error_get_code());
02900
02901 collapse = cpl_imagelist_collapse_create(masterl);
02902 skip_if(collapse == NULL);
02903 skip_if(cpl_imagelist_set(masterl, collapse, 0));
02904
02905
02906 offs = (cpl_imagelist *)masterl;
02907 }
02908
02909
02910 if(detmon_lg_config.rescale)
02911 {
02912 skip_if(irplib_detmon_lg_rescale(ons));
02913 if (!detmon_lg_config.collapse &&
02914 !strcmp(detmon_lg_config.method, "MED"))
02915 skip_if(irplib_detmon_lg_rescale(offs));
02916 }
02917
02918
02919 filename =
02920 cpl_frame_get_filename(cpl_frameset_get_first_const(pair_on));
02921 skip_if ((plist = cpl_propertylist_load(filename, 0)) == NULL);
02922
02923 if (plist)
02924 {
02925 pDETlist = cpl_propertylist_new();
02926 cpl_propertylist_copy_property_regexp(pDETlist, plist, "DET[0-9]* WIN[0-9]* UIT[0-9]*",0);
02927 if (dit_nb == 0)
02928 {
02929 irplib_table_create_column(gain_table, pDETlist);
02930 irplib_table_create_column(linear_table, pDETlist);
02931 }
02932 }
02933 if(opt_nir == NIR) {
02934 c_dit = irplib_pfits_get_dit(plist);
02935 c_ndit = irplib_pfits_get_ndit(plist);
02936 } else {
02937 c_dit = irplib_pfits_get_exptime(plist);
02938 c_ndit=1;
02939 }
02940
02941
02942
02943
02944
02945
02946
02947
02948 if(detmon_lg_config.collapse) {
02949 offs = (cpl_imagelist *) opt_offs;
02950 }
02951
02952 cpl_msg_info(cpl_func, "Computing GAIN for EXPTIME value nb %d",
02953 dit_nb + 1);
02954
02955
02956 if(cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE && dit_nb == 0)
02957 {
02958 cpl_table_erase_column(gain_table, "MEAN_OFF1");
02959 cpl_table_erase_column(gain_table, "MEAN_OFF2");
02960 cpl_table_erase_column(gain_table, "SIG_OFF_DIF");
02961 cpl_table_erase_column(gain_table, "GAIN");
02962 cpl_table_erase_column(gain_table, "GAIN_CORR");
02963 cpl_table_new_column(gain_table, "MEAN_OFF", CPL_TYPE_DOUBLE);
02964 }
02965
02966 skip_if(irplib_detmon_gain_table_fill_row(gain_table,
02967 c_dit,c_ndit,
02968 autocorr_images,
02969 diff_flats, ons, offs,
02970 detmon_lg_config.kappa,
02971 detmon_lg_config.niter,
02972 detmon_lg_config.llx,
02973 detmon_lg_config.lly,
02974 detmon_lg_config.urx,
02975 detmon_lg_config.ury,
02976 detmon_lg_config.m,
02977 detmon_lg_config.n,
02978 detmon_lg_config.saturation_limit,
02979 dit_nb, mode, rows_affected));
02980
02981
02982 if (*rows_affected)
02983 {
02984
02985 skip_if(irplib_fill_table_DETWINUIT(gain_table, pDETlist, dit_nb));
02986
02987 cpl_msg_info(cpl_func, "Linearity reduction for nb %d",
02988 dit_nb + 1);
02989 skip_if(irplib_detmon_lin_table_fill_row(linear_table, c_dit,
02990 linearity_inputs, ons, offs,
02991 detmon_lg_config.llx,
02992 detmon_lg_config.lly,
02993 detmon_lg_config.urx,
02994 detmon_lg_config.ury,
02995 dit_nb, *dit_nskip, mode));
02996
02997 skip_if(irplib_fill_table_DETWINUIT(linear_table, pDETlist, dit_nb));
02998 }
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009 if(opt_nir == OPT &&
03010 *rows_affected != 0 ) {
03011 irplib_detmon_opt_contamination(ons, offs, mode, qclist);
03012 }
03013
03014 }
03015
03016 end_skip;
03017
03018 cpl_frameset_delete(pair_on);
03019 cpl_imagelist_delete(ons);
03020
03021 if(!detmon_lg_config.collapse ) {
03022 cpl_imagelist_delete(offs);
03023 }
03024
03025 if(!detmon_lg_config.collapse) {
03026 cpl_frameset_delete(pair_off);
03027 }
03028
03029 if(detmon_lg_config.collapse) {
03030 cpl_imagelist_delete(masterl);
03031 }
03032
03033 cpl_propertylist_delete(plist);
03034 cpl_propertylist_delete(pDETlist);
03035 return cpl_error_get_code();
03036 }
03037
03038
03044
03045 static cpl_error_code
03046 irplib_detmon_add_adl_column(cpl_table * table,
03047 cpl_boolean opt_nir)
03048 {
03049 cpl_error_code error;
03050 double mean_med_dit;
03051 double *dits;
03052
03053 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
03054
03055 mean_med_dit = cpl_table_get_column_mean(table, "MED_DIT");
03056 if (opt_nir == OPT)
03057 dits = cpl_table_get_data_double(table, "EXPTIME");
03058 else
03059 dits = cpl_table_get_data_double(table, "DIT");
03060
03061 error = cpl_table_copy_data_double(table, "ADL", dits);
03062 cpl_ensure_code(!error, error);
03063 error = cpl_table_multiply_scalar(table, "ADL", mean_med_dit);
03064 cpl_ensure_code(!error, error);
03065
03066 return cpl_error_get_code();
03067 }
03068
03069
03077
03078 static cpl_error_code
03079 irplib_detmon_lg_reduce_init(cpl_table * gain_table,
03080 cpl_table * linear_table,
03081 cpl_imagelist ** linearity_inputs,
03082 const cpl_boolean opt_nir)
03083 {
03084 skip_if(irplib_detmon_gain_table_create(gain_table, opt_nir));
03085 skip_if(irplib_detmon_lin_table_create(linear_table, opt_nir));
03086
03087 if(detmon_lg_config.pix2pix) {
03088 *linearity_inputs = cpl_imagelist_new();
03089 skip_if(*linearity_inputs == NULL);
03090 }
03091
03092 end_skip;
03093
03094 return cpl_error_get_code();
03095 }
03096
03097
03103
03104 static double
03105 irplib_pfits_get_dit(const cpl_propertylist * plist)
03106 {
03107 return irplib_pfits_get_prop_double(plist, "ESO DET DIT");
03108 }
03109
03110
03116
03117 static double
03118 irplib_pfits_get_dit_opt(const cpl_propertylist * plist)
03119 {
03120 return irplib_pfits_get_prop_double(plist, "ESO DET WIN1 UIT1");
03121 }
03122
03123 static double irplib_pfits_get_prop_double(const cpl_propertylist * plist, const char* prop_name)
03124 {
03125 double dit;
03126 dit = cpl_propertylist_get_double(plist, prop_name);
03127 if(cpl_error_get_code() != CPL_ERROR_NONE)
03128 {
03129 cpl_msg_error(cpl_func, "Cannot read property '%s', err[%s]",prop_name, cpl_error_get_where());
03130 }
03131 return dit;
03132 }
03133
03165
03166 static cpl_error_code
03167 irplib_detmon_gain_table_fill_row(cpl_table * gain_table,
03168 double c_dit,int c_ndit,
03169 cpl_imagelist * autocorr_images,
03170 cpl_imagelist * diff_flats,
03171 const cpl_imagelist * ons,
03172 const cpl_imagelist * offs,
03173 double kappa, int nclip,
03174 int llx, int lly, int urx, int ury,
03175 int m, int n,
03176 double saturation_limit,
03177 const int pos, unsigned mode, int* rows_affected)
03178 {
03179 const cpl_image *image;
03180 double std = 0;
03181 cpl_image *on_dif = NULL;
03182 cpl_image *off_dif = NULL;
03183 double avg_on1, avg_on2;
03184 double avg_off1, avg_off2;
03185 double avg_on_dif, sig_on_dif;
03186 double avg_off_dif, sig_off_dif;
03187 double double_adu, autocorr, gain, gain_corr;
03188 double sigma, sigma_corr;
03189
03190 cpl_table_set(gain_table, "FLAG", pos, 1);
03191 if (mode & IRPLIB_GAIN_NIR)
03192 {
03193 cpl_table_set(gain_table, "DIT", pos, c_dit);
03194 cpl_table_set(gain_table, "NDIT", pos, c_ndit);
03195 } else if (mode & IRPLIB_GAIN_OPT)
03196 {
03197 cpl_table_set(gain_table, "EXPTIME", pos, c_dit);
03198 } else
03199 {
03200 cpl_msg_error(cpl_func, "Mandatory mode (OPT or NIR) not provided");
03201 skip_if(1);
03202 }
03203 if(*rows_affected == 0)
03204 {
03205 cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
03206 cpl_table_set(gain_table, "FLAG", pos, 0);
03207 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03208 {
03209 autocorr = -1;
03210 if (diff_flats)
03211 {
03212 irplib_detmon_lg_add_empty_image(diff_flats, pos);
03213 }
03214 if (autocorr_images)
03215 {
03216 irplib_detmon_lg_add_empty_image(autocorr_images, pos);
03217 }
03218 }
03219 return cpl_error_get_code();
03220 }
03221 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
03222 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
03223 nclip, 1e-5, &avg_on1, &std));
03224 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
03225 skip_if(irplib_ksigma_clip(image, llx, lly, urx, ury, kappa,
03226 nclip, 1e-5, &avg_on2, &std));
03227
03228 if ((avg_on1 > saturation_limit) || (avg_on2 > saturation_limit))
03229 {
03230 cpl_msg_warning(cpl_func, "Average saturation is above the limit, the frames would not be taken into calculation");
03231 cpl_msg_warning(cpl_func, "saturation levels [%f ; %f], limit [%f]", avg_on1, avg_on2, saturation_limit);
03232 cpl_msg_info(cpl_func, "skip the frame #%d", pos + 1);
03233 cpl_table_set(gain_table, "FLAG", pos, 0);
03234 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03235 {
03236 autocorr = -1;
03237 if (diff_flats)
03238 {
03239 irplib_detmon_lg_add_empty_image(diff_flats, pos);
03240 }
03241 if (autocorr_images)
03242 {
03243 irplib_detmon_lg_add_empty_image(autocorr_images, pos);
03244 }
03245 }
03246 *rows_affected = 0;
03247 }
03248 else
03249 {
03250 *rows_affected = 1;
03251 skip_if(cpl_table_set_double(gain_table, "MEAN_ON1", pos, avg_on1));
03252 skip_if(cpl_table_set_double(gain_table, "MEAN_ON2", pos, avg_on2));
03253 on_dif =
03254 cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
03255 cpl_imagelist_get_const(ons, 1));
03256 skip_if(on_dif == NULL);
03257 skip_if(irplib_ksigma_clip(on_dif, llx, lly, urx, ury, kappa,
03258 nclip, 1e-5,
03259 &avg_on_dif, &sig_on_dif));
03260 skip_if(cpl_table_set_double(gain_table, "SIG_ON_DIF", pos, sig_on_dif));
03261
03262 if(mode & IRPLIB_GAIN_WITH_AUTOCORR)
03263 {
03264 if (diff_flats)
03265 {
03266 cpl_image * diff = cpl_image_duplicate(on_dif);
03267 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
03268 }
03269 if (autocorr_images)
03270 {
03271 cpl_image * corr = NULL;
03272 autocorr = irplib_detmon_autocorr_factor(on_dif, &corr, m, n);
03273 if(corr)
03274 {
03275 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
03276 }
03277 else
03278 {
03279 irplib_detmon_lg_add_empty_image(autocorr_images, pos);
03280 }
03281 } else
03282 {
03283 autocorr = irplib_detmon_autocorr_factor(on_dif, NULL, m, n);
03284 }
03285 autocorr = isnan(autocorr) ? 1.0 : autocorr;
03286 } else
03287 {
03288 autocorr = 1.0;
03289 }
03290
03291 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
03292 {
03293
03294 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
03295 llx, lly, urx, ury, kappa, nclip,
03296 1e-5, &avg_off1, &std));
03297 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF", pos, avg_off1));
03298
03299 } else if (mode & IRPLIB_GAIN_NO_COLLAPSE ||
03300 ( pos == 0 && mode & IRPLIB_GAIN_COLLAPSE )) {
03301 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 0),
03302 llx, lly, urx, ury, kappa, nclip,
03303 1e-5, &avg_off1, &std));
03304 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
03305 skip_if(irplib_ksigma_clip(cpl_imagelist_get_const(offs, 1),
03306 llx, lly, urx, ury, kappa, nclip,
03307 1e-5, &avg_off2, &std));
03308 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
03309 off_dif =
03310 cpl_image_subtract_create(cpl_imagelist_get_const(offs, 0),
03311 cpl_imagelist_get_const(offs, 1));
03312 skip_if(off_dif == NULL);
03313 skip_if(irplib_ksigma_clip(off_dif, llx, lly, urx, ury,
03314 kappa, nclip, 1e-5,
03315 &avg_off_dif, &sig_off_dif));
03316 skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
03317 pos, sig_off_dif));
03318 } else if (pos > 0 && mode & IRPLIB_GAIN_COLLAPSE)
03319 {
03320 int status;
03321 avg_off1 = cpl_table_get_double(gain_table, "MEAN_OFF1", 0, &status);
03322 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
03323 avg_off2 = cpl_table_get_double(gain_table, "MEAN_OFF2", 0, &status);
03324 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
03325 sig_off_dif = cpl_table_get_double(gain_table, "SIG_OFF_DIF",
03326 0, &status);
03327 skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
03328 pos, sig_off_dif));
03329 }
03330
03331 if (cpl_imagelist_get_size(offs) == 1 && mode & IRPLIB_GAIN_NO_COLLAPSE)
03332 {
03333 double_adu = (avg_on1 + avg_on2) - 2 * avg_off1;
03334 }
03335 else
03336 {
03337 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
03338
03339 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
03340
03341 sigma_corr = autocorr * sigma;
03342
03343 gain = double_adu / (c_ndit * sigma);
03344
03345 gain_corr = double_adu / (c_dit*sigma_corr);
03346
03347 skip_if(cpl_table_set_double(gain_table, "GAIN", pos, gain));
03348 skip_if(cpl_table_set_double(gain_table, "GAIN_CORR", pos, gain_corr));
03349 }
03350
03351 skip_if(cpl_table_set_double(gain_table, "AUTOCORR", pos, autocorr));
03352 skip_if(cpl_table_set_double(gain_table, "ADU", pos, double_adu / 2));
03353
03354
03355 skip_if(cpl_table_set_double(gain_table, "Y_FIT",
03356 pos,
03357 c_ndit* sig_on_dif * sig_on_dif));
03358 skip_if(cpl_table_set_double(gain_table, "Y_FIT_CORR",
03359 pos,
03360 c_ndit * sig_on_dif * sig_on_dif));
03361 skip_if(cpl_table_set_double(gain_table, "X_FIT", pos, double_adu));
03362 skip_if(cpl_table_set_double(gain_table, "X_FIT_CORR",
03363 pos, double_adu / autocorr));
03364 }
03365 end_skip;
03366
03367 cpl_image_delete(on_dif);
03368 cpl_image_delete(off_dif);
03369
03370 return cpl_error_get_code();
03371 }
03372
03373
03380
03381
03382 static cpl_image *
03383 irplib_detmon_bpixs(const cpl_imagelist * coeffs,
03384 cpl_boolean bpmbin,
03385 const double kappa,
03386 int *nbpixs)
03387 {
03388 int size;
03389 int i;
03390 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
03391 cpl_stats *stats;
03392 double cur_mean;
03393 double cur_stdev;
03394 double lo_cut;
03395 double hi_cut;
03396 cpl_mask *cur_mask;
03397 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
03398 cpl_image_get_size_y(first));
03399 cpl_image *cur_image = NULL;
03400 cpl_image *bpm = NULL;
03401 double p;
03402
03403 size = cpl_imagelist_get_size(coeffs);
03404
03405 if(!bpmbin) {
03406 bpm = cpl_image_new(cpl_image_get_size_x(first),
03407 cpl_image_get_size_y(first),
03408 CPL_TYPE_INT);
03409 }
03410
03411
03412 for(i = 0; i < size; i++) {
03413 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
03414
03415 stats = cpl_stats_new_from_image(cur_coeff,
03416 CPL_STATS_MEAN | CPL_STATS_STDEV);
03417 cur_mean = cpl_stats_get_mean(stats);
03418 cur_stdev = cpl_stats_get_stdev(stats);
03419
03420 lo_cut = cur_mean - kappa * cur_stdev;
03421 hi_cut = cur_mean + kappa * cur_stdev;
03422
03423 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
03424 cpl_mask_not(cur_mask);
03425
03426 if(!bpmbin) {
03427 cur_image = cpl_image_new_from_mask(cur_mask);
03428 p = pow(2, i);
03429 cpl_image_power(cur_image, p);
03430 cpl_image_add(bpm, cur_image);
03431 cpl_image_delete(cur_image);
03432 }
03433
03434 cpl_mask_or(mask, cur_mask);
03435
03436 cpl_mask_delete(cur_mask);
03437 cpl_stats_delete(stats);
03438 }
03439
03440 if(bpmbin) {
03441 bpm = cpl_image_new_from_mask(mask);
03442 }
03443
03444 *nbpixs += cpl_mask_count(mask);
03445
03446 cpl_mask_delete(mask);
03447
03448 return bpm;
03449 }
03450
03451
03463
03464
03465 static double
03466 irplib_detmon_autocorr_factor(const cpl_image * image,
03467 cpl_image ** autocorr_image, int m, int n)
03468 {
03469 cpl_image * mycorr_image = NULL;
03470 double autocorr = 0;
03471 cpl_error_code err = CPL_ERROR_NONE;
03472
03473 mycorr_image = irplib_detmon_image_correlate(image, image, m, n);
03474 err=cpl_error_get_code();
03475 if (err == CPL_ERROR_UNSUPPORTED_MODE)
03476 {
03477 cpl_msg_warning(cpl_func, "FFTW is not supported by CPL, autocorrelation "
03478 "would be computed using internal implementation");
03479 cpl_error_reset();
03480 if (mycorr_image)
03481 cpl_image_delete(mycorr_image);
03482 mycorr_image = irplib_detmon_autocorrelate(image, m, n);
03483 }
03484 if(mycorr_image == NULL) {
03485 return -1;
03486 }
03487
03488 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
03489
03490 autocorr = cpl_image_get_flux(mycorr_image);
03491
03492 if (autocorr_image) *autocorr_image = mycorr_image;
03493 else cpl_image_delete(mycorr_image);
03494
03495 return autocorr;
03496 }
03497
03498
03529
03530 static cpl_error_code
03531 irplib_detmon_lg_save(const cpl_parameterlist * parlist,
03532 cpl_frameset * frameset,
03533 const char *recipe_name,
03534 const char *pipeline_name,
03535 const char *pafregexp,
03536 const cpl_propertylist * pro_lintbl,
03537 const cpl_propertylist * pro_gaintbl,
03538 const cpl_propertylist * pro_coeffscube,
03539 const cpl_propertylist * pro_bpm,
03540 const cpl_propertylist * pro_corr,
03541 const cpl_propertylist * pro_diff,
03542 const char *package,
03543 cpl_imagelist * coeffs,
03544 cpl_table * gain_table,
03545 cpl_table * linear_table,
03546 cpl_image * bpms,
03547 cpl_imagelist * autocorr_images,
03548 cpl_imagelist * diff_flats,
03549 cpl_propertylist * gaint_qclist,
03550 cpl_propertylist * lint_qclist,
03551 cpl_propertylist * linc_qclist,
03552 cpl_propertylist * bpm_qclist,
03553 const int flag_sets,
03554 const int which_set,
03555 const cpl_frameset * usedframes,
03556 int whichext)
03557 {
03558
03559 cpl_frame *ref_frame;
03560 cpl_propertylist *plist = NULL;
03561 cpl_propertylist *mainplist = NULL;
03562 char *name_o = NULL;
03563 int nb_images;
03564 int i;
03565 cpl_error_code error;
03566 cpl_propertylist * xplist = NULL;
03567 cpl_propertylist * gaint_paflist = NULL;
03568 cpl_propertylist * lint_paflist = NULL;
03569 cpl_propertylist * linc_paflist = NULL;
03570 cpl_propertylist * bpm_paflist = NULL;
03571
03572 cpl_propertylist * mypro_lintbl =
03573 cpl_propertylist_duplicate(pro_lintbl);
03574 cpl_propertylist * mypro_gaintbl =
03575 cpl_propertylist_duplicate(pro_gaintbl);
03576 cpl_propertylist * mypro_coeffscube =
03577 cpl_propertylist_duplicate(pro_coeffscube);
03578 cpl_propertylist * mypro_bpm =
03579 cpl_propertylist_duplicate(pro_bpm);
03580 cpl_propertylist * mypro_corr =
03581 cpl_propertylist_duplicate(pro_corr);
03582 cpl_propertylist * mypro_diff =
03583 cpl_propertylist_duplicate(pro_diff);
03584
03585 const char * procatg_lintbl =
03586 cpl_propertylist_get_string(mypro_lintbl, CPL_DFS_PRO_CATG);
03587
03588 const char * procatg_gaintbl =
03589 cpl_propertylist_get_string(mypro_gaintbl, CPL_DFS_PRO_CATG);
03590
03591 const char * procatg_coeffscube =
03592 cpl_propertylist_get_string(mypro_coeffscube, CPL_DFS_PRO_CATG);
03593 const char * procatg_bpm =
03594 cpl_propertylist_get_string(mypro_bpm, CPL_DFS_PRO_CATG);
03595
03596
03597 if (detmon_lg_config.exts < 0) {
03598 const char * filename =
03599 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
03600
03601
03602 xplist = cpl_propertylist_load_regexp(filename, whichext,
03603 "ESO DET|EXTNAME", 0);
03604
03605
03606 cpl_propertylist_erase_regexp(xplist, "DET CHIP LIVE", 0) ;
03607
03608
03609 skip_if(cpl_propertylist_append(gaint_qclist, xplist));
03610 skip_if(cpl_propertylist_append(lint_qclist, xplist));
03611 skip_if(cpl_propertylist_append(linc_qclist, xplist));
03612 skip_if(cpl_propertylist_append(bpm_qclist, xplist));
03613 }
03614
03615
03616
03617
03618 ref_frame = cpl_frameset_get_first(frameset);
03619
03620 skip_if((mainplist =
03621 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03622 0)) == NULL);
03623
03624
03625
03626
03627
03628
03629 if(!flag_sets) {
03630 name_o = cpl_sprintf("%s_linearity_table.fits", recipe_name);
03631 assert(name_o != NULL);
03632 } else {
03633 name_o =
03634 cpl_sprintf("%s_linearity_table_set%02d.fits", recipe_name,
03635 which_set);
03636 assert(name_o != NULL);
03637 }
03638
03639 if (detmon_lg_config.exts >= 0) {
03640
03641 cpl_propertylist_append(mypro_lintbl, lint_qclist);
03642
03643 skip_if(cpl_dfs_save_table(frameset, NULL,parlist, usedframes, NULL,linear_table,
03644 NULL, recipe_name,
03645 mypro_lintbl, NULL, package, name_o));
03646
03647 } else {
03648 if(whichext == 1) {
03649
03650 skip_if(cpl_dfs_save_table(frameset,NULL, parlist, usedframes, NULL, linear_table,
03651 lint_qclist, recipe_name, mypro_lintbl,
03652 NULL, package, name_o));
03653 } else {
03654 skip_if(cpl_table_save(linear_table, NULL, lint_qclist, name_o,
03655 CPL_IO_EXTEND));
03656 }
03657 }
03658
03659
03660 if(name_o!=NULL) {
03661 cpl_free(name_o);
03662 name_o=NULL;
03663 }
03664
03665
03666
03667
03668
03669
03670 if(!flag_sets) {
03671 name_o = cpl_sprintf("%s_gain_table.fits", recipe_name);
03672 assert(name_o != NULL);
03673 } else {
03674 name_o =
03675 cpl_sprintf("%s_gain_table_set%02d.fits", recipe_name,
03676 which_set);
03677 assert(name_o != NULL);
03678 }
03679
03680 if (detmon_lg_config.exts >= 0) {
03681
03682 cpl_propertylist_append(mypro_gaintbl, gaint_qclist);
03683
03684 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL,gain_table,
03685 NULL, recipe_name, mypro_gaintbl,
03686 NULL, package, name_o));
03687 } else {
03688 if(whichext == 1) {
03689
03690 skip_if(cpl_dfs_save_table(frameset, NULL, parlist, usedframes, NULL, gain_table,
03691 gaint_qclist, recipe_name, mypro_gaintbl,
03692 NULL, package, name_o));
03693 } else {
03694 skip_if(cpl_table_save(gain_table, NULL, gaint_qclist, name_o,
03695 CPL_IO_EXTEND));
03696 }
03697 }
03698
03699
03700 if(name_o!=NULL) {
03701 cpl_free(name_o);
03702 name_o=NULL;
03703 }
03704
03705 if(detmon_lg_config.pix2pix) {
03706
03707
03708
03709
03710
03711
03712 if(!flag_sets) {
03713 name_o =
03714 cpl_sprintf("%s_coeffs_cube.fits", recipe_name);
03715 assert(name_o != NULL);
03716 } else {
03717 name_o =
03718 cpl_sprintf("%s_coeffs_cube_set%02d.fits",
03719 recipe_name, which_set);
03720 assert(name_o != NULL);
03721 }
03722
03723
03724 if(detmon_lg_config.exts >= 0) {
03725 cpl_propertylist_append(mypro_coeffscube, linc_qclist);
03726 skip_if(irplib_detmon_lg_dfs_save_imagelist
03727 (frameset, parlist, usedframes, coeffs,
03728 recipe_name, mypro_coeffscube, package,
03729 name_o));
03730 } else {
03731 if(whichext == 1) {
03732 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
03733 NULL, NULL,
03734 CPL_BPP_IEEE_FLOAT, recipe_name,
03735 mypro_coeffscube, NULL,
03736 package, name_o));
03737 skip_if(cpl_imagelist_save(coeffs,
03738 name_o, CPL_BPP_IEEE_FLOAT, linc_qclist,
03739 CPL_IO_EXTEND));
03740 } else {
03741 skip_if(cpl_imagelist_save(coeffs,
03742 name_o, CPL_BPP_IEEE_FLOAT, linc_qclist,
03743 CPL_IO_EXTEND));
03744 }
03745 }
03746 if(name_o!=NULL) {
03747 cpl_free(name_o);
03748 name_o=NULL;
03749 }
03750
03751
03752
03753
03754
03755
03756 if(!flag_sets) {
03757 name_o = cpl_sprintf("%s_bpm.fits", recipe_name);
03758 assert(name_o != NULL);
03759 } else {
03760 name_o =
03761 cpl_sprintf("%s_bpm_set%02d.fits", recipe_name, which_set);
03762 assert(name_o != NULL);
03763 }
03764
03765
03766 if(detmon_lg_config.exts >= 0) {
03767 cpl_propertylist_append(mypro_bpm, bpm_qclist);
03768
03769 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL, bpms,
03770 CPL_BPP_IEEE_FLOAT, recipe_name,
03771 mypro_bpm, NULL, package,
03772 name_o));
03773 } else {
03774 if (whichext == 1) {
03775 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes,NULL, NULL,
03776 CPL_BPP_IEEE_FLOAT, recipe_name,
03777 mypro_bpm, NULL, package,
03778 name_o));
03779 skip_if(cpl_image_save(bpms, name_o, CPL_BPP_IEEE_FLOAT,
03780 bpm_qclist, CPL_IO_EXTEND));
03781 } else {
03782 skip_if(cpl_image_save(bpms, name_o, CPL_BPP_IEEE_FLOAT,
03783 bpm_qclist, CPL_IO_EXTEND));
03784 }
03785 }
03786
03787 if(name_o!=NULL) {
03788 cpl_free(name_o);
03789 name_o=NULL;
03790 }
03791
03792 }
03793
03794 if(detmon_lg_config.intermediate) {
03795
03796
03797
03798 nb_images = cpl_imagelist_get_size(autocorr_images);
03799 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
03800 for(i = 0; i < nb_images; i++) {
03801 cpl_propertylist* plist = cpl_propertylist_duplicate(mypro_corr);
03802 int inull = 0;
03803 cpl_array* pnames = cpl_table_get_column_names(linear_table);
03804 double ddit = 0;
03805 if(i < cpl_table_get_nrow(linear_table))
03806 {
03807 ddit = cpl_table_get_double(linear_table,
03808 cpl_array_get_data_string_const(pnames)[0], i, &inull);
03809 }
03810 cpl_array_delete(pnames);
03811 cpl_propertylist_append_double(plist, "ESO DET DIT", ddit);
03812
03813 if(!flag_sets) {
03814 name_o =
03815 cpl_sprintf("%s_autocorr_%d.fits", recipe_name, i);
03816 assert(name_o != NULL);
03817 } else {
03818 name_o =
03819 cpl_sprintf("%s_autocorr_%02d_set%02d.fits",
03820 recipe_name, i, which_set);
03821 assert(name_o != NULL);
03822 }
03823
03824
03825
03826 if(detmon_lg_config.exts >= 0) {
03827
03828 skip_if(cpl_dfs_save_image
03829 (frameset, NULL, parlist, usedframes, NULL,
03830 cpl_imagelist_get(autocorr_images, i), CPL_BPP_IEEE_FLOAT,
03831 recipe_name, plist, NULL, package,
03832 name_o));
03833
03834 } else {
03835 if(whichext == 1) {
03836 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,NULL,
03837 CPL_BPP_IEEE_FLOAT, recipe_name,
03838 plist, NULL,
03839 package, name_o));
03840 skip_if(cpl_image_save(cpl_imagelist_get(autocorr_images, i),
03841 name_o, CPL_BPP_IEEE_FLOAT, NULL,
03842 CPL_IO_EXTEND));
03843 } else {
03844 skip_if(cpl_image_save(cpl_imagelist_get(autocorr_images, i),
03845 name_o, CPL_BPP_IEEE_FLOAT, NULL,
03846 CPL_IO_EXTEND));
03847 }
03848 }
03849 if(name_o!=NULL) {
03850 cpl_free(name_o);
03851 name_o=NULL;
03852 }
03853 cpl_propertylist_delete (plist);
03854 }
03855
03856
03857
03858
03859
03860 for(i = 0; i < nb_images; i++) {
03861 cpl_propertylist* plist = cpl_propertylist_duplicate(mypro_diff);
03862 int inull = 0;
03863 cpl_array* pnames = cpl_table_get_column_names(linear_table);
03864 double ddit = 0;
03865 if(i < cpl_table_get_nrow(linear_table))
03866 {
03867 ddit = cpl_table_get_double(linear_table,
03868 cpl_array_get_data_string_const(pnames)[0], i, &inull);
03869 }
03870 cpl_array_delete(pnames);
03871 cpl_propertylist_append_double(plist, "ESO DET DIT", ddit);
03872
03873 if(!flag_sets) {
03874 name_o =
03875 cpl_sprintf("%s_diff_flat_%d.fits", recipe_name, i);
03876 assert(name_o != NULL);
03877 } else {
03878 name_o =
03879 cpl_sprintf("%s_diff_flat_%d_set%02d.fits",
03880 recipe_name, i, which_set);
03881 assert(name_o != NULL);
03882 }
03883
03884
03885
03886 if(detmon_lg_config.exts >= 0) {
03887 skip_if(cpl_dfs_save_image
03888 (frameset, NULL, parlist, usedframes, NULL,
03889 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
03890 recipe_name, plist, NULL, package,
03891 name_o));
03892 } else {
03893 if(whichext == 1) {
03894 skip_if(cpl_dfs_save_image(frameset, NULL, parlist, usedframes, NULL,NULL,
03895 CPL_BPP_IEEE_FLOAT, recipe_name,
03896 mypro_diff, NULL,
03897 package, name_o));
03898 skip_if(cpl_image_save(cpl_imagelist_get(diff_flats, i),
03899 name_o, CPL_BPP_IEEE_FLOAT, NULL,
03900 CPL_IO_EXTEND));
03901 } else {
03902 skip_if(cpl_image_save(cpl_imagelist_get(diff_flats, i),
03903 name_o, CPL_BPP_IEEE_FLOAT, NULL,
03904 CPL_IO_EXTEND));
03905 }
03906
03907 }
03908 if(name_o!=NULL) {
03909 cpl_free(name_o);
03910 name_o=NULL;
03911 }
03912 cpl_propertylist_delete(plist);
03913 }
03914 if(name_o!=NULL) {
03915 cpl_free(name_o);
03916 name_o=NULL;
03917 }
03918
03919
03920 }
03921
03922
03923
03924
03925
03926 gaint_paflist = cpl_propertylist_new();
03927 lint_paflist = cpl_propertylist_new();
03928
03929 skip_if(cpl_propertylist_append_string(gaint_paflist, CPL_DFS_PRO_CATG,
03930 procatg_gaintbl));
03931 skip_if(cpl_propertylist_append_string(lint_paflist, CPL_DFS_PRO_CATG,
03932 procatg_lintbl));
03933
03934 if(detmon_lg_config.pix2pix) {
03935 linc_paflist = cpl_propertylist_new();
03936 bpm_paflist = cpl_propertylist_new();
03937
03938 skip_if(cpl_propertylist_append_string(linc_paflist, CPL_DFS_PRO_CATG,
03939 procatg_coeffscube));
03940 skip_if(cpl_propertylist_append_string(bpm_paflist, CPL_DFS_PRO_CATG,
03941 procatg_bpm));
03942
03943 }
03944
03945
03946 if(detmon_lg_config.exts >= 0) {
03947 skip_if((plist =
03948 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03949 detmon_lg_config.exts)) == NULL);
03950
03951 if(!flag_sets) {
03952 name_o = cpl_sprintf("%s_qc01.paf", detmon_lg_config.pafname);
03953 assert(name_o != NULL);
03954 } else {
03955 name_o = cpl_sprintf("%s_qc01_set%02d.paf",
03956 detmon_lg_config.pafname, which_set);
03957 assert(name_o != NULL);
03958 }
03959 } else {
03960 skip_if((plist =
03961 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03962 whichext)) == NULL);
03963
03964
03965 if(!flag_sets) {
03966 name_o = cpl_sprintf("%s_qc01_ext%02d.paf",
03967 detmon_lg_config.pafname, whichext);
03968 assert(name_o != NULL);
03969 } else {
03970 name_o = cpl_sprintf("%s_qc01_set%02d_ext%02d.paf",
03971 detmon_lg_config.pafname,
03972 which_set, whichext);
03973 assert(name_o != NULL);
03974 }
03975 }
03976
03977
03978 skip_if(cpl_propertylist_copy_property_regexp(gaint_paflist, plist,
03979 pafregexp, 0));
03980 skip_if(cpl_propertylist_copy_property_regexp(gaint_paflist, mainplist,
03981 pafregexp, 0));
03982
03983 if(plist!=NULL) {
03984 cpl_propertylist_delete(plist);
03985 plist=NULL;
03986 }
03987 skip_if(error = cpl_propertylist_append(gaint_paflist, gaint_qclist));
03988
03989
03990 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, gaint_paflist, name_o));
03991
03992 if(name_o!=NULL) {
03993 cpl_free(name_o);
03994 name_o=NULL;
03995 }
03996
03997
03998 if(detmon_lg_config.exts >= 0) {
03999 skip_if((plist =
04000 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04001 detmon_lg_config.exts)) == NULL);
04002
04003 if(!flag_sets) {
04004 name_o = cpl_sprintf("%s_qc02.paf", detmon_lg_config.pafname);
04005 assert(name_o != NULL);
04006 } else {
04007 name_o = cpl_sprintf("%s_qc02_set%02d.paf",
04008 detmon_lg_config.pafname, which_set);
04009 assert(name_o != NULL);
04010 }
04011 } else {
04012 skip_if((plist =
04013 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04014 whichext)) == NULL);
04015
04016
04017 if(!flag_sets) {
04018 name_o = cpl_sprintf("%s_qc02_ext%02d.paf",
04019 detmon_lg_config.pafname, whichext);
04020 assert(name_o != NULL);
04021 } else {
04022 name_o = cpl_sprintf("%s_qc02_set%02d_ext%02d.paf",
04023 detmon_lg_config.pafname,
04024 which_set, whichext);
04025 assert(name_o != NULL);
04026 }
04027 }
04028
04029
04030 skip_if(cpl_propertylist_copy_property_regexp(lint_paflist, plist,
04031 pafregexp, 0));
04032 skip_if(cpl_propertylist_copy_property_regexp(lint_paflist, mainplist,
04033 pafregexp, 0));
04034
04035 if(plist!=NULL) {
04036 cpl_propertylist_delete(plist);
04037 plist=NULL;
04038 }
04039
04040 skip_if(error = cpl_propertylist_append(lint_paflist, lint_qclist));
04041
04042
04043 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, lint_paflist, name_o));
04044
04045 if(name_o!=NULL) {
04046 cpl_free(name_o);
04047 name_o=NULL;
04048 }
04049
04050 if(detmon_lg_config.pix2pix) {
04051
04052
04053 if(detmon_lg_config.exts >= 0) {
04054 skip_if((plist =
04055 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04056 detmon_lg_config.exts)) == NULL);
04057
04058 if(!flag_sets) {
04059 name_o = cpl_sprintf("%s_qc03.paf", detmon_lg_config.pafname);
04060 assert(name_o != NULL);
04061 } else {
04062 name_o = cpl_sprintf("%s_qc03_set%02d.paf",
04063 detmon_lg_config.pafname, which_set);
04064 assert(name_o != NULL);
04065 }
04066 } else {
04067 skip_if((plist =
04068 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04069 whichext)) == NULL);
04070
04071
04072 if(!flag_sets) {
04073 name_o = cpl_sprintf("%s_qc03_ext%02d.paf",
04074 detmon_lg_config.pafname, whichext);
04075 assert(name_o != NULL);
04076 } else {
04077 name_o = cpl_sprintf("%s_qc03_set%02d_ext%02d.paf",
04078 detmon_lg_config.pafname,
04079 which_set, whichext);
04080 assert(name_o != NULL);
04081 }
04082 }
04083
04084
04085 skip_if(cpl_propertylist_copy_property_regexp(linc_paflist, plist,
04086 pafregexp, 0));
04087 skip_if(cpl_propertylist_copy_property_regexp(linc_paflist, mainplist,
04088 pafregexp, 0));
04089
04090 skip_if(error = cpl_propertylist_append(linc_paflist, linc_qclist));
04091
04092 if(plist!=NULL) {
04093 cpl_propertylist_delete(plist);
04094 plist=NULL;
04095 }
04096
04097
04098 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, linc_paflist, name_o));
04099
04100 if(name_o!=NULL) {
04101 cpl_free(name_o);
04102 name_o=NULL;
04103 }
04104
04105
04106 if(detmon_lg_config.exts >= 0) {
04107 skip_if((plist =
04108 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04109 detmon_lg_config.exts)) == NULL);
04110
04111 if(!flag_sets) {
04112 name_o = cpl_sprintf("%s_qc04.paf", detmon_lg_config.pafname);
04113 assert(name_o != NULL);
04114 } else {
04115 name_o = cpl_sprintf("%s_qc04_set%02d.paf",
04116 detmon_lg_config.pafname, which_set);
04117 assert(name_o != NULL);
04118 }
04119 } else {
04120 skip_if((plist =
04121 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
04122 whichext)) == NULL);
04123
04124
04125 if(!flag_sets) {
04126 name_o = cpl_sprintf("%s_qc04_ext%02d.paf",
04127 detmon_lg_config.pafname, whichext);
04128 assert(name_o != NULL);
04129 } else {
04130 name_o = cpl_sprintf("%s_qc04_set%02d_ext%02d.paf",
04131 detmon_lg_config.pafname,
04132 which_set, whichext);
04133 assert(name_o != NULL);
04134 }
04135 }
04136
04137
04138 skip_if(cpl_propertylist_copy_property_regexp(bpm_paflist, plist,
04139 pafregexp, 0));
04140 skip_if(cpl_propertylist_copy_property_regexp(bpm_paflist, mainplist,
04141 pafregexp, 0));
04142
04143 if(plist!=NULL) {
04144 cpl_propertylist_delete(plist);
04145 plist=NULL;
04146 }
04147
04148 skip_if(error = cpl_propertylist_append(bpm_paflist, bpm_qclist));
04149
04150
04151 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, bpm_paflist, name_o));
04152 if(name_o!=NULL) {
04153 cpl_free(name_o);
04154 name_o=NULL;
04155 }
04156 }
04157
04158 end_skip;
04159
04160 cpl_propertylist_delete(xplist);
04161
04162 cpl_propertylist_delete(gaint_paflist);
04163 cpl_propertylist_delete(lint_paflist);
04164 cpl_propertylist_delete(linc_paflist);
04165 cpl_propertylist_delete(bpm_paflist);
04166
04167
04168 if(plist!=NULL) {
04169 cpl_propertylist_delete(plist);
04170 plist=NULL;
04171 }
04172
04173 if(name_o!=NULL) {
04174 cpl_free(name_o);
04175 name_o=NULL;
04176 }
04177
04178 cpl_propertylist_delete(mainplist);
04179
04180 cpl_propertylist_delete(mypro_lintbl);
04181 cpl_propertylist_delete(mypro_gaintbl);
04182 cpl_propertylist_delete(mypro_coeffscube);
04183 cpl_propertylist_delete(mypro_bpm);
04184 cpl_propertylist_delete(mypro_corr);
04185 cpl_propertylist_delete(mypro_diff);
04186
04187 return cpl_error_get_code();
04188 }
04189
04190
04191
04199
04200 static cpl_error_code
04201 irplib_detmon_opt_contamination(const cpl_imagelist * ons,
04202 const cpl_imagelist * offs,
04203 unsigned mode,
04204 cpl_propertylist * qclist)
04205 {
04206
04207 double median[5] = {0, 0, 0, 0, 0};
04208
04209 cpl_image * dif1=NULL;
04210 cpl_image * dif2=NULL;
04211 cpl_image * dif_avg=NULL;
04212 char* kname=NULL;
04213 int offsize = cpl_imagelist_get_size(offs);
04214
04215
04216 dif1 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
04217 cpl_imagelist_get_const(offs, 0));
04218
04219 if (offsize == 1 || mode & IRPLIB_LIN_COLLAPSE)
04220 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
04221 cpl_imagelist_get_const(offs, 0));
04222 else if (mode & IRPLIB_LIN_NO_COLLAPSE)
04223 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
04224 cpl_imagelist_get_const(offs, 1));
04225
04226 dif_avg = cpl_image_average_create(dif1, dif2);
04227
04228 cpl_image_abs(dif_avg);
04229
04230 median[0] = cpl_image_get_median_window(dif_avg,
04231 detmon_lg_config.llx1,
04232 detmon_lg_config.lly1,
04233 detmon_lg_config.urx1,
04234 detmon_lg_config.ury1);
04235
04236 skip_if(0);
04237 kname = cpl_sprintf("%s%d", DETMON_QC_CONTAM,1);
04238
04239 if(cpl_propertylist_has(qclist,kname)){
04240 skip_if(cpl_propertylist_update_double(qclist,kname,median[0]));
04241 } else {
04242 skip_if(cpl_propertylist_append_double(qclist,kname,median[0]));
04243 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04244 }
04245 median[1] = cpl_image_get_median_window(dif_avg,
04246 detmon_lg_config.llx2,
04247 detmon_lg_config.lly2,
04248 detmon_lg_config.urx2,
04249 detmon_lg_config.ury2);
04250
04251 skip_if(0);
04252 kname = cpl_sprintf("%s%d", DETMON_QC_CONTAM,2);
04253 if(cpl_propertylist_has(qclist,kname)){
04254 skip_if(cpl_propertylist_update_double(qclist,kname,median[1]));
04255 } else {
04256 skip_if(cpl_propertylist_append_double(qclist,kname,median[1]));
04257 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04258 }
04259 median[2] = cpl_image_get_median_window(dif_avg,
04260 detmon_lg_config.llx3,
04261 detmon_lg_config.lly3,
04262 detmon_lg_config.urx3,
04263 detmon_lg_config.ury3);
04264 skip_if(0);
04265
04266 kname = cpl_sprintf("%s%d", DETMON_QC_CONTAM,3);
04267 if(cpl_propertylist_has(qclist,kname)){
04268 skip_if(cpl_propertylist_update_double(qclist,kname,median[2]));
04269 } else {
04270 skip_if(cpl_propertylist_append_double(qclist,kname,median[2]));
04271 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04272 }
04273
04274 median[3] = cpl_image_get_median_window(dif_avg,
04275 detmon_lg_config.llx4,
04276 detmon_lg_config.lly4,
04277 detmon_lg_config.urx4,
04278 detmon_lg_config.ury4);
04279 skip_if(0);
04280
04281 kname = cpl_sprintf("%s%d", DETMON_QC_CONTAM,4);
04282 if(cpl_propertylist_has(qclist,kname)){
04283 skip_if(cpl_propertylist_update_double(qclist,kname,median[3]));
04284 } else {
04285 skip_if(cpl_propertylist_append_double(qclist,kname,median[3]));
04286 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04287 }
04288
04289 median[4] = cpl_image_get_median_window(dif_avg,
04290 detmon_lg_config.llx5,
04291 detmon_lg_config.lly5,
04292 detmon_lg_config.urx5,
04293 detmon_lg_config.ury5);
04294 skip_if(0);
04295
04296 kname = cpl_sprintf("%s%d", DETMON_QC_CONTAM,5);
04297 if(cpl_propertylist_has(qclist,kname)){
04298 skip_if(cpl_propertylist_update_double(qclist,kname,median[4]));
04299 } else {
04300 skip_if(cpl_propertylist_append_double(qclist,kname,median[4]));
04301 skip_if(cpl_propertylist_set_comment(qclist,kname,DETMON_QC_CONTAM_C));
04302 }
04303 end_skip;
04304
04305 cpl_image_delete(dif1);
04306 cpl_image_delete(dif2);
04307 cpl_image_delete(dif_avg);
04308
04309 return cpl_error_get_code();
04310 }
04311
04312
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04366
04367 int
04368 irplib_detmon_lg_dfs_set_groups(cpl_frameset * set,
04369 const char *tag_on, const char *tag_off)
04370 {
04371 cpl_frame *cur_frame;
04372 const char *tag;
04373 int nframes;
04374 int i;
04375
04376
04377 if(set == NULL)
04378 return -1;
04379
04380
04381 nframes = cpl_frameset_get_size(set);
04382
04383
04384 for(i = 0; i < nframes; i++) {
04385 cur_frame = cpl_frameset_get_frame(set, i);
04386 tag = cpl_frame_get_tag(cur_frame);
04387
04388
04389 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
04390 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
04391
04392
04393
04394
04395
04396 }
04397 return 0;
04398 }
04399
04400
04414
04415 static cpl_error_code
04416 irplib_detmon_lg_reduce_all(const cpl_table * linear_table,
04417 cpl_propertylist * gaint_qclist,
04418 cpl_propertylist * lint_qclist,
04419 cpl_propertylist * linc_qclist,
04420 cpl_propertylist * bpm_qclist,
04421 cpl_imagelist ** coeffs_ptr,
04422 cpl_image ** bpms_ptr,
04423 const cpl_imagelist * linearity_inputs,
04424 const cpl_table * gain_table,
04425 int which_ext, cpl_boolean opt_nir)
04426 {
04427
04428 int nbpixs = 0;
04429 const int nsets = cpl_table_get_nrow(linear_table);
04430 int i, j, k;
04431 double autocorr;
04432 cpl_polynomial *poly_linfit = NULL;
04433 cpl_image *fiterror = NULL;
04434 char * name_o1 = NULL;
04435 char * name_o2 = NULL;
04436 double * pcoeffs = cpl_malloc(sizeof(double)*(detmon_lg_config.order + 1));
04437 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
04438 double min_val=0;
04439 double max_val=0;
04440 cpl_vector *x =NULL;
04441 const cpl_vector *y =NULL;
04442
04443
04444 const cpl_image * first = NULL;
04445 int sizex = 0;
04446 int sizey = 0;
04447
04448 int vsize = 0;
04449
04450
04451
04452
04453 cpl_ensure_code(gaint_qclist != NULL, CPL_ERROR_NULL_INPUT);
04454 cpl_ensure_code(lint_qclist != NULL, CPL_ERROR_NULL_INPUT);
04455 cpl_ensure_code(linc_qclist != NULL, CPL_ERROR_NULL_INPUT);
04456 cpl_ensure_code(bpm_qclist != NULL, CPL_ERROR_NULL_INPUT);
04457
04458 skip_if(cpl_propertylist_append_string(gaint_qclist, DETMON_QC_METHOD,
04459 detmon_lg_config.method));
04460 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_METHOD,
04461 DETMON_QC_METHOD_C));
04462
04463 if (!strcmp(detmon_lg_config.method, "PTC")) {
04464
04465 if (detmon_lg_config.exts >= 0) {
04466 cpl_msg_info(cpl_func,
04467 "Polynomial fitting for the GAIN (constant term method)");
04468 } else {
04469 cpl_msg_info(cpl_func,
04470 "Polynomial fitting for the GAIN (constant term method)"
04471 " for extension nb %d", which_ext);
04472 }
04473 skip_if(irplib_detmon_lg_qc_ptc(gain_table, gaint_qclist, mode, nsets));
04474 } else {
04475 skip_if(irplib_detmon_lg_qc_med(gain_table, gaint_qclist, nsets));
04476 }
04477
04478
04479
04480 if(detmon_lg_config.lamp_ok) {
04481 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_FLUX,
04482 detmon_lg_config.cr));
04483 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_FLUX,
04484 DETMON_QC_LAMP_FLUX_C));
04485 }
04486
04487
04488 if(detmon_lg_config.autocorr == TRUE) {
04489 autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
04490 skip_if(cpl_propertylist_append_double(gaint_qclist, DETMON_QC_AUTOCORR,
04491 autocorr));
04492 skip_if(cpl_propertylist_set_comment(gaint_qclist, DETMON_QC_AUTOCORR,
04493 DETMON_QC_AUTOCORR_C));
04494 }
04495 if (detmon_lg_config.exts >= 0) {
04496 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix");
04497 } else {
04498 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix"
04499 " for extension nb %d", which_ext);
04500 }
04501
04502 if(!detmon_lg_config.pix2pix) {
04503 double mse = 0;
04504
04505 y = cpl_vector_wrap(nsets,
04506 (double *)cpl_table_get_data_double_const(linear_table,
04507 "MED"));
04508
04509 if (opt_nir == NIR)
04510 x = cpl_vector_wrap(nsets,
04511 (double *)cpl_table_get_data_double_const(linear_table,
04512 "DIT"));
04513 else
04514 x = cpl_vector_wrap(nsets,
04515 (double *)cpl_table_get_data_double_const(linear_table,
04516 "EXPTIME"));
04517
04518
04519 if(x == NULL || y == NULL) {
04520 cpl_vector_unwrap((cpl_vector *)x);
04521 cpl_vector_unwrap((cpl_vector *)y);
04522
04523
04524
04525
04526
04527
04528 skip_if(1);
04529 }
04530
04531 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
04532 poly_linfit = irplib_polynomial_fit_1d_create(x, y,
04533 detmon_lg_config.order,
04534 &mse);
04535
04536 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
04537 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
04538 mse = 0;
04539 }
04540
04541 if(poly_linfit == NULL) {
04542 cpl_vector_unwrap((cpl_vector *)x);
04543 cpl_vector_unwrap((cpl_vector *)y);
04544
04545 skip_if(1);
04546 }
04547
04548
04549 min_val=cpl_vector_get_min(y);
04550 max_val=cpl_vector_get_max(y);
04551
04552 cpl_vector_unwrap((cpl_vector *)x);
04553 cpl_vector_unwrap((cpl_vector *)y);
04554
04555 for(i = 0; i <= detmon_lg_config.order; i++) {
04556 const double coeff =
04557 cpl_polynomial_get_coeff(poly_linfit, &i);
04558 char *name_o =
04559 cpl_sprintf("ESO QC LIN COEF%d", i);
04560 assert(name_o != NULL);
04561 skip_if(cpl_propertylist_append_double(lint_qclist, name_o, coeff));
04562 skip_if(cpl_propertylist_set_comment(lint_qclist,name_o,
04563 DETMON_QC_LIN_COEF_C));
04564
04565 cpl_free(name_o);
04566 pcoeffs[i] = coeff;
04567 }
04568 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_ERRFIT, mse));
04569 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_ERRFIT,
04570 DETMON_QC_ERRFIT_MSE_C));
04571
04572
04573 } else {
04574
04575
04576 y = cpl_vector_wrap(nsets,
04577 (double *)cpl_table_get_data_double_const(linear_table,
04578 "MED"));
04579
04580 if (opt_nir == NIR) {
04581 x=
04582 cpl_vector_wrap(nsets,
04583 (double *)cpl_table_get_data_double_const(linear_table,
04584 "DIT"));
04585
04586 } else {
04587
04588 x =
04589 cpl_vector_wrap(nsets,
04590 (double *)cpl_table_get_data_double_const(linear_table,
04591 "EXPTIME"));
04592
04593 }
04594
04595
04596 first = cpl_imagelist_get_const(linearity_inputs, 0);
04597 sizex = cpl_image_get_size_x(first);
04598 sizey = cpl_image_get_size_y(first);
04599
04600 vsize = cpl_vector_get_size(x);
04601 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
04602
04603 *coeffs_ptr =
04604 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
04605 detmon_lg_config.order, FALSE,
04606 CPL_TYPE_FLOAT, fiterror);
04607
04608 min_val=cpl_vector_get_min(y);
04609 max_val=cpl_vector_get_max(y);
04610
04611
04612 cpl_vector_unwrap((cpl_vector*)x);
04613 cpl_vector_unwrap((cpl_vector*)y);
04614 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
04615 "Failed polynomial fit");
04616
04617 for(i = 0; i <= detmon_lg_config.order; i++) {
04618 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, i);
04619 const double coeff = cpl_image_get_median(image);
04620 pcoeffs[i] = coeff;
04621 name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
04622 name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
04623 assert(name_o1 != NULL);
04624 assert(name_o2 != NULL);
04625 skip_if(cpl_propertylist_append_double(linc_qclist, name_o1, coeff));
04626 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o1,
04627 DETMON_QC_LIN_COEF_C));
04628 cpl_free(name_o1);
04629 name_o1= NULL;
04630 skip_if(cpl_propertylist_append_double(linc_qclist, name_o2,
04631 cpl_image_get_stdev(image)));
04632 skip_if(cpl_propertylist_set_comment(linc_qclist,name_o2,
04633 DETMON_QC_LIN_COEF_ERR_C));
04634 cpl_free(name_o2);
04635 name_o2= NULL;
04636 }
04637
04638 if(detmon_lg_config.order == vsize - 1) {
04639 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
04640 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
04641 0.0));
04642 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
04643 DETMON_QC_ERRFIT_C));
04644
04645
04646
04647 } else {
04648 skip_if(cpl_propertylist_append_double(linc_qclist,DETMON_QC_ERRFIT,
04649 cpl_image_get_median(fiterror)));
04650 skip_if(cpl_propertylist_set_comment(linc_qclist,DETMON_QC_ERRFIT,
04651 DETMON_QC_ERRFIT_C));
04652
04653 }
04654 }
04655
04656
04657 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MIN,
04658 min_val));
04659
04660 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MIN,
04661 DETMON_QC_COUNTS_MIN_C));
04662
04663 skip_if(cpl_propertylist_append_double(lint_qclist,DETMON_QC_COUNTS_MAX,
04664 max_val));
04665
04666 skip_if(cpl_propertylist_set_comment(lint_qclist,DETMON_QC_COUNTS_MAX,
04667 DETMON_QC_COUNTS_MAX_C));
04668
04669 skip_if(irplib_detmon_lg_lineff(pcoeffs,lint_qclist,detmon_lg_config.ref_level,
04670 detmon_lg_config.order));
04671
04672
04673 if (detmon_lg_config.exts >= 0) {
04674 cpl_msg_info(cpl_func, "Bad pixel detection");
04675 } else {
04676 cpl_msg_info(cpl_func, "Bad pixel detection"
04677 " for extension nb %d", which_ext);
04678 }
04679
04680 if(detmon_lg_config.pix2pix) {
04681 *bpms_ptr = irplib_detmon_bpixs(*coeffs_ptr, detmon_lg_config.bpmbin,
04682 detmon_lg_config.kappa, &nbpixs);
04683 skip_if(*bpms_ptr == NULL);
04684 }
04685
04686 skip_if(cpl_propertylist_append_int(bpm_qclist, DETMON_QC_NUM_BPM, nbpixs));
04687 skip_if(cpl_propertylist_set_comment(bpm_qclist, DETMON_QC_NUM_BPM,
04688 DETMON_QC_NUM_BPM_C));
04689
04690 if(detmon_lg_config.lamp_stability != 0.0) {
04691 skip_if(cpl_propertylist_append_double(lint_qclist, DETMON_QC_LAMP_STAB,
04692 detmon_lg_config.lamp_stability));
04693 skip_if(cpl_propertylist_set_comment(lint_qclist, DETMON_QC_LAMP_STAB,
04694 DETMON_QC_LAMP_STAB_C));
04695 }
04696
04697
04698 if (!detmon_lg_config.wholechip) {
04699 cpl_image * dummy_bpm = cpl_image_new(detmon_lg_config.nx,
04700 detmon_lg_config.ny,
04701 CPL_TYPE_INT);
04702 cpl_imagelist * dummy_coeffs = cpl_imagelist_new();
04703
04704 int * db_p = cpl_image_get_data_int(dummy_bpm);
04705 int * rb_p = cpl_image_get_data_int(*bpms_ptr);
04706
04707 float ** dcs_p =
04708 cpl_malloc(sizeof(float *) * (detmon_lg_config.order + 1));
04709
04710 float ** rcs_p =
04711 cpl_malloc(sizeof(float *) * (detmon_lg_config.order + 1));
04712
04713 int dlength = detmon_lg_config.nx;
04714 int rlength = detmon_lg_config.urx - detmon_lg_config.llx + 1;
04715
04716 for (i = 0; i <= detmon_lg_config.order; i++) {
04717 cpl_image * dummy_coeff = cpl_image_new(detmon_lg_config.nx,
04718 detmon_lg_config.ny,
04719 CPL_TYPE_FLOAT);
04720
04721 cpl_imagelist_set(dummy_coeffs, dummy_coeff, i);
04722
04723 dcs_p[i] = cpl_image_get_data_float(dummy_coeff);
04724 rcs_p[i] =
04725 cpl_image_get_data_float(cpl_imagelist_get(*coeffs_ptr, i));
04726 }
04727
04728 for (i = detmon_lg_config.lly - 1; i < detmon_lg_config.ury; i++) {
04729 for (j = detmon_lg_config.llx - 1; j < detmon_lg_config.urx; j++) {
04730
04731 *(db_p + i * dlength + j) =
04732 *(rb_p + (i - detmon_lg_config.lly + 1) * rlength +
04733 j - detmon_lg_config.llx + 1);
04734
04735 for (k = 0; k <= detmon_lg_config.order; k++) {
04736 *(dcs_p[k] + i * dlength + j) =
04737 *(rcs_p[k] + (i - detmon_lg_config.lly + 1) * rlength +
04738 j - detmon_lg_config.llx + 1);
04739 }
04740 }
04741 }
04742
04743 cpl_imagelist_delete(*coeffs_ptr);
04744 cpl_image_delete(*bpms_ptr);
04745 *coeffs_ptr = dummy_coeffs;
04746 *bpms_ptr = dummy_bpm;
04747
04748 cpl_free(dcs_p);
04749 cpl_free(rcs_p);
04750 }
04751
04752 end_skip;
04753
04754 cpl_free(pcoeffs);
04755 cpl_free(name_o1);
04756 cpl_free(name_o2);
04757 cpl_image_delete(fiterror);
04758 cpl_polynomial_delete(poly_linfit);
04759
04760 return cpl_error_get_code();
04761 }
04762
04763
04771
04772 static cpl_error_code
04773 irplib_detmon_lg_lineff(double * pcoeffs,
04774 cpl_propertylist * qclist,
04775 int ref_level,
04776 int order)
04777 {
04778 double lineff = 0;
04779 double root = 0;
04780 cpl_polynomial * poly = cpl_polynomial_new(1);
04781 int i;
04782
04783 double residual, slope;
04784
04785
04786
04787
04788
04789 pcoeffs[0] -= ref_level;
04790
04791 for (i = 2; i <= order; i++) {
04792 int j;
04793 for(j = 0; j < i; j++) {
04794 pcoeffs[i] /= pcoeffs[1];
04795 }
04796 }
04797
04798 pcoeffs[1] = 1;
04799
04800 for (i = 0; i <= order; i++) {
04801 skip_if(cpl_polynomial_set_coeff(poly, &i, pcoeffs[i]));
04802 }
04803
04804
04805
04806
04807
04808
04809
04810 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
04811
04812 if (slope <= 0.0 && residual >= 0.0) {
04813 cpl_msg_warning(cpl_func, "Reference level (--ref_level) outside"
04814 " linearity range of the detector. Cannot compute"
04815 " linearity efficiency (QC.LINEFF).");
04816 lineff = -1;
04817 } else {
04818 skip_if(cpl_polynomial_solve_1d(poly, 0.0, &root, 1));
04819
04820 lineff = (root - ref_level) / ref_level;
04821 }
04822
04823 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
04824 lineff));
04825 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
04826 DETMON_QC_LIN_EFF_C));
04827
04828 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF_FLUX,
04829 ref_level));
04830 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF_FLUX,
04831 DETMON_QC_LIN_EFF_FLUX_C));
04832
04833 end_skip;
04834
04835 cpl_polynomial_delete(poly);
04836
04837 return cpl_error_get_code();
04838 }
04839
04840
04847
04848 static cpl_error_code
04849 irplib_detmon_lg_qc_ptc(const cpl_table * gain_table,
04850 cpl_propertylist * qclist, unsigned mode, int rows_in_gain)
04851 {
04852 double mse = 0;
04853 cpl_polynomial *poly_fit = NULL;
04854 cpl_polynomial *poly_fit2 = NULL;
04855 int i;
04856 const int nsets = rows_in_gain;
04857
04858
04859
04860
04861
04862 const cpl_vector *x;
04863 const cpl_vector *y;
04864
04865 cpl_errorstate prestate;
04866 double coef = 0;
04867
04868 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
04869 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
04870
04871 x = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
04872
04873 y = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
04874
04875 skip_if(x == NULL || y == NULL);
04876
04877
04878 poly_fit = irplib_polynomial_fit_1d_create_chiq(x, y, 1, &mse);
04879 skip_if(poly_fit == NULL);
04880
04881
04882 i = 1;
04883 prestate = cpl_errorstate_get();
04884 coef = cpl_polynomial_get_coeff(poly_fit, &i);
04885 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
04886
04887 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
04888 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
04889 DETMON_QC_CONAD_C));
04890
04891 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
04892 1 / coef));
04893 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
04894 DETMON_QC_GAIN_C));
04895
04896
04897
04898
04899
04900 i = 0;
04901
04902
04903
04904
04905
04906
04907
04908
04909 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
04910 const cpl_vector *x2 =
04911 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT_CORR"));
04912 const cpl_vector *y2 =
04913 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
04914
04915 if(x2 == NULL || y2 == NULL) {
04916 cpl_vector_unwrap((cpl_vector *)x2);
04917 cpl_vector_unwrap((cpl_vector *)y2);
04918
04919
04920
04921
04922
04923
04924 skip_if(1);
04925 }
04926
04927
04928 poly_fit2 = irplib_polynomial_fit_1d_create(x2, y2, 1, &mse);
04929 if(poly_fit2 == NULL) {
04930 cpl_vector_unwrap((cpl_vector *)x2);
04931 cpl_vector_unwrap((cpl_vector *)y2);
04932
04933 cpl_msg_error(cpl_func, "Error during polynomial fit, err[%s]", cpl_error_get_where());
04934
04935 skip_if(1);
04936 }
04937 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
04938 cpl_vector_unwrap((cpl_vector *)x2);
04939 cpl_vector_unwrap((cpl_vector *)y2);
04940 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
04941
04942 i = 1;
04943 prestate = cpl_errorstate_get();
04944 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
04945 skip_if(cpl_error_get_code() != CPL_ERROR_NONE);
04946 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
04947
04948 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,
04949 coef));
04950 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
04951 DETMON_QC_CONAD_CORR_C));
04952
04953 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
04954 1 / coef));
04955 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
04956 DETMON_QC_GAIN_CORR_C));
04957 }
04958
04959 end_skip;
04960
04961
04962 cpl_vector_unwrap((cpl_vector *)x);
04963 cpl_vector_unwrap((cpl_vector *)y);
04964 cpl_polynomial_delete(poly_fit);
04965 cpl_polynomial_delete(poly_fit2);
04966
04967 return cpl_error_get_code();
04968 }
04969
04970
04979
04980 static cpl_error_code
04981 irplib_detmon_lg_qc_med(const cpl_table * gain_table,
04982 cpl_propertylist * qclist, int rows_in_gain)
04983 {
04984
04985 double gain=0;
04986 gain=cpl_table_get_column_median(gain_table, "GAIN");
04987
04988 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,gain));
04989
04990 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
04991 DETMON_QC_GAIN_C));
04992
04993 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
04994 cpl_table_get_column_stdev
04995 (gain_table, "GAIN")));
04996 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
04997 DETMON_QC_GAIN_MSE_C));
04998
04999 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD,1./gain));
05000 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
05001 DETMON_QC_CONAD_C));
05002
05003
05004 gain=cpl_table_get_column_median(gain_table, "GAIN_CORR");
05005
05006 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
05007 gain));
05008 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
05009 DETMON_QC_GAIN_CORR_C));
05010
05011
05012 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD_CORR,1./gain));
05013 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD_CORR,
05014 DETMON_QC_CONAD_CORR_C));
05015
05016
05017 end_skip;
05018
05019 return cpl_error_get_code();
05020 }
05021
05022
05023
05032
05033 static cpl_error_code
05034 irplib_detmon_lg_rescale(cpl_imagelist * to_rescale)
05035 {
05036 double med1 =
05037 cpl_image_get_median(cpl_imagelist_get(to_rescale, 0));
05038 double med2 =
05039 cpl_image_get_median(cpl_imagelist_get(to_rescale, 1));
05040
05041 skip_if(0);
05042
05043 if(fabs(med1 / med2 - 1) > 0.001) {
05044 if(med1 > med2)
05045 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
05046 med1 / med2));
05047 else
05048 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
05049 med2 / med1));
05050 }
05051
05052 end_skip;
05053
05054 return cpl_error_get_code();
05055 }
05056
05057 static cpl_error_code
05058 irplib_detmon_pair_extract_next(const cpl_frameset * set,
05059 int* iindex,
05060 int* next_element,
05061 double* dit_array,
05062
05063
05064 cpl_frameset ** pair,
05065 double tolerance)
05066 {
05067 double dit = -100;
05068 double dit_next = -100;
05069 int* selection;
05070 int nsets_extracted = 0;
05071 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
05072 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
05073 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
05074 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
05075
05076 nsets_extracted = cpl_frameset_get_size(set);
05077 selection = cpl_malloc(sizeof(int) * nsets_extracted);
05078 memset(&selection[0], 0, sizeof(int) * nsets_extracted);
05079
05080
05081 dit = dit_array[*next_element ];
05082
05083 if (*next_element < nsets_extracted - 1)
05084 {
05085 dit_next = dit_array[*next_element + 1 ];
05086
05087 }
05088
05089 selection[iindex[*next_element] ] = 1;
05090 if (fabs(dit - dit_next) < tolerance)
05091 {
05092
05093 selection[iindex[*next_element + 1] ] = 1;
05094 (*next_element)++;
05095 }
05096 else
05097 {
05098 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);
05099 }
05100 (*next_element)++;
05101
05102 cpl_frameset_delete(*pair);
05103 *pair = cpl_frameset_extract(set, selection, 1);
05104
05105
05106 cpl_free(selection);
05107 return cpl_error_get_code();
05108 }
05109 static cpl_error_code
05110 irplib_detmon_single_extract_next(const cpl_frameset * set,
05111 int* iindex,
05112 int* next_element,
05113 double* dit_array,
05114 cpl_frameset ** pair)
05115 {
05116 double dit = -100;
05117 int* selection;
05118 int nsets_extracted = 0;
05119 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
05120 cpl_ensure_code(dit_array != NULL, CPL_ERROR_NULL_INPUT);
05121 cpl_ensure_code(iindex != NULL, CPL_ERROR_NULL_INPUT);
05122 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
05123
05124 nsets_extracted = cpl_frameset_get_size(set);
05125 selection = cpl_malloc(sizeof(int) * nsets_extracted);
05126 memset(&selection[0], 0, sizeof(int) * nsets_extracted);
05127
05128 nsets_extracted = cpl_frameset_get_size(set);
05129 dit = dit_array[iindex[*next_element] ];
05130
05131 selection[iindex[*next_element] ] = 1;
05132 (*next_element)++;
05133
05134 cpl_frameset_delete(*pair);
05135 *pair = cpl_frameset_extract(set, selection, 1);
05136
05137 cpl_free(selection);
05138 return cpl_error_get_code();
05139 }
05140
05141
05142
05231
05232
05233 cpl_table *
05234 irplib_detmon_gain(const cpl_imagelist * imlist_on,
05235 const cpl_imagelist * imlist_off,
05236 const cpl_vector * exptimes,
05237 const cpl_vector * ndit,
05238 double tolerance,
05239 int llx,
05240 int lly,
05241 int urx,
05242 int ury,
05243 double kappa,
05244 int nclip,
05245 int xshift,
05246 int yshift,
05247 cpl_propertylist * qclist,
05248 unsigned mode,
05249 cpl_imagelist ** diff_imlist,
05250 cpl_imagelist ** autocorr_imlist)
05251 {
05252 cpl_table * gain_table = NULL;
05253 cpl_imagelist * difflist = NULL;
05254 cpl_imagelist * autocorrlist = NULL;
05255 cpl_imagelist * c_onlist = NULL;
05256 cpl_imagelist * c_offlist = NULL;
05257 cpl_vector * diffdits = NULL;
05258 cpl_vector * diffndits = NULL;
05259 int rows_in_gain = 0;
05260 int ndiffdits, ndits;
05261 int i, j;
05262 cpl_boolean opt_nir = mode & IRPLIB_GAIN_OPT ? OPT : NIR;
05263 const char * method = mode & IRPLIB_GAIN_PTC ? "PTC" : "MED";
05264
05265 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
05266 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
05267 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
05268 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
05269
05270
05271 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
05272 skip_if(irplib_detmon_gain_table_create(gain_table, opt_nir));
05273
05274
05275
05276 skip_if(irplib_detmon_lg_find_dits_ndits(exptimes, ndit,tolerance,&diffdits,&diffndits));
05277 ndiffdits = cpl_vector_get_size(diffdits);
05278
05279 ndits = cpl_vector_get_size(exptimes);
05280
05281
05282 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
05283 difflist = cpl_imagelist_new();
05284 autocorrlist = cpl_imagelist_new();
05285 }
05286
05287 if (mode & IRPLIB_GAIN_COLLAPSE) {
05288 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05289 c_offlist = cpl_imagelist_duplicate(imlist_off);
05290 skip_if(irplib_detmon_lg_rescale(c_offlist));
05291 } else {
05292 c_offlist = (cpl_imagelist *) imlist_off;
05293 }
05294 }
05295
05296
05297 for (i = 0; i < ndiffdits; i++) {
05298 int c_nons;
05299 int c_noffs = 0;
05300
05301 double c_dit = 0;
05302 int c_ndit = 1;
05303
05304 c_dit=cpl_vector_get(diffdits, i);
05305
05306 if(opt_nir) {
05307 c_ndit=(int)cpl_vector_get(diffndits, i);
05308 }
05309
05310 c_onlist = cpl_imagelist_new();
05311 c_nons = 0;
05312
05313 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05314 c_offlist = cpl_imagelist_new();
05315 c_noffs = 0;
05316 }
05317
05318
05319 for(j = 0; j < ndits; j++) {
05320 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
05321
05322
05323
05324
05325
05326
05327
05328
05329 cpl_image * im_on;
05330 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05331 const cpl_image * im =
05332 cpl_imagelist_get_const(imlist_on, j);
05333 im_on = cpl_image_duplicate(im);
05334 } else {
05335 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
05336 }
05337 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
05338 c_nons++;
05339
05340
05341
05342
05343
05344 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05345 cpl_image * im_off;
05346 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05347 const cpl_image * im =
05348 cpl_imagelist_get_const(imlist_off, j);
05349 im_off = cpl_image_duplicate(im);
05350 } else {
05351 im_off =
05352 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
05353 }
05354 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
05355 c_noffs++;
05356 }
05357 }
05358 }
05359
05360
05361 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
05362 skip_if (c_nons != c_noffs);
05363
05364
05365 skip_if (c_nons == 0 || c_nons % 2 != 0);
05366
05367
05368 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
05369 skip_if(irplib_detmon_lg_rescale(c_onlist));
05370 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
05371 skip_if(irplib_detmon_lg_rescale(c_offlist));
05372 }
05373
05374
05375
05376 while(c_nons > 0) {
05377 int rows_affected = 1;
05378 skip_if(irplib_detmon_gain_table_fill_row(gain_table,
05379 c_dit,c_ndit,
05380 autocorrlist,
05381 difflist, c_onlist,
05382 c_offlist, kappa, nclip,
05383 llx, lly, urx, ury,
05384 xshift, yshift,1E10, i,
05385 mode, &rows_affected));
05386 if (rows_affected)
05387 {
05388 rows_in_gain++;
05389 }
05390 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
05391 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05392 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05393 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05394 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05395 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05396 }
05397 } else {
05398 cpl_imagelist_unset(c_onlist, 0);
05399 skip_if(0);
05400 cpl_imagelist_unset(c_onlist, 0);
05401 skip_if(0);
05402 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05403 cpl_imagelist_unset(c_offlist, 0);
05404 skip_if(0);
05405 cpl_imagelist_unset(c_offlist, 0);
05406 skip_if(0);
05407 }
05408 }
05409 skip_if(0);
05410 c_nons -= 2;
05411 }
05412
05413 cpl_imagelist_delete(c_onlist);
05414 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
05415 cpl_imagelist_delete(c_offlist);
05416 }
05417 }
05418
05419 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD, method));
05420 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
05421 DETMON_QC_METHOD_C));
05422
05423
05424 if (mode & IRPLIB_GAIN_PTC) {
05425 skip_if(irplib_detmon_lg_qc_ptc(gain_table, qclist, mode, rows_in_gain));
05426 } else {
05427 skip_if(irplib_detmon_lg_qc_med(gain_table, qclist, rows_in_gain));
05428 }
05429
05430 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
05431 double autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
05432 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
05433 autocorr));
05434 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
05435 DETMON_QC_AUTOCORR_C));
05436 }
05437
05438 if (diff_imlist != NULL) *diff_imlist = difflist;
05439 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
05440
05441 end_skip;
05442
05443 cpl_vector_delete(diffdits);
05444 cpl_vector_delete(diffndits);
05445
05446 return gain_table;
05447 }
05448
05449 static cpl_error_code
05450 irplib_detmon_gain_table_create(cpl_table * gain_table,
05451 const cpl_boolean opt_nir)
05452 {
05453 if (opt_nir == NIR) {
05454 skip_if(cpl_table_new_column(gain_table, "DIT", CPL_TYPE_DOUBLE));
05455 skip_if(cpl_table_new_column(gain_table, "NDIT", CPL_TYPE_INT));
05456 } else {
05457 skip_if(cpl_table_new_column(gain_table, "EXPTIME", CPL_TYPE_DOUBLE));
05458 }
05459 skip_if(cpl_table_new_column(gain_table, "MEAN_ON1", CPL_TYPE_DOUBLE));
05460 skip_if(cpl_table_new_column(gain_table, "MEAN_ON2", CPL_TYPE_DOUBLE));
05461 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF1", CPL_TYPE_DOUBLE));
05462 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF2", CPL_TYPE_DOUBLE));
05463 skip_if(cpl_table_new_column(gain_table, "SIG_ON_DIF", CPL_TYPE_DOUBLE));
05464 skip_if(cpl_table_new_column(gain_table, "SIG_OFF_DIF", CPL_TYPE_DOUBLE));
05465 skip_if(cpl_table_new_column(gain_table, "GAIN", CPL_TYPE_DOUBLE));
05466 skip_if(cpl_table_new_column(gain_table, "AUTOCORR", CPL_TYPE_DOUBLE));
05467 skip_if(cpl_table_new_column(gain_table, "GAIN_CORR", CPL_TYPE_DOUBLE));
05468 skip_if(cpl_table_new_column(gain_table, "ADU", CPL_TYPE_DOUBLE));
05469 skip_if(cpl_table_new_column(gain_table, "X_FIT", CPL_TYPE_DOUBLE));
05470 skip_if(cpl_table_new_column(gain_table, "X_FIT_CORR", CPL_TYPE_DOUBLE));
05471 skip_if(cpl_table_new_column(gain_table, "Y_FIT", CPL_TYPE_DOUBLE));
05472 skip_if(cpl_table_new_column(gain_table, "Y_FIT_CORR", CPL_TYPE_DOUBLE));
05473 skip_if(cpl_table_new_column(gain_table, "FLAG", CPL_TYPE_INT));
05474
05475 end_skip;
05476
05477 return cpl_error_get_code();
05478 }
05479
05480 static cpl_error_code
05481 irplib_detmon_lin_table_create(cpl_table * lin_table,
05482 const cpl_boolean opt_nir)
05483 {
05484 if (opt_nir == NIR) {
05485 skip_if(cpl_table_new_column(lin_table, "DIT", CPL_TYPE_DOUBLE));
05486 } else {
05487 skip_if(cpl_table_new_column(lin_table, "EXPTIME", CPL_TYPE_DOUBLE));
05488 }
05489 skip_if(cpl_table_new_column(lin_table, "MED", CPL_TYPE_DOUBLE));
05490 skip_if(cpl_table_new_column(lin_table, "MEAN", CPL_TYPE_DOUBLE));
05491 skip_if(cpl_table_new_column(lin_table, "MED_DIT", CPL_TYPE_DOUBLE));
05492 skip_if(cpl_table_new_column(lin_table, "MEAN_DIT", CPL_TYPE_DOUBLE));
05493 skip_if(cpl_table_new_column(lin_table, "ADL", CPL_TYPE_DOUBLE));
05494 end_skip;
05495
05496 return cpl_error_get_code();
05497 }
05498
05499 static cpl_vector *
05500 irplib_detmon_lg_find_dits(const cpl_vector * exptimes,
05501 double tolerance)
05502 {
05503 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
05504 int ndits = 0;
05505
05506 int i, j;
05507
05508
05509 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
05510 ndits = 1;
05511
05512
05513 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
05514 int ndiffs = 0;
05515 for (j = 0; j < ndits; j++) {
05516 if (fabs(cpl_vector_get(exptimes, i) -
05517 cpl_vector_get(dits, j)) > tolerance)
05518 ndiffs++;
05519 }
05520 if(ndiffs == ndits) {
05521 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
05522 ndits++;
05523 }
05524 }
05525
05526 cpl_vector_set_size(dits, ndits);
05527
05528 return dits;
05529 }
05530
05531
05532
05533
05534 static cpl_error_code
05535 irplib_detmon_lg_find_dits_ndits(const cpl_vector * exptimes,
05536 const cpl_vector * vec_ndits,
05537 double tolerance,
05538 cpl_vector** diff_dits,
05539 cpl_vector** diff_ndits)
05540 {
05541 int ndits = 0;
05542
05543 int i, j;
05544 int size=0;
05545
05546
05547 * diff_dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
05548 * diff_ndits = cpl_vector_new(cpl_vector_get_size(*diff_dits));
05549
05550
05551 cpl_vector_set(*diff_dits, 0, cpl_vector_get(exptimes, 0));
05552 cpl_vector_set(*diff_ndits, 0, cpl_vector_get(vec_ndits, 0));
05553
05554 ndits = 1;
05555 size=cpl_vector_get_size(exptimes);
05556
05557 for(i = 1; i < size; i++) {
05558 int ndiffs = 0;
05559 for (j = 0; j < ndits; j++) {
05560 if (fabs(cpl_vector_get(exptimes, i) -
05561 cpl_vector_get(*diff_dits,j)) > tolerance)
05562 ndiffs++;
05563 }
05564 if(ndiffs == ndits) {
05565 cpl_vector_set(*diff_dits, ndits, cpl_vector_get(exptimes, i));
05566 cpl_vector_set(*diff_ndits, ndits, cpl_vector_get(vec_ndits, i));
05567 ndits++;
05568 }
05569 }
05570
05571 cpl_vector_set_size(*diff_dits, ndits);
05572 cpl_vector_set_size(*diff_ndits, ndits);
05573
05574
05575 return cpl_error_get_code();
05576 }
05577
05578
05579
05660
05661
05662 cpl_table *
05663 irplib_detmon_lin(const cpl_imagelist * imlist_on,
05664 const cpl_imagelist * imlist_off,
05665 const cpl_vector * exptimes,
05666 double tolerance,
05667 int llx,
05668 int lly,
05669 int urx,
05670 int ury,
05671 int order,
05672 int ref_level,
05673 double kappa,
05674 cpl_boolean bpmbin,
05675 cpl_propertylist * qclist,
05676 unsigned mode,
05677 cpl_imagelist ** coeffs_cube,
05678 cpl_image ** bpm)
05679 {
05680 cpl_table * lin_table = NULL;
05681 cpl_imagelist * c_onlist = NULL;
05682 cpl_imagelist * c_offlist = NULL;
05683 cpl_vector * diffdits = NULL;
05684 cpl_imagelist * lin_inputs = NULL;
05685 cpl_polynomial * poly_linfit = NULL;
05686 cpl_image * fiterror = NULL;
05687 cpl_vector * vcoeffs = NULL;
05688 double * pcoeffs = NULL;
05689 int ndiffdits, ndits;
05690 int i, j;
05691 cpl_boolean opt_nir = mode & IRPLIB_LIN_OPT ? OPT : NIR;
05692 const cpl_vector *x = NULL;
05693 const cpl_vector *y = NULL;
05694
05695 const cpl_image * first = NULL;
05696 int sizex = 0;
05697 int sizey = 0;
05698
05699 double vsize = 0;
05700
05701
05702 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
05703 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
05704 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
05705 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
05706 cpl_ensure(order > 0 , CPL_ERROR_ILLEGAL_INPUT, NULL);
05707
05708 vcoeffs = cpl_vector_new(order + 1);
05709 pcoeffs = cpl_vector_get_data(vcoeffs);
05710
05711
05712 if (mode & IRPLIB_LIN_PIX2PIX) {
05713 lin_inputs = cpl_imagelist_new();
05714 cpl_ensure(coeffs_cube != NULL, CPL_ERROR_NULL_INPUT, NULL);
05715 cpl_ensure(bpm != NULL, CPL_ERROR_NULL_INPUT, NULL);
05716 }
05717
05718
05719 lin_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
05720 skip_if(irplib_detmon_lin_table_create(lin_table, opt_nir));
05721
05722
05723
05724 diffdits = irplib_detmon_lg_find_dits(exptimes, tolerance);
05725 ndiffdits = cpl_vector_get_size(diffdits);
05726
05727 ndits = cpl_vector_get_size(exptimes);
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757 if (mode & IRPLIB_LIN_COLLAPSE) {
05758
05759
05760
05761
05762 cpl_image * collapse = cpl_imagelist_collapse_create(imlist_off);
05763 skip_if(collapse == NULL);
05764
05765 c_offlist = cpl_imagelist_new();
05766 skip_if(cpl_imagelist_set(c_offlist, collapse, 0));
05767 }
05768
05769
05770 for (i = 0; i < ndiffdits; i++) {
05771 int c_nons;
05772 int c_noffs = 0;
05773
05774 double c_dit = cpl_vector_get(diffdits, i);
05775
05776 c_onlist = cpl_imagelist_new();
05777 c_nons = 0;
05778
05779 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
05780 c_offlist = cpl_imagelist_new();
05781 c_noffs = 0;
05782 }
05783
05784 for(j = 0; j < ndits; j++) {
05785 if (fabs(c_dit - cpl_vector_get(exptimes, j)) <= tolerance) {
05786
05787
05788
05789
05790
05791
05792
05793
05794 cpl_image * im_on;
05795 if (mode & IRPLIB_LIN_WITH_RESCALE) {
05796 const cpl_image * im =
05797 cpl_imagelist_get_const(imlist_on, j);
05798 im_on = cpl_image_duplicate(im);
05799 } else {
05800 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
05801 }
05802 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
05803 c_nons++;
05804
05805
05806
05807
05808
05809 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
05810 cpl_image * im_off;
05811 if (mode & IRPLIB_LIN_WITH_RESCALE) {
05812 const cpl_image * im =
05813 cpl_imagelist_get_const(imlist_off, j);
05814 im_off = cpl_image_duplicate(im);
05815 } else {
05816 im_off =
05817 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
05818 }
05819 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
05820 c_noffs++;
05821 }
05822 }
05823 }
05824
05825
05826 if (mode & IRPLIB_LIN_NO_COLLAPSE)
05827 skip_if (c_nons != c_noffs);
05828
05829
05830 skip_if (c_nons == 0 || c_nons % 2 != 0);
05831
05832
05833 if(mode & IRPLIB_LIN_WITH_RESCALE) {
05834 skip_if(irplib_detmon_lg_rescale(c_onlist));
05835 if (mode & IRPLIB_LIN_NO_COLLAPSE)
05836 skip_if(irplib_detmon_lg_rescale(c_offlist));
05837 }
05838
05839
05840
05841 while(c_nons > 0) {
05842
05843 skip_if(irplib_detmon_lin_table_fill_row(lin_table, c_dit,
05844 lin_inputs,
05845 c_onlist, c_offlist,
05846 llx, lly, urx, ury,
05847 i, 0, mode));
05848
05849 if (mode & IRPLIB_LIN_WITH_RESCALE) {
05850 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05851 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
05852 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
05853 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05854 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
05855 }
05856 } else {
05857 cpl_imagelist_unset(c_onlist, 0);
05858 skip_if(0);
05859 cpl_imagelist_unset(c_onlist, 0);
05860 skip_if(0);
05861 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
05862 cpl_imagelist_unset(c_offlist, 0);
05863 skip_if(0);
05864 cpl_imagelist_unset(c_offlist, 0);
05865 skip_if(0);
05866 }
05867 }
05868 skip_if(0);
05869 c_nons -= 2;
05870 }
05871
05872 cpl_imagelist_delete(c_onlist);
05873 if (mode & IRPLIB_LIN_NO_COLLAPSE) {
05874 cpl_imagelist_delete(c_offlist);
05875 }
05876 }
05877
05878 skip_if(irplib_detmon_add_adl_column(lin_table, opt_nir));
05879
05880 if(!(mode & IRPLIB_LIN_PIX2PIX)) {
05881 double mse = 0;
05882
05883 y = cpl_vector_wrap(cpl_table_get_nrow(lin_table),
05884 (double *)cpl_table_get_data_double_const(lin_table,
05885 "MED"));
05886 if (opt_nir == NIR) {
05887 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
05888 (double *)cpl_table_get_data_double_const(lin_table, "DIT"));
05889 } else {
05890 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
05891 (double *)cpl_table_get_data_double_const(lin_table, "EXPTIME"));
05892 }
05893 if(x == NULL || y == NULL) {
05894 cpl_vector_unwrap((cpl_vector *)x);
05895 cpl_vector_unwrap((cpl_vector *)y);
05896
05897
05898
05899
05900
05901
05902 skip_if(1);
05903 }
05904
05905 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
05906 poly_linfit = irplib_polynomial_fit_1d_create_chiq(x, y, order, &mse);
05907
05908 if(order == cpl_vector_get_size(x) - 1) {
05909 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
05910 mse = 0;
05911 }
05912
05913 if(poly_linfit == NULL) {
05914 cpl_vector_unwrap((cpl_vector *)x);
05915 cpl_vector_unwrap((cpl_vector *)y);
05916
05917 skip_if(1);
05918 }
05919
05920 cpl_vector_unwrap((cpl_vector *)x);
05921 cpl_vector_unwrap((cpl_vector *)y);
05922
05923 for(i = 0; i <= order; i++) {
05924 const double coeff =
05925 cpl_polynomial_get_coeff(poly_linfit, &i);
05926 char *name_o =
05927 cpl_sprintf("ESO QC LIN COEF%d", i);
05928 assert(name_o != NULL);
05929 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
05930 skip_if(cpl_propertylist_set_comment(qclist,name_o,
05931 DETMON_QC_LIN_COEF_C));
05932 cpl_free(name_o);
05933 pcoeffs[i] = coeff;
05934 }
05935 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT, mse));
05936 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
05937 DETMON_QC_ERRFIT_MSE_C));
05938
05939
05940 } else {
05941 if (opt_nir == NIR) {
05942 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
05943 (double *)cpl_table_get_data_double_const(lin_table,
05944 "DIT"));
05945 } else {
05946 x=cpl_vector_wrap(cpl_table_get_nrow(lin_table),
05947 (double *)cpl_table_get_data_double_const(lin_table,
05948 "EXPTIME"));
05949 }
05950
05951
05952 first = cpl_imagelist_get_const(lin_inputs, 0);
05953 sizex = cpl_image_get_size_x(first);
05954 sizey = cpl_image_get_size_y(first);
05955
05956 vsize = cpl_vector_get_size(x);
05957
05958 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
05959
05960 *coeffs_cube =
05961 cpl_fit_imagelist_polynomial(x, lin_inputs, 0,
05962 order, FALSE, CPL_TYPE_FLOAT,
05963 fiterror);
05964
05965 cpl_vector_unwrap((cpl_vector*)x);
05966 irplib_ensure(*coeffs_cube != NULL, CPL_ERROR_UNSPECIFIED,
05967 "Failed polynomial fit");
05968
05969 for(i = 0; i <= order; i++) {
05970 cpl_image *image = cpl_imagelist_get(*coeffs_cube, i);
05971 const double coeff = cpl_image_get_median(image);
05972 char * name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
05973 char * name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
05974 pcoeffs[i] = coeff;
05975 assert(name_o1 != NULL);
05976 assert(name_o2 != NULL);
05977 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
05978 skip_if(cpl_propertylist_set_comment(qclist,name_o1,
05979 DETMON_QC_LIN_COEF_C));
05980 cpl_free(name_o1);
05981 name_o1= NULL;
05982 skip_if(cpl_propertylist_append_double(qclist, name_o2,
05983 cpl_image_get_stdev(image)));
05984 skip_if(cpl_propertylist_set_comment(qclist,name_o2,
05985 DETMON_QC_LIN_COEF_ERR_C));
05986 cpl_free(name_o2);
05987 name_o2= NULL;
05988 }
05989
05990 if(order == vsize - 1) {
05991 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
05992 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
05993 0.0));
05994 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
05995 DETMON_QC_ERRFIT_C));
05996
05997
05998 } else {
05999 skip_if(cpl_propertylist_append_double(qclist,DETMON_QC_ERRFIT,
06000 cpl_image_get_median(fiterror)));
06001 skip_if(cpl_propertylist_set_comment(qclist,DETMON_QC_ERRFIT,
06002 DETMON_QC_ERRFIT_C));
06003
06004 }
06005 }
06006
06007 skip_if(irplib_detmon_lg_lineff(pcoeffs, qclist, ref_level, order));
06008
06009 if(mode & IRPLIB_LIN_PIX2PIX) {
06010 int nbpixs;
06011 *bpm = irplib_detmon_bpixs(*coeffs_cube, bpmbin, kappa, &nbpixs);
06012 skip_if(*bpm == NULL);
06013 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM,
06014 nbpixs));
06015 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
06016 DETMON_QC_NUM_BPM_C));
06017 }
06018
06019 end_skip;
06020
06021 cpl_vector_delete(diffdits);
06022 cpl_polynomial_delete(poly_linfit);
06023 cpl_imagelist_delete(lin_inputs);
06024 cpl_vector_delete(vcoeffs);
06025 cpl_image_delete(fiterror);
06026
06027 return lin_table;
06028
06029 }
06030
06031
06055
06056 static cpl_error_code
06057 irplib_detmon_lin_table_fill_row(cpl_table * lin_table, double c_dit,
06058 cpl_imagelist * linearity_inputs,
06059 const cpl_imagelist * ons,
06060 const cpl_imagelist * offs,
06061 int llx,
06062 int lly,
06063 int urx,
06064 int ury,
06065 const int pos,
06066 const int nskip,
06067 unsigned mode)
06068 {
06069 cpl_image * dif1=NULL;
06070 cpl_image * dif2=NULL;
06071 cpl_image * dif_avg=NULL;
06072
06073 double med_dit=0;
06074 double mean_dit=0;
06075 cpl_error_code error;
06076 cpl_image * extracted=NULL;
06077 int offsize=0;
06078
06079 cpl_ensure_code(lin_table != NULL, CPL_ERROR_NULL_INPUT);
06080 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
06081 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
06082
06083 if (mode & IRPLIB_LIN_PIX2PIX) {
06084 cpl_msg_debug(cpl_func,"checking linearity inputs");
06085 cpl_ensure_code(linearity_inputs != NULL, CPL_ERROR_NULL_INPUT);
06086 }
06087
06088
06089 if (mode & IRPLIB_LIN_NIR) {
06090 cpl_table_set(lin_table, "DIT", pos, c_dit);
06091 } else if (mode & IRPLIB_LIN_OPT) {
06092 cpl_table_set(lin_table, "EXPTIME", pos, c_dit);
06093 } else {
06094 cpl_msg_error(cpl_func, "Mandatory mode not given");
06095 }
06096
06097 offsize = cpl_imagelist_get_size(offs);
06098
06099
06100 dif1 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
06101 cpl_imagelist_get_const(offs, 0));
06102
06103 if (mode & IRPLIB_LIN_NO_COLLAPSE && offsize > 1)
06104 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
06105 cpl_imagelist_get_const(offs, 1));
06106 else
06107 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
06108 cpl_imagelist_get_const(offs, 0));
06109
06110 dif_avg = cpl_image_average_create(dif1, dif2);
06111
06112 cpl_image_abs(dif_avg);
06113 extracted = cpl_image_extract(dif_avg, llx, lly, urx, ury);
06114
06115 cpl_ensure_code(extracted != NULL, cpl_error_get_code());
06116
06117 cpl_table_set(lin_table, "MED", pos, cpl_image_get_median(extracted));
06118 cpl_table_set(lin_table, "MEAN", pos, cpl_image_get_mean(extracted));
06119 med_dit = cpl_image_get_median(extracted) / c_dit;
06120 mean_dit = cpl_image_get_mean(extracted) / c_dit;
06121
06122 cpl_table_set(lin_table, "MED_DIT", pos, med_dit);
06123 cpl_table_set(lin_table, "MEAN_DIT", pos, mean_dit);
06124
06125 cpl_image_delete(dif1);
06126 cpl_image_delete(dif2);
06127
06128
06129 if(mode & IRPLIB_LIN_PIX2PIX) {
06130 error = cpl_imagelist_set(linearity_inputs, extracted, pos-nskip);
06131 cpl_ensure_code(!error, error);
06132 } else {
06133 cpl_image_delete(extracted);
06134 }
06135
06136
06137 cpl_image_delete(dif_avg);
06138
06139 return cpl_error_get_code();
06140 }
06141
06142 static double irplib_calculate_total_noise_smooth(const cpl_image* pimage, int pattern_x, int pattern_y)
06143 {
06144 cpl_image * p_tmp_image = 0;
06145 cpl_image * psmooth_image = 0;
06146 double ret_noise = -1;
06147 cpl_mask * mask = cpl_mask_new(pattern_x, pattern_y);
06148 cpl_mask_not(mask);
06149 p_tmp_image = cpl_image_duplicate(pimage);
06150 cpl_image_filter_mask(p_tmp_image,pimage, mask,CPL_FILTER_MEDIAN ,CPL_BORDER_FILTER);
06151 cpl_image_divide_scalar(p_tmp_image, cpl_image_get_median(pimage));
06152 psmooth_image = cpl_image_divide_create(pimage,p_tmp_image);
06153 ret_noise = irplib_calculate_total_noise(psmooth_image);
06154 cpl_mask_delete(mask);
06155 cpl_image_delete(psmooth_image);
06156 cpl_image_delete(p_tmp_image);
06157 return ret_noise;
06158 }
06159 static double irplib_calculate_total_noise(const cpl_image* pimage)
06160 {
06161 double total_noise = -1;
06162 unsigned long max_bin_size = 1E5;
06163 const double hstart = cpl_image_get_min(pimage);
06164 const double hrange = cpl_image_get_max(pimage) - hstart;
06165 const unsigned long nbins = max_bin_size;
06166 cpl_error_code err = CPL_ERROR_NONE;
06167
06168 irplib_hist * phist = 0;
06169 phist = irplib_hist_new();
06170
06171
06172 irplib_hist_init(phist, nbins, hstart, hrange);
06173 err = irplib_hist_fill(phist, pimage);
06174 if (err == CPL_ERROR_NONE)
06175 {
06176 unsigned int i = 0;
06177 double x0 = 0;
06178 double area = 0;
06179 double offset = 0;
06180
06181
06182 unsigned long n_bins = irplib_hist_get_nbins(phist);
06183 double start = irplib_hist_get_start(phist);
06184 double bin_size = irplib_hist_get_bin_size(phist);
06185 cpl_vector* pdata_vector = cpl_vector_new(n_bins);
06186 cpl_vector* ppos_vector = cpl_vector_new(n_bins);
06187 cpl_table* ptable = cpl_table_new(n_bins);
06188 cpl_table_new_column(ptable, "bin", CPL_TYPE_DOUBLE);
06189 cpl_table_new_column(ptable, "value", CPL_TYPE_DOUBLE);
06190 for(i = 0; i < n_bins; i++)
06191 {
06192 unsigned int value = irplib_hist_get_value(phist, i);
06193 double dvalue = (double)(value);
06194 cpl_vector_set(pdata_vector, i, dvalue);
06195 cpl_vector_set(ppos_vector, i, start + i * bin_size);
06196
06197 cpl_table_set(ptable, "bin", i, start + i * bin_size);
06198 cpl_table_set(ptable, "value", i, dvalue);
06199 }
06200 err = cpl_vector_fit_gaussian(ppos_vector, NULL, pdata_vector, NULL, CPL_FIT_ALL, &x0, &total_noise, &area, &offset, NULL, NULL, NULL );
06201 if (err == CPL_ERROR_NONE)
06202 {
06203 cpl_msg_info(cpl_func, "FPN Calculation: histogram x0[%f] total_noise[%f] area[%f] offset[%f]", x0, total_noise, area, offset);
06204 }
06205 else
06206 {
06207 cpl_msg_warning(cpl_func, "FPN could not be computed due failed Gaussian Fit, err msg [%s]", cpl_error_get_message());
06208 cpl_error_reset();
06209 }
06210 cpl_table_delete(ptable);
06211 cpl_vector_delete(ppos_vector);
06212 cpl_vector_delete(pdata_vector);
06213 }
06214 else
06215 {
06216 cpl_msg_warning(cpl_func, "FPN could not be computed due failed histogram computation, err msg [%s]", cpl_error_get_message());
06217 cpl_error_reset();
06218 }
06219 irplib_hist_delete(phist);
06220
06221 return total_noise;
06222 }
06223
06224 static double irplib_compute_err(double gain, double ron, double FA)
06225 {
06226 double int_gain = (gain * gain - 1) / 12;
06227 if (int_gain < 0)
06228 {
06229 int_gain = 0;
06230 }
06231 return sqrt(ron * ron + FA / gain + int_gain);
06232 }
06233 static double irplib_fpn_lg(const cpl_image* f1, int* range, double gain ,
06234 FPN_METHOD fpn_method, int smooth_size, double* mse)
06235 {
06236 cpl_image* im_diff = 0;
06237 const cpl_image* im_f1 = f1;
06238 cpl_image* im_inrange1 = 0;
06239 double FA = 0;
06240 double s_tot = 0;
06241 double s_fpn = 0;
06242 double sr_fpn = 0;
06243
06244 if (gain<=0) {
06245
06246
06247 cpl_msg_warning(cpl_func,"gain[%f]<0", gain);
06248 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06249 s_fpn=-999.;
06250 sr_fpn=-999;
06251 return sr_fpn;
06252 }
06253 if (range)
06254 {
06255 im_inrange1 = cpl_image_extract(f1, range[0], range[1], range[2], range[3]);
06256 im_f1 = im_inrange1;
06257 }
06258 FA = cpl_image_get_median(im_f1);
06259
06260
06261
06262 switch (fpn_method)
06263 {
06264 case FPN_SMOOTH:
06265 cpl_msg_info(cpl_func,"SMOOTH method is used for FPN, pattern size[%d x %d] pixels",smooth_size,smooth_size );
06266 s_tot = irplib_calculate_total_noise_smooth(im_f1,smooth_size,smooth_size);
06267 break;
06268 case FPN_HISTOGRAM:
06269 cpl_msg_info(cpl_func,"HISTOGRAM method is used for FPN");
06270 s_tot = irplib_calculate_total_noise(im_f1);
06271 break;
06272 default:
06273 s_tot = -1;
06274 sr_fpn = -1;
06275 cpl_msg_warning(cpl_func,"fpn_method is not defined");
06276 break;
06277 }
06278 if (s_tot > 0)
06279 {
06280 if (FA<0)
06281 {
06282
06283
06284 cpl_msg_warning(cpl_func,"Median flux on sum of flats<0");
06285 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06286 s_fpn=-999.;
06287 sr_fpn=-999;
06288 }
06289
06290 if ((s_tot * s_tot - FA / gain) > 0)
06291 {
06292 s_fpn = sqrt(s_tot * s_tot - FA / gain);
06293 sr_fpn = s_fpn / FA;
06294 *mse = (irplib_compute_err(gain, 0, FA)) * gain / FA;
06295 } else {
06296
06297
06298 cpl_msg_warning(cpl_func,"s_tot * s_tot < FA / gain");
06299 cpl_msg_warning(cpl_func,"We set dummy values for FPN");
06300 s_fpn=-999.;
06301 sr_fpn=-999;
06302 *mse = -1;
06303 }
06304
06305
06306 }
06307 cpl_image_delete(im_diff);
06308 if (range)
06309 {
06310 cpl_image_delete(im_inrange1);
06311 }
06312 return sr_fpn;
06313 }
06314
06315 static cpl_imagelist * irplib_load_fset_wrp(const cpl_frameset * pframeset, cpl_type type , int whichext)
06316 {
06317 cpl_imagelist * ret = 0;
06318 ret = cpl_imagelist_load_frameset(pframeset, type,
06319 1, whichext);
06320 if (ret)
06321 {
06322
06323 int sz = cpl_imagelist_get_size(ret);
06324 int i = 0;
06325 for(i = 0; i < sz; i ++)
06326 {
06327 cpl_image* pimage = 0;
06328 pimage = cpl_imagelist_get(ret, i);
06329 if (pimage)
06330 {
06331 int size_x = 0;
06332 int size_y = 0;
06333 size_x = cpl_image_get_size_x(pimage);
06334 size_y = cpl_image_get_size_y(pimage);
06335 if (detmon_lg_config.nx != size_x || detmon_lg_config.ny != size_y)
06336 {
06337 cpl_msg_error(cpl_func, "All images in the input should have the same size,\n" \
06338 " image #%d has size x[%d] y[%d], expected size x[%d] y[%d]", i, size_x, size_y,
06339 detmon_lg_config.nx, detmon_lg_config.ny);
06340 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
06341 cpl_imagelist_delete(ret);
06342 ret = 0;
06343 }
06344 }
06345 }
06346 }
06347 return ret;
06348 }
06349
06350 static cpl_imagelist * irplib_load_fset_wrp_ext(const cpl_frameset * pframeset, cpl_type type , int whichext)
06351 {
06352 int i = whichext;
06353 cpl_imagelist* offs = cpl_imagelist_new();
06354 detmon_lg_config.load_fset(pframeset, type, offs);
06355 i++;
06356 return offs;
06357 }
06358
06359 static cpl_error_code irplib_table_create_column(cpl_table* ptable, cpl_propertylist* plist)
06360 {
06361 if (ptable && plist)
06362 {
06363 int size = cpl_propertylist_get_size(plist);
06364 int i = 0;
06365 for (i = 0; i < size; i++)
06366 {
06367 cpl_property* pprop = cpl_propertylist_get(plist,i);
06368 if (pprop)
06369 {
06370 const char* pname = cpl_property_get_name(pprop);
06371 if (pname)
06372 {
06373 cpl_table_new_column(ptable, pname, cpl_property_get_type(pprop));
06374 if (cpl_error_get_code() != CPL_ERROR_NONE)
06375 {
06376 cpl_msg_warning(cpl_func, "cannot create new column[%s], err[%s]", pname, cpl_error_get_message());
06377 break;
06378 }
06379 }
06380 }
06381 }
06382 }
06383 return cpl_error_get_code();
06384 }
06385
06386 static cpl_error_code irplib_fill_table_DETWINUIT(cpl_table* ptable, cpl_propertylist* plist, int row)
06387 {
06388 cpl_error_code err = CPL_ERROR_NONE;
06389 if (ptable && plist)
06390 {
06391 int size = cpl_propertylist_get_size(plist);
06392 int i = 0;
06393 for (i = 0; i < size; i++)
06394 {
06395 cpl_property* pprop = cpl_propertylist_get(plist,i);
06396 if (pprop)
06397 {
06398 const char* pname = cpl_property_get_name(pprop);
06399 double value = cpl_property_get_double(pprop);
06400 if (pname)
06401 {
06402 cpl_table_set_double(ptable, pname, row, value);
06403 if (cpl_error_get_code() != CPL_ERROR_NONE)
06404 {
06405 cpl_msg_warning(cpl_func, "cannot write value to the table, column[%s] value[%f], err[%s]", pname, value, cpl_error_get_message());
06406 cpl_error_reset();
06407 break;
06408 }
06409 }
06410 }
06411 }
06412 }
06413 return err;
06414 }
06415 cpl_error_code irplib_detmon_check_order(const double *exptime, int sz, double tolerance, int order)
06416 {
06417 int nsets = 0;
06418 int i = 0;
06419
06420 do
06421 {
06422 nsets++;
06423 do
06424 {
06425 i++;
06426 if(i == sz - 1)
06427 {
06428 break;
06429 }
06430 } while(fabs(exptime[i-1] - exptime[i]) < tolerance);
06431 } while(i < sz - 1);
06432
06433 if (!fabs(exptime[i-1] - exptime[i]) < tolerance) nsets++;
06434 if(nsets <= order)
06435 {
06436 char err_msg[80];
06437 sprintf(err_msg,"%s%s","Not enough frames for the polynomial",
06438 " fitting. nsets <= order");
06439 cpl_msg_error(cpl_func, err_msg);
06440 cpl_error_set(cpl_func, CPL_ERROR_INCOMPATIBLE_INPUT);
06441 }
06442 return cpl_error_get_code();
06443 }
06444
06445 static cpl_error_code irplib_detmon_lg_dfs_save_imagelist(
06446 cpl_frameset * frameset,
06447 const cpl_parameterlist * parlist,
06448 const cpl_frameset *usedframes,
06449 const cpl_imagelist *coeffs,
06450 const char *recipe_name,
06451 const cpl_propertylist *mypro_coeffscube,
06452 const char * package,
06453 const char * name_o)
06454 {
06455 return(cpl_dfs_save_imagelist
06456 (frameset, NULL, parlist, usedframes, NULL,coeffs, CPL_BPP_IEEE_FLOAT,
06457 recipe_name, mypro_coeffscube, NULL, package,
06458 name_o));
06459 }
06460 static void irplib_detmon_lg_add_empty_image(cpl_imagelist* imlist, int pos)
06461 {
06462 const cpl_image* first = cpl_imagelist_get(imlist, 0);
06463 if (first)
06464 {
06465 int x = cpl_image_get_size_x(first);
06466 int y = cpl_image_get_size_y(first);
06467 cpl_type type = cpl_image_get_type(first);
06468 cpl_image * blank = cpl_image_new(x, y, type);
06469 cpl_imagelist_set(imlist, blank, pos);
06470 }
06471 }