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