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