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