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 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #ifdef HAVE_FFTW
00037 #include <complex.h>
00038
00039 #include <sfftw.h>
00040
00041 #endif
00042
00043
00044
00045 #include <math.h>
00046 #include <string.h>
00047 #include <assert.h>
00048
00049 #include <cpl.h>
00050
00051 #include "irplib_detmon.h"
00052 #include "irplib_detmon_lg.h"
00053
00054 #include "irplib_utils.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 static struct
00070 {
00071 const char * method;
00072
00073 int order;
00074 int kappa;
00075 int niter;
00076 int threshold_min;
00077 int threshold_max;
00078 int llx;
00079 int lly;
00080 int urx;
00081 int ury;
00082 int ref_level;
00083 int threshold;
00084 int m;
00085 int n;
00086 int llx1;
00087 int lly1;
00088 int urx1;
00089 int ury1;
00090 int llx2;
00091 int lly2;
00092 int urx2;
00093 int ury2;
00094 int llx3;
00095 int lly3;
00096 int urx3;
00097 int ury3;
00098 int llx4;
00099 int lly4;
00100 int urx4;
00101 int ury4;
00102 int llx5;
00103 int lly5;
00104 int urx5;
00105 int ury5;
00106 cpl_boolean autocorr;
00107 cpl_boolean intermediate;
00108 cpl_boolean collapse;
00109 cpl_boolean rescale;
00110 cpl_boolean pix2pix;
00111 cpl_boolean bpmbin;
00112 int filter;
00113 double tolerance;
00114 const char * pafname;
00115
00116 double cr;
00117 int exts;
00118 int nb_extensions;
00119 double lamp_stability;
00120 cpl_boolean lamp_ok;
00121 } detmon_lg_config;
00122
00123
00124
00125
00126
00127
00128
00129 static cpl_error_code
00130 irplib_detmon_lg_retrieve_parlist(const char *,
00131 const char *, const cpl_parameterlist *,
00132 cpl_boolean);
00133
00134
00135 static cpl_error_code
00136 irplib_detmon_lg_split_onoff(const cpl_frameset *,
00137 cpl_frameset *,
00138 cpl_frameset *,
00139 const char *, const char * );
00140
00141 static cpl_error_code
00142 irplib_detmon_lg_reduce(const cpl_frameset *,
00143 const cpl_frameset *,
00144 int *,
00145 int *,
00146 int,
00147 cpl_imagelist **,
00148 cpl_table *,
00149 cpl_table *,
00150 cpl_image **,
00151 cpl_imagelist *,
00152 cpl_imagelist *,
00153 cpl_propertylist *,
00154 int (* load_fset) (const cpl_frameset *,
00155 cpl_type,
00156 cpl_imagelist *),
00157 const cpl_boolean, int);
00158
00159 static cpl_error_code
00160 irplib_detmon_linearity(const cpl_frameset *,
00161 cpl_table *,
00162 cpl_table *,
00163 cpl_imagelist *,
00164 cpl_imagelist *,
00165 cpl_imagelist *,
00166 const int,
00167 const int, cpl_propertylist *,
00168 const cpl_boolean);
00169
00170 static cpl_error_code
00171 irplib_detmon_gain_table_fill_row(cpl_table *,
00172 cpl_imagelist *,
00173 cpl_imagelist *,
00174 const cpl_imagelist *,
00175 const cpl_imagelist *,
00176 double, int,
00177 int, int, int, int,
00178 int, int, const int, unsigned);
00179
00180 static cpl_error_code
00181 irplib_detmon_lg_save(const cpl_parameterlist *,
00182 cpl_frameset *,
00183 const char *,
00184 const char *,
00185 const char *,
00186 const char *,
00187 const char *,
00188 const char *,
00189 const char *,
00190 const char *,
00191 const char *,
00192 const char *,
00193 cpl_imagelist *,
00194 cpl_table *,
00195 cpl_table *,
00196 cpl_image *,
00197 cpl_imagelist *,
00198 cpl_imagelist *,
00199 cpl_propertylist *,
00200 const int, const int, const cpl_frameset *,
00201 int);
00202
00203 static cpl_error_code
00204 irplib_detmon_lg_qc_ptc(const cpl_table *,
00205 cpl_propertylist *, unsigned);
00206
00207 static cpl_error_code
00208 irplib_detmon_lg_qc_med(const cpl_table *,
00209 cpl_propertylist *);
00210
00211 static cpl_error_code
00212 irplib_detmon_pair_extract(const cpl_frameset *,
00213 int *, int,
00214 int ,
00215 int *,
00216 int,
00217 cpl_frameset **);
00218
00219
00220
00221 static double
00222 irplib_pfits_get_dit(const cpl_propertylist *);
00223
00224 static double
00225 irplib_pfits_get_dit_opt(const cpl_propertylist *);
00226
00227
00228 static cpl_image *irplib_detmon_bpixs(const cpl_imagelist *, int *);
00229
00230 static double
00231 irplib_detmon_autocorr_factor(const cpl_image *,
00232 cpl_image **, int, int);
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 static cpl_error_code
00245 irplib_detmon_opt_contamination(const cpl_image *, cpl_propertylist *);
00246
00247
00248
00249
00250
00251 int
00252 irplib_detmon_lg_dfs_set_groups(cpl_frameset *, const char *, const char *);
00253
00254 static cpl_error_code
00255 irplib_detmon_lg_reduce_all(const cpl_table *,
00256 cpl_propertylist *,
00257 cpl_imagelist **,
00258 cpl_image **,
00259 const cpl_imagelist *,
00260 const cpl_table *, int);
00261
00262 static cpl_error_code
00263 irplib_detmon_lg_check_defaults(const cpl_image *);
00264
00265 static cpl_error_code
00266 irplib_detmon_lg_rescale(cpl_imagelist *);
00267
00268 static cpl_error_code
00269 irplib_detmon_lg_reduce_init(cpl_table *,
00270 cpl_table *,
00271 cpl_imagelist **);
00272
00273
00274
00275 static cpl_error_code
00276 irplib_detmon_add_adl_column(cpl_table *);
00277
00278 static cpl_error_code
00279 irplib_detmon_lg_lamp_stab(const cpl_frameset *,
00280 const cpl_frameset *,
00281 cpl_boolean);
00282
00283
00284 static cpl_error_code
00285 irplib_detmon_lg_reduce_dit(const cpl_frameset *,
00286 int *,
00287 int ,
00288 int ,
00289 const cpl_frameset *,
00290 int *,
00291 cpl_table *,
00292 cpl_table *,
00293 cpl_imagelist *,
00294 cpl_propertylist *,
00295 cpl_boolean ,
00296 cpl_imagelist *,
00297 cpl_imagelist *,
00298 cpl_imagelist *,
00299 int (*)(const cpl_frameset *,
00300 cpl_type,
00301 cpl_imagelist *), int);
00302
00303 static cpl_error_code
00304 irplib_detmon_lg_core(cpl_frameset *,
00305 cpl_frameset *,
00306 int *,
00307 int *,
00308 int ,
00309 int ,
00310 int ,
00311 const char *,
00312 const char *,
00313 const char *,
00314 const char *,
00315 const char *,
00316 const char *,
00317 const char *,
00318 const char *,
00319 const char *,
00320 const char *,
00321 int (*) (const cpl_frameset *,
00322 cpl_type,
00323 cpl_imagelist *),
00324 int, cpl_boolean,
00325 cpl_frameset *, const cpl_parameterlist *, cpl_frameset *);
00326
00327 static cpl_error_code
00328 irplib_detmon_lg_lineff(double *, cpl_propertylist *);
00329
00330
00331 static int
00332 irplib_detmon_lg_compare_pairs(const cpl_frame *,
00333 const cpl_frame *);
00334
00335 static cpl_error_code
00336 irplib_detmon_gain_table_create(cpl_table *);
00337
00338 static cpl_vector *
00339 irplib_detmon_lg_find_dits(const cpl_vector * exptimes);
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 cpl_error_code
00418 irplib_detmon_lg(cpl_frameset * frameset,
00419 const cpl_parameterlist * parlist,
00420 const char * tag_on,
00421 const char * tag_off,
00422 const char * recipe_name,
00423 const char * pipeline_name,
00424 const char * pafregexp,
00425 const char * procatg_lintbl,
00426 const char * procatg_gaintbl,
00427 const char * procatg_coeffscube,
00428 const char * procatg_bpm,
00429 const char * procatg_corr,
00430 const char * procatg_diff,
00431 const char * package,
00432 int (* compare) (const cpl_frame *,
00433 const cpl_frame *),
00434 int (* load_fset) (const cpl_frameset *,
00435 cpl_type,
00436 cpl_imagelist *),
00437 const cpl_boolean opt_nir)
00438 {
00439 int nsets;
00440 int * selection = NULL;
00441 int i;
00442 cpl_frame * first = NULL;
00443 cpl_image * reference = NULL;
00444 cpl_frameset * set = NULL;
00445
00446
00447
00448
00449
00450
00451 int * selection_on = NULL;
00452 int * selection_off = NULL;
00453 cpl_frameset * cur_fset = NULL;
00454 cpl_frameset * cur_fset_on = NULL;
00455 cpl_frameset * cur_fset_off = NULL;
00456
00457
00458 cpl_ensure_code(frameset != NULL, CPL_ERROR_NULL_INPUT);
00459 cpl_ensure_code(parlist != NULL, CPL_ERROR_NULL_INPUT);
00460 cpl_ensure_code(tag_on != NULL, CPL_ERROR_NULL_INPUT);
00461 cpl_ensure_code(tag_off != NULL, CPL_ERROR_NULL_INPUT);
00462 cpl_ensure_code(recipe_name != NULL, CPL_ERROR_NULL_INPUT);
00463 cpl_ensure_code(pipeline_name != NULL, CPL_ERROR_NULL_INPUT);
00464 cpl_ensure_code(procatg_lintbl != NULL, CPL_ERROR_NULL_INPUT);
00465 cpl_ensure_code(procatg_gaintbl != NULL, CPL_ERROR_NULL_INPUT);
00466 cpl_ensure_code(procatg_coeffscube != NULL, CPL_ERROR_NULL_INPUT);
00467 cpl_ensure_code(procatg_bpm != NULL, CPL_ERROR_NULL_INPUT);
00468 cpl_ensure_code(procatg_corr != NULL, CPL_ERROR_NULL_INPUT);
00469 cpl_ensure_code(procatg_diff != NULL, CPL_ERROR_NULL_INPUT);
00470 cpl_ensure_code(package != NULL, CPL_ERROR_NULL_INPUT);
00471
00472 skip_if (irplib_detmon_lg_dfs_set_groups(frameset, tag_on, tag_off));
00473
00474
00475
00476
00477
00478 irplib_ensure(!(opt_nir == NIR &&
00479 cpl_frameset_get_size(frameset) % 4 != 0),
00480 CPL_ERROR_ILLEGAL_INPUT,
00481 "For NIR data an even number of ON frames "
00482 "and an even number of off frames is required");
00483
00484
00485 skip_if (irplib_detmon_lg_retrieve_parlist(pipeline_name, recipe_name,
00486 parlist, opt_nir));
00487
00488
00489
00490
00491
00492
00493 first = cpl_frameset_get_first(frameset);
00494 irplib_ensure (first != NULL, CPL_ERROR_ILLEGAL_INPUT, "Empty data set!");
00495
00496 if (detmon_lg_config.exts < 0) {
00497 reference = cpl_image_load(cpl_frame_get_filename(first),
00498 CPL_TYPE_FLOAT, 0, 1);
00499 } else {
00500 if (load_fset != NULL) {
00501 cpl_frameset * new = cpl_frameset_new();
00502 cpl_imagelist * p = cpl_imagelist_new();
00503 cpl_frameset_insert(new, cpl_frame_duplicate(first));
00504 (*load_fset)(new, CPL_TYPE_FLOAT, p);
00505 reference = cpl_image_duplicate(cpl_imagelist_get(p, 0));
00506 cpl_imagelist_delete(p);
00507 cpl_frameset_delete(new);
00508 } else {
00509 cpl_msg_info(cpl_func,"name=%s",cpl_frame_get_filename(first));
00510 reference = cpl_image_load(cpl_frame_get_filename(first),
00511 CPL_TYPE_FLOAT, 0, detmon_lg_config.exts);
00512 }
00513 }
00514 skip_if (reference == NULL);
00515
00516 skip_if (irplib_detmon_lg_check_defaults(reference));
00517
00518
00519 set = cpl_frameset_duplicate(frameset);
00520
00521
00522
00523
00524
00525 if (compare == NULL) {
00526 nsets = 1;
00527 } else {
00528 cpl_msg_info(cpl_func, "Identifying different settings");
00529 selection = cpl_frameset_labelise(set, compare, &nsets);
00530 skip_if (selection == NULL);
00531 }
00532
00533
00534 detmon_lg_config.nb_extensions = 1;
00535 if (detmon_lg_config.exts < 0) {
00536 detmon_lg_config.nb_extensions = cpl_frame_get_nextensions(first);
00537 }
00538
00539
00540 for(i = 0; i < nsets; i++) {
00541 int j;
00542 int nexts = detmon_lg_config.nb_extensions;
00543
00544 int nsets_on = 0;
00545 int nsets_off = 0;
00546
00547
00548 cpl_msg_info(cpl_func, "Reduce data set nb %d out of %d",
00549 i + 1, nsets);
00550
00551 cur_fset = nsets == 1 ?
00552 cpl_frameset_duplicate(set) :
00553 cpl_frameset_extract(set, selection, i);
00554 skip_if(cur_fset == NULL);
00555
00556
00557 cur_fset_on = cpl_frameset_new();
00558 cur_fset_off = cpl_frameset_new();
00559 cpl_msg_info(cpl_func, "Splitting into ON and OFF sub-framesets");
00560 skip_if (irplib_detmon_lg_split_onoff(cur_fset,
00561 cur_fset_on, cur_fset_off,
00562 tag_on, tag_off ));
00563
00564
00565 selection_on = cpl_frameset_labelise(cur_fset_on,
00566 irplib_detmon_lg_compare_pairs,
00567 &nsets_on);
00568 skip_if (selection_on == NULL);
00569
00570 if (!detmon_lg_config.collapse) {
00571 selection_off = cpl_frameset_labelise(cur_fset_off,
00572 irplib_detmon_lg_compare_pairs,
00573 &nsets_off);
00574 skip_if (selection_off == NULL);
00575 }
00576
00577
00578 if (!detmon_lg_config.collapse) {
00579 skip_if(nsets_on != nsets_off);
00580 }
00581
00582 if(nsets_on <= detmon_lg_config.order) {
00583 cpl_msg_error(cpl_func, "Not enough frames for the polynomial"
00584 " fitting. nsets <= order.");
00585 skip_if(1);
00586 }
00587
00588 if(detmon_lg_config.exts >= 0) {
00589
00590
00591
00592
00593
00594
00595
00596
00597 skip_if(irplib_detmon_lg_core(cur_fset_on, cur_fset_off, selection_on,
00598 selection_off, nsets_on, detmon_lg_config.exts, i, recipe_name, pipeline_name, pafregexp, procatg_lintbl, procatg_gaintbl, procatg_coeffscube, procatg_bpm, procatg_corr, procatg_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
00599 } else {
00600 for(j = 1; j <= nexts; j++) {
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 skip_if(irplib_detmon_lg_core(cur_fset_on, cur_fset_off, selection_on,
00612 selection_off, nsets_on, j, i, recipe_name, pipeline_name,pafregexp, procatg_lintbl, procatg_gaintbl, procatg_coeffscube, procatg_bpm, procatg_corr, procatg_diff, package, load_fset, nsets, opt_nir, frameset, parlist, cur_fset));
00613 }
00614 }
00615
00616
00617 cpl_free(selection_on);
00618 cpl_free(selection_off);
00619
00620 cpl_frameset_delete(cur_fset);
00621 cpl_frameset_delete(cur_fset_on);
00622 cpl_frameset_delete(cur_fset_off);
00623
00624 selection_on = NULL;
00625 selection_off = NULL;
00626 cur_fset = NULL;
00627 cur_fset_on = NULL;
00628 cur_fset_off = NULL;
00629 }
00630
00631 end_skip;
00632
00633 cpl_free(selection_on);
00634 cpl_free(selection_off);
00635
00636 cpl_frameset_delete(cur_fset);
00637 cpl_frameset_delete(cur_fset_on);
00638 cpl_frameset_delete(cur_fset_off);
00639
00640 cpl_frameset_delete(set);
00641 cpl_free(selection);
00642 cpl_image_delete(reference);
00643
00644 return cpl_error_get_code();
00645 }
00646
00647
00680
00681
00682 static cpl_error_code
00683 irplib_detmon_lg_core(cpl_frameset * cur_fset_on,
00684 cpl_frameset * cur_fset_off,
00685 int * selection_on,
00686 int * selection_off,
00687 int nsets_on,
00688 int whichext,
00689 int whichset,
00690 const char * recipe_name,
00691 const char * pipeline_name,
00692 const char * pafregexp,
00693 const char * procatg_lintbl,
00694 const char * procatg_gaintbl,
00695 const char * procatg_coeffscube,
00696 const char * procatg_bpm,
00697 const char * procatg_diff,
00698 const char * procatg_corr,
00699 const char * package,
00700 int (* load_fset) (const cpl_frameset *,
00701 cpl_type,
00702 cpl_imagelist *),
00703 int nsets, cpl_boolean opt_nir,
00704 cpl_frameset * frameset, const cpl_parameterlist * parlist,
00705 cpl_frameset * cur_fset)
00706 {
00707 cpl_table * gain_table = cpl_table_new(cpl_frameset_get_size(cur_fset_on)/2);
00708 cpl_table * linear_table = cpl_table_new(cpl_frameset_get_size(cur_fset_on)/2);
00709 cpl_imagelist * coeffs = NULL;
00710 cpl_image * bpm = NULL;
00711 cpl_imagelist * autocorr_images = NULL;
00712 cpl_imagelist * diff_flats = NULL;
00713 cpl_propertylist * qclist = NULL;
00714
00715
00716 cpl_msg_info(cpl_func, "Reduce extension nb %d ",
00717 whichext);
00718
00719
00720
00721 if (detmon_lg_config.intermediate) {
00722 autocorr_images = cpl_imagelist_new();
00723 diff_flats = cpl_imagelist_new();
00724 }
00725 qclist = cpl_propertylist_new();
00726
00727
00728 cpl_msg_info(cpl_func, "Starting data reduction");
00729 skip_if(irplib_detmon_lg_reduce(cur_fset_on, cur_fset_off,
00730 selection_on, selection_off,
00731 nsets_on, &coeffs, gain_table,
00732 linear_table, &bpm, autocorr_images,
00733 diff_flats, qclist, load_fset,
00734 opt_nir, whichext));
00735
00736
00737 cpl_msg_info(cpl_func, "Saving the products");
00738 if(nsets == 1) {
00739 skip_if(irplib_detmon_lg_save(parlist, frameset, recipe_name,
00740 pipeline_name, pafregexp,
00741 procatg_lintbl, procatg_gaintbl,
00742 procatg_coeffscube, procatg_bpm,
00743 procatg_corr, procatg_diff, package,
00744 coeffs, gain_table, linear_table,
00745 bpm, autocorr_images, diff_flats,
00746 qclist, 0, 0, cur_fset, whichext));
00747 } else {
00748 skip_if(irplib_detmon_lg_save(parlist, frameset, recipe_name,
00749 pipeline_name, pafregexp,
00750 procatg_lintbl, procatg_gaintbl,
00751 procatg_coeffscube, procatg_bpm,
00752 procatg_corr, procatg_diff, package,
00753 coeffs, gain_table, linear_table,
00754 bpm, autocorr_images, diff_flats,
00755 qclist, 1, whichset+ 1, cur_fset, whichext));
00756 }
00757
00758 end_skip;
00759
00760
00761 cpl_table_delete(gain_table);
00762 cpl_table_delete(linear_table);
00763 cpl_imagelist_delete(coeffs);
00764 cpl_propertylist_delete(qclist);
00765 cpl_image_delete(bpm);
00766 cpl_imagelist_delete(autocorr_images);
00767 cpl_imagelist_delete(diff_flats);
00768
00769 return cpl_error_get_code();
00770 }
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 #ifdef HAVE_FFTW
00791
00792 cpl_image *
00793 irplib_detmon_image_correlate(const cpl_image * image1,
00794 const cpl_image * image2,
00795 const int m, const int n)
00796 {
00797 cpl_image *image1_padded;
00798 cpl_image *image2_padded;
00799 float *data1;
00800 float *data2;
00801 int nx, ny;
00802 int nx2, ny2;
00803 int i;
00804
00805 fftwnd_plan p1;
00806 fftw_complex *in1;
00807 fftw_complex *ri1;
00808
00809 fftwnd_plan p2;
00810 fftw_complex *in2;
00811 fftw_complex *ri2;
00812
00813 fftwnd_plan p_inv;
00814 fftw_complex *in_inv;
00815 fftw_complex *ri_inv;
00816
00817 fftw_complex *corr;
00818 float *corr_r;
00819
00820 cpl_image *corr_image;
00821 cpl_image *corr_image_window;
00822 cpl_image *reorganised;
00823 cpl_image *image;
00824
00825
00826
00827
00828
00829 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
00830 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
00831
00832 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
00833 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
00834
00835 nx = cpl_image_get_size_x(image1);
00836 ny = cpl_image_get_size_y(image1);
00837
00838 nx2 = cpl_image_get_size_x(image2);
00839 ny2 = cpl_image_get_size_y(image2);
00840
00841
00842 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
00843
00844
00845 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
00846 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
00847
00848 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
00849 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
00850
00851
00852 data1 = cpl_image_get_data_float(image1_padded);
00853 data2 = cpl_image_get_data_float(image2_padded);
00854
00855
00856 nx = nx + 2 * m;
00857 ny = ny + 2 * n;
00858
00859
00860 in1 = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00861 ri1 = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00862
00863 p1 = fftw2d_create_plan_specific(ny, nx, FFTW_FORWARD, FFTW_ESTIMATE,
00864 in1, 1, ri1, 1);
00865
00866
00867 for(i = 0; i < nx * ny; i++) {
00868 *((float complex *)in1 + i) = (*(data1 + i) + 0.0 * I);
00869 }
00870
00871
00872 fftwnd_one(p1, in1, ri1);
00873
00874
00875 fftwnd_destroy_plan(p1);
00876 cpl_image_delete(image1_padded);
00877
00878
00879 in2 = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00880 ri2 = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00881
00882
00883 ; p2 = fftw2d_create_plan_specific(ny, nx, FFTW_FORWARD, FFTW_ESTIMATE,
00884 in2, 1, ri2, 1);
00885
00886
00887
00888 for(i = 0; i < nx * ny; i++) {
00889 *((float complex *)in2 + i) = (*(data2 + i) + 0.0 * I);
00890 }
00891
00892
00893 fftwnd_one(p2, in2, ri2);
00894
00895
00896 fftwnd_destroy_plan(p2);
00897 cpl_image_delete(image2_padded);
00898
00899
00900 in_inv = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00901 ri_inv = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00902
00903
00904 p_inv = fftw2d_create_plan_specific(ny, nx, FFTW_FORWARD, FFTW_ESTIMATE,
00905 in_inv, 1, ri_inv, 1);
00906
00907
00908 for(i = 0; i < nx * ny; i++) {
00909 *((float complex *)in_inv + i) = conjf(*((float complex *)ri1 + i)) *
00910 (*((float complex *)ri2+i));
00911 }
00912
00913
00914 fftw_free(in1);
00915 fftw_free(ri1);
00916
00917 fftw_free(in2);
00918 fftw_free(ri2);
00919
00920
00921 fftwnd_one(p_inv, in_inv, ri_inv);
00922
00923
00924 fftwnd_destroy_plan(p_inv);
00925
00926
00927 corr = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * nx * ny);
00928 corr_r = (float *) cpl_malloc(sizeof(float) * nx * ny);
00929
00930 for(i = 0; i < nx * ny; i++) {
00931 *((float complex *)corr + i) = conjf(*((float complex *)ri_inv + i));
00932 *((float complex *)corr + i) *= *((float complex *)ri_inv + i);
00933 *(corr_r + i) = crealf(*((float complex *)corr + i));
00934 }
00935 fftw_free(in_inv);
00936 fftw_free(ri_inv);
00937
00938
00939 corr_image = cpl_image_wrap_float(nx, ny, corr_r);
00940
00941
00942 fftw_free(corr);
00943
00944
00945
00946
00947 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00948
00949 image = cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
00950 cpl_image_copy(reorganised, image, 1, 1);
00951 cpl_image_delete(image);
00952
00953 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
00954 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
00955 cpl_image_delete(image);
00956
00957 cpl_image_unwrap(corr_image);
00958 cpl_free(corr_r);
00959
00960 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00961
00962 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
00963 cpl_image_copy(corr_image, image, 1, 1);
00964 cpl_image_delete(image);
00965
00966 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
00967 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
00968 cpl_image_delete(image);
00969
00970
00971 corr_image_window = cpl_image_extract(corr_image,
00972 nx / 2 + 1 - m,
00973 ny / 2 + 1 - n,
00974 nx / 2 + 1 + m, ny / 2 + 1 + n);
00975
00976
00977 cpl_image_delete(reorganised);
00978 cpl_image_delete(corr_image);
00979
00980 if(cpl_image_divide_scalar(corr_image_window,
00981 cpl_image_get_max(corr_image_window))) {
00982 cpl_image_delete(corr_image_window);
00983 return NULL;
00984 }
00985
00986 return corr_image_window;
00987 }
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 #endif
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 cpl_image *
01133 irplib_detmon_autocorrelate(const cpl_image * input2, const int m,
01134 const int n)
01135 {
01136 cpl_image *im_re = NULL;
01137 cpl_image *im_im = NULL;
01138 int nx, ny;
01139 cpl_image *ifft_re = NULL;
01140 cpl_image *ifft_im = NULL;
01141 cpl_image *autocorr = NULL;
01142 cpl_image *autocorr_norm_double = NULL;
01143 cpl_image *autocorr_norm = NULL;
01144
01145
01146 cpl_image *reorganised = NULL;
01147 cpl_image *image = NULL;
01148 int p;
01149 cpl_error_code error;
01150 cpl_image *input;
01151
01152 cpl_ensure(input2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
01153
01154 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
01155 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
01156
01157 nx = cpl_image_get_size_x(input2) + 2 * m;
01158 ny = cpl_image_get_size_y(input2) + 2 * n;
01159
01160 p = 128;
01161 while(nx > p || ny > p) {
01162 p *= 2;
01163 }
01164
01165 input = cpl_image_cast(input2, CPL_TYPE_DOUBLE);
01166
01167 im_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01168 error = cpl_image_copy(im_re, input, 1, 1);
01169 cpl_ensure(!error, error, NULL);
01170
01171 im_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01172
01173 error = cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
01174 cpl_ensure(!error, error, NULL);
01175
01176 ifft_re = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01177
01178
01179 error = cpl_image_power(im_re, 2);
01180 cpl_ensure(!error, error, NULL);
01181
01182 error = cpl_image_add(ifft_re, im_re);
01183 cpl_ensure(!error, error, NULL);
01184
01185 cpl_image_delete(im_re);
01186
01187 error = cpl_image_power(im_im, 2);
01188 cpl_ensure(!error, error, NULL);
01189
01190 error = cpl_image_add(ifft_re, im_im);
01191 cpl_ensure(!error, error, NULL);
01192
01193 cpl_image_delete(im_im);
01194
01195 ifft_im = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01196
01197 error = cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
01198 cpl_ensure(!error, error, NULL);
01199
01200 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01201
01202 error = cpl_image_power(ifft_re, 2);
01203 cpl_ensure(!error, error, NULL);
01204
01205 error = cpl_image_add(autocorr, ifft_re);
01206 cpl_ensure(!error, error, NULL);
01207
01208 cpl_image_delete(ifft_re);
01209
01210 error = cpl_image_power(ifft_im, 2);
01211 cpl_ensure(!error, error, NULL);
01212
01213 error = cpl_image_add(autocorr, ifft_im);
01214 cpl_ensure(!error, error, NULL);
01215
01216 cpl_image_delete(ifft_im);
01217
01218
01219
01220
01221
01222
01223 reorganised = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01224
01225 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
01226 cpl_image_copy(reorganised, image, 1, 1);
01227 cpl_image_delete(image);
01228
01229 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
01230 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
01231 cpl_image_delete(image);
01232
01233 cpl_image_delete(autocorr);
01234
01235 autocorr = cpl_image_new(p, p, CPL_TYPE_DOUBLE);
01236
01237 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
01238 cpl_image_copy(autocorr, image, 1, 1);
01239 cpl_image_delete(image);
01240
01241 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
01242 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
01243 cpl_image_delete(image);
01244
01245 cpl_image_delete(reorganised);
01246
01247 autocorr_norm_double =
01248 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
01249 p / 2 + 1 + m, p / 2 + 1 + n);
01250
01251 cpl_image_delete(autocorr);
01252
01253 if(cpl_image_divide_scalar(autocorr_norm_double,
01254 cpl_image_get_max(autocorr_norm_double))) {
01255 cpl_image_delete(autocorr_norm_double);
01256 cpl_ensure(0, cpl_error_get_code(), NULL);
01257 }
01258
01259
01260 autocorr_norm = cpl_image_cast(autocorr_norm_double, CPL_TYPE_FLOAT);
01261 cpl_image_delete(autocorr_norm_double);
01262
01263 cpl_image_delete(input);
01264
01265 return autocorr_norm;
01266 }
01267
01268
01279
01280 cpl_error_code
01281 irplib_detmon_lg_fill_parlist_nir_default(cpl_parameterlist * parlist,
01282 const char *recipe_name,
01283 const char *pipeline_name)
01284 {
01285 const cpl_error_code error =
01286 irplib_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01287 "PTC",
01288 3,
01289 3,
01290 25,
01291 -1,
01292 -1,
01293 -1,
01294 -1,
01295 10000,
01296 "CPL_FALSE",
01297 "CPL_FALSE",
01298 "CPL_FALSE",
01299 "CPL_TRUE",
01300 "CPL_TRUE",
01301 "CPL_FALSE",
01302 -1,
01303 26,
01304 26,
01305 1e-3,
01306 recipe_name,
01307 -1,
01308 -1,
01309 -1,
01310 -1,
01311 -1,
01312 -1,
01313 -1,
01314 -1,
01315 -1,
01316 -1,
01317 -1,
01318 -1,
01319 -1,
01320 -1,
01321 -1,
01322 -1,
01323 -1,
01324 -1,
01325 -1,
01326 -1,
01327 0,
01328 NIR);
01329
01330
01331 cpl_ensure_code(!error, error);
01332
01333 return cpl_error_get_code();
01334 }
01335
01336
01347
01348 cpl_error_code
01349 irplib_detmon_lg_fill_parlist_opt_default(cpl_parameterlist * parlist,
01350 const char *recipe_name,
01351 const char *pipeline_name)
01352 {
01353 const cpl_error_code error =
01354 irplib_detmon_lg_fill_parlist(parlist, recipe_name, pipeline_name,
01355 "PTC",
01356 3,
01357 3,
01358 25,
01359 -1,
01360 -1,
01361 -1,
01362 -1,
01363 10000,
01364 "CPL_FALSE",
01365 "CPL_FALSE",
01366 "CPL_TRUE",
01367 "CPL_TRUE",
01368 "CPL_FALSE",
01369 "CPL_FALSE",
01370 -1,
01371 26,
01372 26,
01373 1e-3,
01374 recipe_name,
01375 -1,
01376 -1,
01377 -1,
01378 -1,
01379 -1,
01380 -1,
01381 -1,
01382 -1,
01383 -1,
01384 -1,
01385 -1,
01386 -1,
01387 -1,
01388 -1,
01389 -1,
01390 -1,
01391 -1,
01392 -1,
01393 -1,
01394 -1,
01395 0,
01396 OPT);
01397
01398 cpl_ensure_code(!error, error);
01399
01400 return cpl_error_get_code();
01401 }
01402
01403
01457
01458 cpl_error_code
01459 irplib_detmon_lg_fill_parlist(cpl_parameterlist * parlist,
01460 const char *recipe_name, const char *pipeline_name,
01461 const char *method,
01462 int order,
01463 int kappa,
01464 int niter,
01465 int llx,
01466 int lly,
01467 int urx,
01468 int ury,
01469 int ref_level,
01470 const char *intermediate,
01471 const char *autocorr,
01472 const char *collapse,
01473 const char *rescale,
01474 const char *pix2pix,
01475 const char *bpmbin,
01476 int filter,
01477 int m,
01478 int n,
01479 double tolerance,
01480 const char * pafname,
01481 int llx1,
01482 int lly1,
01483 int urx1,
01484 int ury1,
01485 int llx2,
01486 int lly2,
01487 int urx2,
01488 int ury2,
01489 int llx3,
01490 int lly3,
01491 int urx3,
01492 int ury3,
01493 int llx4,
01494 int lly4,
01495 int urx4,
01496 int ury4,
01497 int llx5, int lly5, int urx5, int ury5, int exts,
01498 cpl_boolean opt_nir)
01499 {
01500 const cpl_error_code error =
01501 irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 21,
01502 "method",
01503 "Method to be used when computing GAIN. Methods appliable: <PTC | MED>. By default PTC method will be applied.",
01504 "CPL_TYPE_STRING", method,
01505
01506 "order",
01507 "Polynomial order for the fit (Linearity)",
01508 "CPL_TYPE_INT", order,
01509 "kappa",
01510 "Kappa value for the kappa-sigma clipping (Gain)",
01511 "CPL_TYPE_INT", kappa,
01512 "niter",
01513 "Number of iterations to compute rms (Gain)",
01514 "CPL_TYPE_INT", niter,
01515 "llx",
01516 "x coordinate of the lower-left "
01517 "point of the region of interest. If not modified, default value will be 1.",
01518 "CPL_TYPE_INT", llx,
01519 "lly",
01520 "y coordinate of the lower-left "
01521 "point of the region of interest. If not modified, default value will be 1.",
01522 "CPL_TYPE_INT", lly,
01523 "urx",
01524 "x coordinate of the upper-right "
01525 "point of the region of interest. If not modified, default value will be X dimension of the input image.",
01526 "CPL_TYPE_INT", urx,
01527 "ury",
01528 "y coordinate of the upper-right "
01529 "point of the region of interest. If not modified, default value will be Y dimension of the input image.",
01530 "CPL_TYPE_INT", ury,
01531 "ref_level",
01532 "User reference level",
01533 "CPL_TYPE_INT", ref_level,
01534 "intermediate",
01535 "De-/Activate intermediate products",
01536 "CPL_TYPE_BOOL", intermediate,
01537 "autocorr",
01538 "De-/Activate the autocorr option",
01539 "CPL_TYPE_BOOL", autocorr,
01540 "collapse",
01541 "De-/Activate the collapse option",
01542 "CPL_TYPE_BOOL", collapse,
01543 "rescale",
01544 "De-/Activate the collapse option",
01545 "CPL_TYPE_BOOL", rescale,
01546 "pix2pix",
01547 "De-/Activate the pix2pix option",
01548 "CPL_TYPE_BOOL", pix2pix,
01549 "bpmbin",
01550 "De-/Activate the binary bpm option",
01551 "CPL_TYPE_BOOL", bpmbin,
01552 "m",
01553 "Maximum x-shift for the autocorr",
01554 "CPL_TYPE_INT", m,
01555 "filter",
01556 "Upper limit of Median flux to be filtered",
01557 "CPL_TYPE_INT", filter,
01558 "n",
01559 "Maximum y-shift for the autocorr",
01560 "CPL_TYPE_INT", n,
01561 "tolerance",
01562 "Tolerance for pair discrimination",
01563 "CPL_TYPE_DOUBLE", tolerance,
01564 "pafname",
01565 "Specific name for PAF file",
01566 "CPL_TYPE_STRING", pafname,
01567
01568 "exts",
01569 "Activate the multi-exts option",
01570 "CPL_TYPE_INT", exts);
01571
01572
01573 if(opt_nir == FALSE) {
01574 const cpl_error_code erroropt =
01575 irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 20,
01576 "llx1",
01577 "x coord of the lower-left point of the first "
01578 "field used for contamination measurement. If not modified, default value will be 1.",
01579 "CPL_TYPE_INT", llx1,
01580 "lly1",
01581 "y coord of the lower-left point of the first "
01582 "field used for contamination measurement. If not modified, default value will be 1.",
01583 "CPL_TYPE_INT", lly1,
01584 "urx1",
01585 "x coord of the upper-right point of the first "
01586 "field used for contamination measurement. If not modified, default value will be X dimension of the input image.",
01587 "CPL_TYPE_INT", urx1,
01588 "ury1",
01589 "y coord of the upper-right point of the first "
01590 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01591 "CPL_TYPE_INT", ury1,
01592 "llx2",
01593 "x coord of the lower-left point of the second "
01594 "field used for contamination measurement. If not modified, default value will be 1.",
01595 "CPL_TYPE_INT", llx2,
01596 "lly2",
01597 "y coord of the lower-left point of the second "
01598 "field used for contamination measurement. If not modified, default value will be 1.",
01599 "CPL_TYPE_INT", lly2,
01600 "urx2",
01601 "x coord of the upper-right point of the second "
01602 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01603 "CPL_TYPE_INT", urx2,
01604 "ury2",
01605 "y coord of the upper-right point of the second "
01606 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01607 "CPL_TYPE_INT", ury2,
01608 "llx3",
01609 "x coord of the lower-left point of the third "
01610 "field used for contamination measurement. If not modified, default value will be 1.",
01611 "CPL_TYPE_INT", llx3,
01612 "lly3",
01613 "y coord of the lower-left point of the third "
01614 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01615 "CPL_TYPE_INT", lly3,
01616 "urx3",
01617 "x coord of the upper-right point of the third "
01618 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01619 "CPL_TYPE_INT", urx3,
01620 "ury3",
01621 "y coord of the upper-right point of the third "
01622 "field used for contamination measurement. If not modified, default value will be Y dimension of the image.",
01623 "CPL_TYPE_INT", ury3,
01624 "llx4",
01625 "x coord of the lower-left point of the fourth "
01626 "field used for contamination measurement. If not modified, default value will be half of X dimension of the image.",
01627 "CPL_TYPE_INT", llx4,
01628 "lly4",
01629 "y coord of the lower-left point of the fourth "
01630 "field used for contamination measurement. If not modified, default value will be half of the Y dimension of the input image.",
01631 "CPL_TYPE_INT", lly4,
01632 "urx4",
01633 "x coord of the upper-right point of the fourth "
01634 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01635 "CPL_TYPE_INT", urx4,
01636 "ury4",
01637 "y coord of the upper-right point of the fourth "
01638 "field used for contamination measurement. If not modified, default value will be Y dimension of the input image.",
01639 "CPL_TYPE_INT", ury4,
01640 "llx5",
01641 "x coord of the lower-left point of the fifth "
01642 "field used for contamination measurement. If not modified, default value will be half of the X dimension of the input image.",
01643 "CPL_TYPE_INT", llx5,
01644 "lly5",
01645 "y coord of the lower-left point of the fifth "
01646 "field used for contamination measurement. If not modified, default value will be 1.",
01647 "CPL_TYPE_INT", lly5,
01648 "urx5",
01649 "x coord of the upper-right point of the fifth "
01650 "field used for contamination measurement. If not modified, default value will be X dimension of the image.",
01651 "CPL_TYPE_INT", urx5,
01652 "ury5",
01653 "y coord of the upper-right point of the fifth "
01654 "field used for contamination measurement. If not modified, default value will be half of Y dimension of the input image.",
01655 "CPL_TYPE_INT", ury5);
01656 cpl_ensure_code(!erroropt, erroropt);
01657 }
01658
01659 cpl_ensure_code(!error, error);
01660
01661 return cpl_error_get_code();
01662 }
01663
01664
01673
01674 static cpl_error_code
01675 irplib_detmon_lg_retrieve_parlist(const char * pipeline_name,
01676 const char * recipe_name,
01677 const cpl_parameterlist * parlist,
01678 cpl_boolean opt_nir)
01679 {
01680
01681 char * par_name;
01682 cpl_parameter * par;
01683
01684
01685 par_name = cpl_sprintf("%s.%s.method", pipeline_name, recipe_name);
01686 assert(par_name != NULL);
01687 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01688 detmon_lg_config.method = cpl_parameter_get_string(par);
01689 cpl_free(par_name);
01690
01691
01692 detmon_lg_config.order =
01693 irplib_detmon_retrieve_par("order", pipeline_name, recipe_name,
01694 parlist);
01695
01696
01697 detmon_lg_config.kappa =
01698 irplib_detmon_retrieve_par("kappa", pipeline_name, recipe_name,
01699 parlist);
01700
01701
01702 detmon_lg_config.niter =
01703 irplib_detmon_retrieve_par("niter", pipeline_name, recipe_name,
01704 parlist);
01705
01706
01707 detmon_lg_config.llx =
01708 irplib_detmon_retrieve_par("llx", pipeline_name, recipe_name,
01709 parlist);
01710
01711
01712 detmon_lg_config.lly =
01713 irplib_detmon_retrieve_par("lly", pipeline_name, recipe_name,
01714 parlist);
01715
01716
01717 detmon_lg_config.urx =
01718 irplib_detmon_retrieve_par("urx", pipeline_name, recipe_name,
01719 parlist);
01720
01721
01722 detmon_lg_config.ury =
01723 irplib_detmon_retrieve_par("ury", pipeline_name, recipe_name,
01724 parlist);
01725
01726
01727 detmon_lg_config.ref_level =
01728 irplib_detmon_retrieve_par("ref_level", pipeline_name, recipe_name,
01729 parlist);
01730
01731
01732 par_name =
01733 cpl_sprintf("%s.%s.intermediate", pipeline_name, recipe_name);
01734 assert(par_name != NULL);
01735 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01736 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
01737 cpl_free(par_name);
01738
01739
01740 par_name = cpl_sprintf("%s.%s.autocorr", pipeline_name, recipe_name);
01741 assert(par_name != NULL);
01742 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01743 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
01744 cpl_free(par_name);
01745
01746
01747 par_name = cpl_sprintf("%s.%s.collapse", pipeline_name, recipe_name);
01748 assert(par_name != NULL);
01749 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01750 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
01751 cpl_free(par_name);
01752
01753
01754 par_name = cpl_sprintf("%s.%s.rescale", pipeline_name, recipe_name);
01755 assert(par_name != NULL);
01756 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01757 detmon_lg_config.rescale = cpl_parameter_get_bool(par);
01758 cpl_free(par_name);
01759
01760
01761 par_name = cpl_sprintf("%s.%s.pix2pix", pipeline_name, recipe_name);
01762 assert(par_name != NULL);
01763 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01764 detmon_lg_config.pix2pix = cpl_parameter_get_bool(par);
01765 cpl_free(par_name);
01766
01767
01768 par_name = cpl_sprintf("%s.%s.bpmbin", pipeline_name, recipe_name);
01769 assert(par_name != NULL);
01770 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01771 detmon_lg_config.bpmbin = cpl_parameter_get_bool(par);
01772 cpl_free(par_name);
01773
01774
01775 detmon_lg_config.filter =
01776 irplib_detmon_retrieve_par("filter", pipeline_name,
01777 recipe_name, parlist);
01778
01779
01780 detmon_lg_config.m =
01781 irplib_detmon_retrieve_par("m", pipeline_name, recipe_name, parlist);
01782
01783
01784 detmon_lg_config.n =
01785 irplib_detmon_retrieve_par("n", pipeline_name, recipe_name, parlist);
01786
01787
01788 par_name = cpl_sprintf("%s.%s.tolerance", pipeline_name, recipe_name);
01789 assert(par_name != NULL);
01790 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01791 detmon_lg_config.tolerance = cpl_parameter_get_double(par);
01792 cpl_free(par_name);
01793
01794
01795 par_name = cpl_sprintf("%s.%s.pafname", pipeline_name, recipe_name);
01796 assert(par_name != NULL);
01797 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01798 detmon_lg_config.pafname = cpl_parameter_get_string(par);
01799 cpl_free(par_name);
01800
01801 if(opt_nir == OPT) {
01802
01803 detmon_lg_config.llx1 =
01804 irplib_detmon_retrieve_par("llx1", pipeline_name, recipe_name,
01805 parlist);
01806
01807
01808 detmon_lg_config.lly1 =
01809 irplib_detmon_retrieve_par("lly1", pipeline_name, recipe_name,
01810 parlist);
01811
01812
01813 detmon_lg_config.urx1 =
01814 irplib_detmon_retrieve_par("urx1", pipeline_name, recipe_name,
01815 parlist);
01816
01817
01818 detmon_lg_config.ury1 =
01819 irplib_detmon_retrieve_par("ury1", pipeline_name, recipe_name,
01820 parlist);
01821
01822
01823 detmon_lg_config.llx2 =
01824 irplib_detmon_retrieve_par("llx2", pipeline_name, recipe_name,
01825 parlist);
01826
01827
01828 detmon_lg_config.lly2 =
01829 irplib_detmon_retrieve_par("lly2", pipeline_name, recipe_name,
01830 parlist);
01831
01832
01833 detmon_lg_config.urx2 =
01834 irplib_detmon_retrieve_par("urx2", pipeline_name, recipe_name,
01835 parlist);
01836
01837
01838 detmon_lg_config.ury2 =
01839 irplib_detmon_retrieve_par("ury2", pipeline_name, recipe_name,
01840 parlist);
01841
01842
01843 detmon_lg_config.llx3 =
01844 irplib_detmon_retrieve_par("llx3", pipeline_name, recipe_name,
01845 parlist);
01846
01847
01848 detmon_lg_config.lly3 =
01849 irplib_detmon_retrieve_par("lly3", pipeline_name, recipe_name,
01850 parlist);
01851
01852
01853 detmon_lg_config.urx3 =
01854 irplib_detmon_retrieve_par("urx3", pipeline_name, recipe_name,
01855 parlist);
01856
01857
01858 detmon_lg_config.ury3 =
01859 irplib_detmon_retrieve_par("ury3", pipeline_name, recipe_name,
01860 parlist);
01861
01862
01863 detmon_lg_config.llx4 =
01864 irplib_detmon_retrieve_par("llx4", pipeline_name, recipe_name,
01865 parlist);
01866
01867
01868 detmon_lg_config.lly4 =
01869 irplib_detmon_retrieve_par("lly4", pipeline_name, recipe_name,
01870 parlist);
01871
01872
01873 detmon_lg_config.urx4 =
01874 irplib_detmon_retrieve_par("urx4", pipeline_name, recipe_name,
01875 parlist);
01876
01877
01878 detmon_lg_config.ury4 =
01879 irplib_detmon_retrieve_par("ury4", pipeline_name, recipe_name,
01880 parlist);
01881
01882
01883 detmon_lg_config.llx5 =
01884 irplib_detmon_retrieve_par("llx5", pipeline_name, recipe_name,
01885 parlist);
01886
01887
01888 detmon_lg_config.lly5 =
01889 irplib_detmon_retrieve_par("lly5", pipeline_name, recipe_name,
01890 parlist);
01891
01892
01893 detmon_lg_config.urx5 =
01894 irplib_detmon_retrieve_par("urx5", pipeline_name, recipe_name,
01895 parlist);
01896
01897
01898 detmon_lg_config.ury5 =
01899 irplib_detmon_retrieve_par("ury5", pipeline_name, recipe_name,
01900 parlist);
01901 }
01902
01903
01904 detmon_lg_config.exts =
01905 irplib_detmon_retrieve_par("exts", pipeline_name, recipe_name,
01906 parlist);
01907
01908 if(cpl_error_get_code()) {
01909 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
01910 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
01911 }
01912
01913
01914 return cpl_error_get_code();
01915 }
01916
01917
01923
01924 static cpl_error_code
01925 irplib_detmon_lg_check_defaults(const cpl_image * reference)
01926 {
01927 const int nx = cpl_image_get_size_x(reference);
01928 const int ny = cpl_image_get_size_y(reference);
01929
01930 if(detmon_lg_config.llx == -1)
01931 detmon_lg_config.llx = 1;
01932 if(detmon_lg_config.lly == -1)
01933 detmon_lg_config.lly = 1;
01934 if(detmon_lg_config.urx == -1)
01935 detmon_lg_config.urx = nx;
01936 if(detmon_lg_config.ury == -1)
01937 detmon_lg_config.ury = ny;
01938
01939 if(detmon_lg_config.llx1 == -1)
01940 detmon_lg_config.llx1 = 1;
01941 if(detmon_lg_config.lly1 == -1)
01942 detmon_lg_config.lly1 = 1;
01943 if(detmon_lg_config.urx1 == -1)
01944 detmon_lg_config.urx1 = nx;
01945 if(detmon_lg_config.ury1 == -1)
01946 detmon_lg_config.ury1 = ny;
01947
01948 if(detmon_lg_config.llx2 == -1)
01949 detmon_lg_config.llx2 = 1;
01950 if(detmon_lg_config.lly2 == -1)
01951 detmon_lg_config.lly2 = 1;
01952 if(detmon_lg_config.urx2 == -1)
01953 detmon_lg_config.urx2 = nx / 2;
01954 if(detmon_lg_config.ury2 == -1)
01955 detmon_lg_config.ury2 = ny / 2;
01956
01957 if(detmon_lg_config.llx3 == -1)
01958 detmon_lg_config.llx3 = 1;
01959 if(detmon_lg_config.lly3 == -1)
01960 detmon_lg_config.lly3 = ny / 2;
01961 if(detmon_lg_config.urx3 == -1)
01962 detmon_lg_config.urx3 = nx / 2;
01963 if(detmon_lg_config.ury3 == -1)
01964 detmon_lg_config.ury3 = ny;
01965
01966 if(detmon_lg_config.llx4 == -1)
01967 detmon_lg_config.llx4 = nx / 2;
01968 if(detmon_lg_config.lly4 == -1)
01969 detmon_lg_config.lly4 = ny / 2;
01970 if(detmon_lg_config.urx4 == -1)
01971 detmon_lg_config.urx4 = nx;
01972 if(detmon_lg_config.ury4 == -1)
01973 detmon_lg_config.ury4 = ny;
01974
01975 if(detmon_lg_config.llx5 == -1)
01976 detmon_lg_config.llx5 = nx / 2;
01977 if(detmon_lg_config.lly5 == -1)
01978 detmon_lg_config.lly5 = 1;
01979 if(detmon_lg_config.urx5 == -1)
01980 detmon_lg_config.urx5 = nx;
01981 if(detmon_lg_config.ury5 == -1)
01982 detmon_lg_config.ury5 = ny / 2;
01983
01984 if(detmon_lg_config.intermediate == TRUE) {
01985 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.");
01986 detmon_lg_config.autocorr = TRUE;
01987 }
01988
01989 #ifndef HAVE_FFTW
01990 if(detmon_lg_config.autocorr == TRUE)
01991 cpl_msg_warning(cpl_func,
01992 "You don't have FFTW installed in your system."
01993 " Please note that use of --autocorr option without it "
01994 "will result in an execution time close to 10 minutes.");
01995
01996 #endif
01997
01998 detmon_lg_config.lamp_stability = 0.0;
01999
02000 detmon_lg_config.lamp_ok = FALSE;
02001
02002 detmon_lg_config.cr = 0.0;
02003
02004 return cpl_error_get_code();
02005 }
02006
02007
02018
02019 static cpl_error_code
02020 irplib_detmon_lg_split_onoff(const cpl_frameset * cur_fset,
02021 cpl_frameset * cur_fset_on,
02022 cpl_frameset * cur_fset_off,
02023 const char *tag_on,
02024 const char *tag_off)
02025
02026 {
02027 int nframes;
02028 int i;
02029
02030 const cpl_frame * first;
02031 const cpl_frame * second;
02032
02033 const char * first_tag;
02034 const char * second_tag;
02035
02036 cpl_frame * cur_frame_dup = NULL;
02037
02038 skip_if((first = cpl_frameset_get_first_const(cur_fset)) == NULL);
02039 skip_if((second = cpl_frameset_get_next_const (cur_fset)) == NULL);
02040
02041 skip_if((first_tag = cpl_frame_get_tag(first)) == NULL);
02042 skip_if((second_tag = cpl_frame_get_tag(second)) == NULL);
02043
02044
02045
02046
02047
02048
02049
02050
02051 nframes = cpl_frameset_get_size(cur_fset);
02052 for(i = detmon_lg_config.lamp_ok ? 2 : 0; i < nframes; i++) {
02053 const cpl_frame * cur_frame =
02054 cpl_frameset_get_frame_const(cur_fset, i);
02055 char * tag;
02056
02057
02058 cur_frame_dup = cpl_frame_duplicate(cur_frame);
02059 tag = (char *) cpl_frame_get_tag(cur_frame_dup);
02060
02061
02062 if(!strcmp(tag, tag_on)) {
02063 skip_if(cpl_frameset_insert(cur_fset_on, cur_frame_dup));
02064 } else if(!strcmp(tag, tag_off)) {
02065 skip_if(cpl_frameset_insert(cur_fset_off, cur_frame_dup));
02066 } else {
02067 cpl_frame_delete(cur_frame_dup);
02068 cur_frame_dup = NULL;
02069 }
02070 }
02071 cur_frame_dup = NULL;
02072
02073 end_skip;
02074
02075 cpl_frame_delete(cur_frame_dup);
02076
02077 return cpl_error_get_code();
02078 }
02079
02080
02104
02105
02106 static cpl_error_code
02107 irplib_detmon_lg_reduce(const cpl_frameset * set_on,
02108 const cpl_frameset * set_off,
02109 int *selection_on,
02110 int *selection_off,
02111 int nsets_extracted,
02112 cpl_imagelist ** coeffs_ptr,
02113 cpl_table * gain_table,
02114 cpl_table * linear_table,
02115 cpl_image ** bpm_ptr,
02116 cpl_imagelist * autocorr_images,
02117 cpl_imagelist * diff_flats,
02118 cpl_propertylist * qclist,
02119 int (* load_fset) (const cpl_frameset *,
02120 cpl_type,
02121 cpl_imagelist *),
02122 const cpl_boolean opt_nir,
02123 int whichext)
02124 {
02125 int i;
02126 cpl_imagelist * linearity_inputs = NULL;
02127 cpl_imagelist * opt_offs = NULL;
02128 int nsets;
02129 cpl_propertylist * reflist = NULL;
02130
02131
02132 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02133 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
02134
02135 nsets = cpl_frameset_get_size(set_on) / 2;
02136
02137 if(detmon_lg_config.collapse) {
02138
02139
02140
02141
02142
02143
02144 const cpl_frame *first = cpl_frameset_get_first_const(set_off);
02145 cpl_frame *dup_first = cpl_frame_duplicate(first);
02146
02147 const cpl_frame *second = cpl_frameset_get_next_const(set_off);
02148 cpl_frame *dup_second = cpl_frame_duplicate(second);
02149
02150 cpl_frameset *raw_offs = cpl_frameset_new();
02151
02152 cpl_frameset_insert(raw_offs, dup_first);
02153 cpl_frameset_insert(raw_offs, dup_second);
02154
02155 opt_offs = cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT,
02156 0, whichext);
02157
02158 cpl_frameset_delete(raw_offs);
02159
02160 }
02161
02162 skip_if(irplib_detmon_lg_reduce_init(gain_table,
02163 linear_table,
02164 &linearity_inputs));
02165
02166 if(!detmon_lg_config.collapse)
02167 skip_if(irplib_detmon_lg_lamp_stab(set_on, set_off, opt_nir));
02168
02169
02170 skip_if(cpl_table_unselect_all(linear_table));
02171 skip_if(cpl_table_unselect_all(gain_table));
02172
02173
02174 for(i = 0; i < nsets ; i++) {
02175 skip_if(irplib_detmon_lg_reduce_dit(set_on, selection_on, i,
02176 nsets_extracted, set_off,
02177 selection_off, linear_table,
02178 gain_table, linearity_inputs,
02179 qclist, opt_nir,
02180 autocorr_images, diff_flats,
02181 opt_offs, load_fset, whichext));
02182 }
02183
02184 skip_if(irplib_detmon_add_adl_column(linear_table));
02185
02186
02187
02188
02189
02190 skip_if(cpl_table_erase_selected(gain_table));
02191 skip_if(cpl_table_erase_selected(linear_table));
02192
02193 reflist = cpl_propertylist_new();
02194 skip_if(cpl_propertylist_append_bool(reflist, "ADU", FALSE));
02195 skip_if(cpl_table_sort(gain_table, reflist));
02196
02197
02198
02199
02200
02201
02202
02203 skip_if(irplib_detmon_lg_reduce_all(linear_table,
02204 qclist, coeffs_ptr, bpm_ptr,
02205 linearity_inputs,
02206 gain_table, i+1));
02207
02208 end_skip;
02209
02210 cpl_imagelist_delete(linearity_inputs);
02211 cpl_imagelist_delete(opt_offs);
02212 cpl_propertylist_delete(reflist);
02213
02214 return cpl_error_get_code();
02215 }
02216
02217
02225
02226 static cpl_error_code
02227 irplib_detmon_lg_lamp_stab(const cpl_frameset * lamps,
02228 const cpl_frameset * darks,
02229 cpl_boolean opt_nir)
02230 {
02231
02232
02233
02234
02235
02236
02237 int nb_lamps;
02238 cpl_vector * selection = NULL;
02239 cpl_propertylist * plist;
02240 double dit_lamp, dit_dark;
02241 int dit_stab;
02242 cpl_imagelist * lamps_data = NULL;
02243 cpl_imagelist * darks_data = NULL;
02244 double * stab_levels = NULL;
02245 int i, j;
02246 double * ditvals = NULL;
02247 int last_stab = 0;
02248
02249
02250 cpl_ensure_code((nb_lamps = cpl_frameset_get_size(lamps)) >= 3,
02251 CPL_ERROR_ILLEGAL_INPUT);
02252 cpl_ensure_code(cpl_frameset_get_size(darks) == nb_lamps,
02253 CPL_ERROR_ILLEGAL_INPUT);
02254
02255
02256 cpl_msg_info(__func__, "Checking DIT consistency");
02257 selection = cpl_vector_new(nb_lamps);
02258 ditvals = cpl_malloc(nb_lamps * sizeof(double));
02259 dit_stab = 0;
02260 for (i = 0; i < nb_lamps; i++) {
02261 const cpl_frame * c_lamp;
02262 const cpl_frame * c_dark;
02263
02264 skip_if (cpl_error_get_code());
02265
02266
02267 c_lamp = cpl_frameset_get_frame_const(lamps, i);
02268 plist = cpl_propertylist_load(cpl_frame_get_filename(c_lamp), 0);
02269 if(opt_nir)
02270 dit_lamp = (double)irplib_pfits_get_dit(plist);
02271 else
02272 dit_lamp = (double)irplib_pfits_get_dit_opt(plist);
02273 cpl_propertylist_delete(plist);
02274 skip_if (cpl_error_get_code());
02275
02276
02277 c_dark = cpl_frameset_get_frame_const(darks, i);
02278 plist = cpl_propertylist_load(cpl_frame_get_filename(c_dark), 0);
02279 if(opt_nir)
02280 dit_dark = (double)irplib_pfits_get_dit(plist);
02281 else
02282 dit_dark = (double)irplib_pfits_get_dit_opt(plist);
02283 cpl_propertylist_delete(plist);
02284 skip_if (cpl_error_get_code());
02285
02286
02287 if (fabs(dit_dark-dit_lamp) > 1e-3) {
02288 cpl_msg_error(__func__, "DIT not consistent between LAMP and DARK");
02289
02290 skip_if(1);
02291 }
02292 ditvals[i] = dit_lamp;
02293
02294 if (i==0) {
02295 cpl_vector_set(selection, i, -1.0);
02296 dit_stab ++;
02297 last_stab = 0;
02298 } else {
02299
02300
02301
02302
02303 if (fabs(dit_lamp - ditvals[0]) < 1e-5 && i - last_stab > 3) {
02304 cpl_vector_set(selection, i, -1.0);
02305 dit_stab ++;
02306 last_stab = i;
02307 } else {
02308 cpl_vector_set(selection, i, 1.0);
02309 }
02310 }
02311 }
02312
02313
02314 if (dit_stab < 2) {
02315 cpl_msg_info(__func__, "Not enough frames for stability check");
02316 } else {
02317
02318
02319 cpl_msg_info(__func__, "Compute the differences lamp - dark");
02320 lamps_data = cpl_imagelist_load_frameset(lamps, CPL_TYPE_FLOAT, 1, 0);
02321 darks_data = cpl_imagelist_load_frameset(darks, CPL_TYPE_FLOAT, 1, 0);
02322 skip_if(cpl_imagelist_subtract(lamps_data,darks_data));
02323
02324
02325 cpl_msg_info(__func__, "Check the lamp stability");
02326 stab_levels = cpl_malloc(dit_stab * sizeof(double));
02327 j = 0;
02328 for (i=0; i<nb_lamps; i++) {
02329 if (cpl_vector_get(selection, i) < 0) {
02330 stab_levels[j] =
02331 cpl_image_get_mean(cpl_imagelist_get(lamps_data, i));
02332 j++;
02333 }
02334 }
02335
02336
02337 for (i=1; i<dit_stab; i++) {
02338 if ((fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0]) >
02339 detmon_lg_config.lamp_stability)
02340 detmon_lg_config.lamp_stability =
02341 fabs(stab_levels[i]-stab_levels[0]) / stab_levels[0];
02342 }
02343
02344
02345
02346 if (detmon_lg_config.lamp_stability > 0.01) {
02347 cpl_msg_warning(__func__,
02348 "level difference too high - proceed anyway");
02349 }
02350 }
02351 end_skip;
02352
02353 cpl_free(ditvals);
02354 cpl_vector_delete(selection);
02355 cpl_imagelist_delete(lamps_data);
02356 cpl_imagelist_delete(darks_data);
02357 cpl_free(stab_levels);
02358
02359 return cpl_error_get_code();
02360 }
02361
02362
02390
02391 static cpl_error_code
02392 irplib_detmon_lg_reduce_dit(const cpl_frameset * set_on,
02393 int * selection_on,
02394 int dit_nb,
02395 int nsets_extracted,
02396 const cpl_frameset * set_off,
02397 int * selection_off,
02398 cpl_table * linear_table,
02399 cpl_table * gain_table,
02400 cpl_imagelist * linearity_inputs,
02401 cpl_propertylist * qclist,
02402 cpl_boolean opt_nir,
02403 cpl_imagelist * autocorr_images,
02404 cpl_imagelist * diff_flats,
02405 cpl_imagelist * opt_offs,
02406 int (* load_fset) (const cpl_frameset *,
02407 cpl_type,
02408 cpl_imagelist *),
02409 int whichext)
02410 {
02411 cpl_frameset * pair_on = NULL;
02412 cpl_frameset * pair_off = NULL;
02413 cpl_imagelist * ons = NULL;
02414 cpl_imagelist * offs = NULL;
02415 int with_equal_dit = 0;
02416 cpl_boolean follow = CPL_TRUE;
02417 cpl_imagelist * masterl = NULL;
02418 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
02419
02420 mode = detmon_lg_config.collapse ? mode & IRPLIB_GAIN_COLLAPSE : mode;
02421
02422
02423 skip_if(irplib_detmon_pair_extract(set_on, selection_on, dit_nb, nsets_extracted, &with_equal_dit, 1, &pair_on));
02424
02425
02426 if (load_fset != NULL) {
02427 ons = cpl_imagelist_new();
02428 (*load_fset)(pair_on, CPL_TYPE_FLOAT, ons);
02429 } else {
02430 ons = cpl_imagelist_load_frameset(pair_on, CPL_TYPE_FLOAT, 1,whichext);
02431 }
02432 skip_if(ons == NULL);
02433
02434 if(detmon_lg_config.filter > 0) {
02435 double med1 =
02436 cpl_image_get_median_window(cpl_imagelist_get(ons, 0),
02437 detmon_lg_config.llx,
02438 detmon_lg_config.lly,
02439 detmon_lg_config.urx,
02440 detmon_lg_config.ury);
02441 double med2 =
02442 cpl_image_get_median_window(cpl_imagelist_get(ons, 1),
02443 detmon_lg_config.llx,
02444 detmon_lg_config.lly,
02445 detmon_lg_config.urx,
02446 detmon_lg_config.ury);
02447 if ( med1 > (double)detmon_lg_config.filter ||
02448 med2 > (double)detmon_lg_config.filter) {
02449 follow = CPL_FALSE;
02450 cpl_table_select_row(gain_table, dit_nb);
02451 cpl_table_select_row(linear_table, dit_nb);
02452 cpl_msg_warning(cpl_func, "Frames of EXPTIME nb %d "
02453 "will not be taken into account for computation "
02454 "as they are above --filter threshold", dit_nb);
02455 }
02456 }
02457
02458 if (follow || detmon_lg_config.filter < 0) {
02459
02460
02461
02462
02463
02464 if(!detmon_lg_config.collapse) {
02465 skip_if(irplib_detmon_pair_extract(set_off, selection_off, dit_nb, nsets_extracted, &with_equal_dit, 0, &pair_off));
02466
02467
02468 if (load_fset != NULL) {
02469 offs = cpl_imagelist_new();
02470 (*load_fset)(pair_off, CPL_TYPE_FLOAT, offs);
02471 } else {
02472 offs = cpl_imagelist_load_frameset(pair_off, CPL_TYPE_FLOAT,
02473 1, whichext);
02474 }
02475 skip_if(offs == NULL);
02476 skip_if(cpl_error_get_code());
02477 } else {
02478
02479
02480
02481
02482 cpl_image * collapse;
02483 masterl = cpl_imagelist_load_frameset(set_off, CPL_TYPE_FLOAT,
02484 1, whichext);
02485 skip_if(masterl == NULL);
02486 skip_if(cpl_error_get_code());
02487
02488 collapse = cpl_imagelist_collapse_create(masterl);
02489 skip_if(collapse == NULL);
02490 skip_if(cpl_imagelist_set(masterl, collapse, 0));
02491
02492
02493 offs = (cpl_imagelist *)masterl;
02494 }
02495
02496
02497 if(detmon_lg_config.rescale) {
02498 skip_if(irplib_detmon_lg_rescale(ons));
02499 skip_if(irplib_detmon_lg_rescale(offs));
02500 }
02501
02502
02503 skip_if(irplib_detmon_linearity(pair_on, linear_table,
02504 gain_table,
02505 linearity_inputs,
02506 ons, offs, dit_nb,
02507 nsets_extracted, qclist, opt_nir));
02508
02509
02510
02511
02512
02513
02514
02515
02516 if(detmon_lg_config.collapse) {
02517 offs = (cpl_imagelist *) opt_offs;
02518 }
02519
02520 cpl_msg_info(cpl_func, "Computing GAIN for EXPTIME value nb %d",
02521 dit_nb + 1);
02522
02523 skip_if(irplib_detmon_gain_table_fill_row(gain_table, autocorr_images,
02524 diff_flats, ons, offs,
02525 (double)detmon_lg_config.kappa,
02526 detmon_lg_config.niter,
02527 detmon_lg_config.llx,
02528 detmon_lg_config.lly,
02529 detmon_lg_config.urx,
02530 detmon_lg_config.ury,
02531 detmon_lg_config.m,
02532 detmon_lg_config.n,
02533 dit_nb, mode));
02534 }
02535
02536 end_skip;
02537
02538 cpl_frameset_delete(pair_on);
02539 cpl_imagelist_delete(ons);
02540
02541 if(!detmon_lg_config.collapse ) {
02542 cpl_imagelist_delete(offs);
02543 }
02544
02545 if(!detmon_lg_config.collapse) {
02546 cpl_frameset_delete(pair_off);
02547 }
02548
02549 if(detmon_lg_config.collapse) {
02550 cpl_imagelist_delete(masterl);
02551 }
02552
02553
02554 return cpl_error_get_code();
02555 }
02556
02557
02563
02564 static cpl_error_code
02565 irplib_detmon_add_adl_column(cpl_table * table)
02566 {
02567 cpl_error_code error;
02568 double mean_med_dit;
02569 double *dits;
02570
02571 cpl_ensure_code(table != NULL, CPL_ERROR_NULL_INPUT);
02572
02573 mean_med_dit = cpl_table_get_column_mean(table, "MED_DIT");
02574 dits = cpl_table_get_data_double(table, "DIT");
02575
02576 error = cpl_table_copy_data_double(table, "ADL", dits);
02577 cpl_ensure_code(!error, error);
02578 error = cpl_table_multiply_scalar(table, "ADL", mean_med_dit);
02579 cpl_ensure_code(!error, error);
02580
02581 return cpl_error_get_code();
02582 }
02583
02584
02592
02593 static cpl_error_code
02594 irplib_detmon_lg_reduce_init(cpl_table * gain_table,
02595 cpl_table * linear_table,
02596 cpl_imagelist ** linearity_inputs)
02597 {
02598 skip_if(irplib_detmon_gain_table_create(gain_table));
02599
02600 skip_if(cpl_table_new_column(linear_table, "DIT", CPL_TYPE_DOUBLE));
02601 skip_if(cpl_table_new_column(linear_table, "EXPTIME", CPL_TYPE_DOUBLE));
02602 skip_if(cpl_table_new_column(linear_table, "MED", CPL_TYPE_DOUBLE));
02603 skip_if(cpl_table_new_column(linear_table, "MEAN", CPL_TYPE_DOUBLE));
02604 skip_if(cpl_table_new_column(linear_table, "MED_DIT", CPL_TYPE_DOUBLE));
02605 skip_if(cpl_table_new_column(linear_table, "MEAN_DIT",
02606 CPL_TYPE_DOUBLE));
02607 skip_if(cpl_table_new_column(linear_table, "ADL", CPL_TYPE_DOUBLE));
02608
02609 if(detmon_lg_config.pix2pix) {
02610 *linearity_inputs = cpl_imagelist_new();
02611 skip_if(*linearity_inputs == NULL);
02612 }
02613
02614 end_skip;
02615
02616 return cpl_error_get_code();
02617 }
02618
02619
02625
02626 static double
02627 irplib_pfits_get_dit(const cpl_propertylist * plist)
02628 {
02629 double dit;
02630
02631 dit = cpl_propertylist_get_double(plist, "ESO DET DIT");
02632
02633 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02634 cpl_msg_error(cpl_func, cpl_error_get_where());
02635 }
02636 return dit;
02637 }
02638
02639
02645
02646 static double
02647 irplib_pfits_get_dit_opt(const cpl_propertylist * plist)
02648 {
02649 double dit;
02650
02651 dit = cpl_propertylist_get_double(plist, "ESO DET WIN1 UIT1");
02652
02653 if(cpl_error_get_code() != CPL_ERROR_NONE) {
02654 cpl_msg_error(cpl_func, cpl_error_get_where());
02655 }
02656 return dit;
02657 }
02658
02659
02675
02676
02677 static cpl_error_code
02678 irplib_detmon_linearity(const cpl_frameset * pair,
02679 cpl_table * linear_table,
02680 cpl_table * gain_table,
02681 cpl_imagelist * linearity_inputs,
02682 cpl_imagelist * ons,
02683 cpl_imagelist * offs,
02684 const int pos,
02685 const int nsets,
02686 cpl_propertylist * qclist,
02687 const cpl_boolean opt_nir)
02688 {
02689 const char *filename;
02690 cpl_propertylist *plist;
02691 cpl_image *dif1;
02692 cpl_image *dif2;
02693 cpl_image *dif_avg;
02694 double med_dit;
02695 double mean_dit;
02696 double exptime, dit;
02697 cpl_error_code error;
02698
02699 cpl_ensure_code(ons != NULL, CPL_ERROR_NULL_INPUT);
02700 cpl_ensure_code(offs != NULL, CPL_ERROR_NULL_INPUT);
02701
02702 filename = cpl_frame_get_filename(cpl_frameset_get_first_const(pair));
02703 if((plist = cpl_propertylist_load(filename, 0)) == NULL) {
02704 cpl_msg_error(cpl_func, "getting header from reference frame");
02705 cpl_ensure_code(0, cpl_error_get_code());
02706 }
02707
02708 if(opt_nir) {
02709 dit = irplib_pfits_get_dit(plist);
02710 } else {
02711 dit = irplib_pfits_get_dit_opt(plist);
02712 }
02713
02714 exptime = irplib_pfits_get_exptime(plist);
02715
02716 cpl_table_set(linear_table, "DIT", pos, dit);
02717 cpl_table_set(gain_table, "DIT", pos, dit);
02718
02719 cpl_table_set(linear_table, "EXPTIME", pos, exptime);
02720 cpl_table_set(gain_table, "EXPTIME", pos, exptime);
02721
02722
02723 dif1 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
02724 cpl_imagelist_get_const(offs, 0));
02725 if(!detmon_lg_config.collapse)
02726 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
02727 cpl_imagelist_get_const(offs, 1));
02728 else
02729 dif2 = cpl_image_subtract_create(cpl_imagelist_get_const(ons, 1),
02730 cpl_imagelist_get_const(offs, 0));
02731
02732 dif_avg = cpl_image_average_create(dif1, dif2);
02733
02734 cpl_image_abs(dif_avg);
02735
02736 cpl_ensure_code(dif_avg != NULL, cpl_error_get_code());
02737
02738 if(opt_nir == OPT && pos == nsets / 2) {
02739 irplib_detmon_opt_contamination(dif_avg, qclist);
02740 }
02741
02742 cpl_table_set(linear_table, "MED", pos, cpl_image_get_median(dif_avg));
02743 cpl_table_set(linear_table, "MEAN", pos, cpl_image_get_mean(dif_avg));
02744 med_dit = cpl_image_get_median(dif_avg) / dit;
02745 mean_dit = cpl_image_get_mean(dif_avg) / dit;
02746
02747 cpl_table_set(linear_table, "MED_DIT", pos, med_dit);
02748 cpl_table_set(linear_table, "MEAN_DIT", pos, mean_dit);
02749
02750 cpl_image_delete(dif1);
02751 cpl_image_delete(dif2);
02752 cpl_propertylist_delete(plist);
02753
02754
02755 if(detmon_lg_config.pix2pix) {
02756 error = cpl_imagelist_set(linearity_inputs, dif_avg, pos);
02757 cpl_ensure_code(!error, error);
02758 } else {
02759 cpl_image_delete(dif_avg);
02760 }
02761
02762 return cpl_error_get_code();
02763 }
02764
02765
02776
02777 static cpl_error_code
02778 irplib_detmon_gain_table_fill_row(cpl_table * gain_table,
02779 cpl_imagelist * autocorr_images,
02780 cpl_imagelist * diff_flats,
02781 const cpl_imagelist * ons,
02782 const cpl_imagelist * offs,
02783 double kappa, int nclip,
02784 int llx, int lly, int urx, int ury,
02785 int m, int n,
02786 const int pos, unsigned mode)
02787 {
02788 const cpl_image *image;
02789 double std = 0;
02790 cpl_image *on_dif = NULL;
02791 cpl_image *off_dif = NULL;
02792 double avg_on1, avg_on2;
02793 double avg_off1, avg_off2;
02794 double avg_on_dif, sig_on_dif;
02795 double avg_off_dif, sig_off_dif;
02796 double double_adu, autocorr, gain, gain_corr;
02797 double sigma, sigma_corr;
02798
02799 skip_if((image = cpl_imagelist_get_const(ons, 0)) == NULL);
02800 skip_if(irplib_get_clean_mean_window(image, llx, lly, urx, ury, kappa,
02801 nclip, 1e-5, &avg_on1, &std));
02802 skip_if(cpl_table_set_double(gain_table, "MEAN_ON1", pos, avg_on1));
02803
02804 skip_if((image = cpl_imagelist_get_const(ons, 1)) == NULL);
02805 skip_if(irplib_get_clean_mean_window(image, llx, lly, urx, ury, kappa,
02806 nclip, 1e-5, &avg_on2, &std));
02807 skip_if(cpl_table_set_double(gain_table, "MEAN_ON2", pos, avg_on2));
02808
02809 on_dif =
02810 cpl_image_subtract_create(cpl_imagelist_get_const(ons, 0),
02811 cpl_imagelist_get_const(ons, 1));
02812 skip_if(on_dif == NULL);
02813
02814 skip_if(irplib_get_clean_mean_window(on_dif, llx, lly, urx, ury, kappa,
02815 nclip, 1e-5,
02816 &avg_on_dif, &sig_on_dif));
02817 skip_if(cpl_table_set_double(gain_table, "SIG_ON_DIF", pos, sig_on_dif));
02818
02819
02820
02821 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
02822 if (diff_flats) {
02823 cpl_image * diff = cpl_image_duplicate(on_dif);
02824 skip_if(cpl_imagelist_set(diff_flats, diff, pos));
02825 }
02826 if (autocorr_images) {
02827 cpl_image * corr;
02828 autocorr = irplib_detmon_autocorr_factor(on_dif, &corr, m, n);
02829 skip_if(cpl_imagelist_set(autocorr_images, corr, pos));
02830 } else {
02831 autocorr = irplib_detmon_autocorr_factor(on_dif, NULL, m, n);
02832 }
02833 } else {
02834 autocorr = 1.0;
02835 }
02836
02837 if (mode & IRPLIB_GAIN_NO_COLLAPSE || pos == 0) {
02838 skip_if(irplib_get_clean_mean_window(cpl_imagelist_get_const(offs, 0),
02839 llx, lly, urx, ury, kappa, nclip,
02840 1e-5, &avg_off1, &std));
02841 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
02842 skip_if(irplib_get_clean_mean_window(cpl_imagelist_get_const(offs, 1),
02843 llx, lly, urx, ury, kappa, nclip,
02844 1e-5, &avg_off2, &std));
02845 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
02846 off_dif =
02847 cpl_image_subtract_create(cpl_imagelist_get_const(offs, 0),
02848 cpl_imagelist_get_const(offs, 1));
02849 skip_if(off_dif == NULL);
02850 skip_if(irplib_get_clean_mean_window(off_dif, llx, lly, urx, ury,
02851 kappa, nclip, 1e-5,
02852 &avg_off_dif, &sig_off_dif));
02853 skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
02854 pos, sig_off_dif));
02855 } else {
02856 int status;
02857 avg_off1 = cpl_table_get_double(gain_table, "MEAN_OFF1", 0, &status);
02858 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF1", pos, avg_off1));
02859 avg_off2 = cpl_table_get_double(gain_table, "MEAN_OFF2", 0, &status);
02860 skip_if(cpl_table_set_double(gain_table, "MEAN_OFF2", pos, avg_off2));
02861 sig_off_dif = cpl_table_get_double(gain_table, "SIG_OFF_DIF",
02862 0, &status);
02863 skip_if(cpl_table_set_double(gain_table, "SIG_OFF_DIF",
02864 pos, sig_off_dif));
02865 }
02866
02867 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
02868
02869 sigma = (sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif);
02870
02871 sigma_corr = autocorr * sigma;
02872
02873 gain = double_adu / sigma;
02874
02875 gain_corr = double_adu / sigma_corr;
02876
02877 skip_if(cpl_table_set_double(gain_table, "GAIN", pos, gain));
02878 skip_if(cpl_table_set_double(gain_table, "AUTOCORR", pos, autocorr));
02879 skip_if(cpl_table_set_double(gain_table, "GAIN_CORR", pos, gain_corr));
02880 skip_if(cpl_table_set_double(gain_table, "ADU", pos, double_adu / 2));
02881
02882
02883 skip_if(cpl_table_set_double(gain_table, "Y_FIT",
02884 pos, sig_on_dif * sig_on_dif));
02885 skip_if(cpl_table_set_double(gain_table, "X_FIT", pos, double_adu));
02886 skip_if(cpl_table_set_double(gain_table, "X_FIT_CORR",
02887 pos, double_adu / autocorr));
02888
02889 end_skip;
02890
02891 cpl_image_delete(on_dif);
02892 cpl_image_delete(off_dif);
02893
02894 return cpl_error_get_code();
02895 }
02896
02897
02904
02905
02906 static cpl_image *
02907 irplib_detmon_bpixs(const cpl_imagelist * coeffs, int *nbpixs)
02908 {
02909 int size;
02910 int i;
02911 const cpl_image *first= cpl_imagelist_get_const(coeffs, 0);
02912 cpl_stats *stats;
02913 double cur_mean;
02914 double cur_stdev;
02915 double lo_cut;
02916 double hi_cut;
02917 cpl_mask *cur_mask;
02918 cpl_mask *mask = cpl_mask_new(cpl_image_get_size_x(first),
02919 cpl_image_get_size_y(first));
02920 cpl_image *cur_image = NULL;
02921 cpl_image *bpm = NULL;
02922 double p;
02923
02924 size = cpl_imagelist_get_size(coeffs);
02925
02926 if(!detmon_lg_config.bpmbin) {
02927 bpm = cpl_image_new(cpl_image_get_size_x(first),
02928 cpl_image_get_size_y(first),
02929 CPL_TYPE_INT);
02930 }
02931
02932
02933 for(i = 0; i < size; i++) {
02934 const cpl_image * cur_coeff = cpl_imagelist_get_const(coeffs, i);
02935
02936 stats = cpl_stats_new_from_image(cur_coeff,
02937 CPL_STATS_MEAN | CPL_STATS_STDEV);
02938 cur_mean = cpl_stats_get_mean(stats);
02939 cur_stdev = cpl_stats_get_stdev(stats);
02940
02941 lo_cut = cur_mean - detmon_lg_config.kappa * cur_stdev;
02942 hi_cut = cur_mean + detmon_lg_config.kappa * cur_stdev;
02943
02944 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
02945 cpl_mask_not(cur_mask);
02946
02947 if(!detmon_lg_config.bpmbin) {
02948 cur_image = cpl_image_new_from_mask(cur_mask);
02949 p = pow(2, i);
02950 cpl_image_power(cur_image, p);
02951 cpl_image_add(bpm, cur_image);
02952 cpl_image_delete(cur_image);
02953 }
02954
02955 cpl_mask_or(mask, cur_mask);
02956
02957 cpl_mask_delete(cur_mask);
02958 cpl_stats_delete(stats);
02959 }
02960
02961 if(detmon_lg_config.bpmbin) {
02962 bpm = cpl_image_new_from_mask(mask);
02963 }
02964
02965 *nbpixs += cpl_mask_count(mask);
02966
02967 cpl_mask_delete(mask);
02968
02969 return bpm;
02970 }
02971
02972
02984
02985
02986 static double
02987 irplib_detmon_autocorr_factor(const cpl_image * image,
02988 cpl_image ** autocorr_image, int m, int n)
02989 {
02990 cpl_image * mycorr_image;
02991 double autocorr;
02992
02993 #ifdef HAVE_FFTW
02994
02995
02996 mycorr_image = irplib_detmon_image_correlate(image, image, m, n);
02997 #else
02998 mycorr_image = irplib_detmon_autocorrelate(image, m, n);
02999 #endif
03000 if(mycorr_image == NULL) {
03001 return -1;
03002 }
03003
03004 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), -1);
03005
03006
03007
03008 autocorr = cpl_image_get_flux(mycorr_image);
03009
03010 if (autocorr_image) *autocorr_image = mycorr_image;
03011 else cpl_image_delete(mycorr_image);
03012
03013 return autocorr;
03014 }
03015
03016
03047
03048 static cpl_error_code
03049 irplib_detmon_lg_save(const cpl_parameterlist * parlist,
03050 cpl_frameset * frameset,
03051 const char *recipe_name,
03052 const char *pipeline_name,
03053 const char *pafregexp,
03054 const char *procatg_lintbl,
03055 const char *procatg_gaintbl,
03056 const char *procatg_coeffscube,
03057 const char *procatg_bpm,
03058 const char *procatg_corr,
03059 const char *procatg_diff,
03060 const char *package,
03061 cpl_imagelist * coeffs,
03062 cpl_table * gain_table,
03063 cpl_table * linear_table,
03064 cpl_image * bpms,
03065 cpl_imagelist * autocorr_images,
03066 cpl_imagelist * diff_flats,
03067 cpl_propertylist * qclist,
03068 const int flag_sets,
03069 const int which_set,
03070 const cpl_frameset * usedframes,
03071 int whichext)
03072 {
03073
03074 cpl_frame *ref_frame;
03075 cpl_propertylist *plist = NULL;
03076 cpl_propertylist *mainplist = NULL;
03077 char *name_o = NULL;
03078 int nb_images;
03079 int i;
03080 cpl_error_code error;
03081 cpl_propertylist * xplist = NULL;
03082 cpl_propertylist * paflist = NULL;
03083
03084
03085 if (detmon_lg_config.exts < 0) {
03086 const char * filename =
03087 cpl_frame_get_filename(cpl_frameset_get_first(frameset));
03088
03089
03090 xplist = cpl_propertylist_load_regexp(filename, whichext,
03091 "ESO DET", 0);
03092 skip_if(cpl_propertylist_append(xplist, qclist));
03093 }
03094
03095
03096
03097
03098 ref_frame = cpl_frameset_get_first(frameset);
03099
03100 skip_if((mainplist =
03101 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03102 0)) == NULL);
03103
03104
03105
03106
03107
03108
03109 if(!flag_sets) {
03110 name_o = cpl_sprintf("%s_linearity_table.fits", recipe_name);
03111 assert(name_o != NULL);
03112 } else {
03113 name_o =
03114 cpl_sprintf("%s_linearity_table_set%02d.fits", recipe_name,
03115 which_set);
03116 assert(name_o != NULL);
03117 }
03118
03119 if (detmon_lg_config.exts >= 0) {
03120
03121 skip_if(cpl_dfs_save_table(frameset, parlist, usedframes, linear_table,
03122 NULL, recipe_name, procatg_lintbl, qclist, NULL,
03123 package, name_o));
03124 } else {
03125 if(whichext == 1) {
03126
03127 skip_if(cpl_dfs_save_table(frameset, parlist, usedframes, linear_table,
03128 xplist, recipe_name, procatg_lintbl, NULL,
03129 NULL, package, name_o));
03130 } else {
03131 skip_if(cpl_table_save(linear_table, NULL, xplist, name_o,
03132 CPL_IO_EXTEND));
03133 }
03134 }
03135
03136
03137 cpl_free(name_o);
03138 name_o = NULL;
03139
03140
03141
03142
03143
03144
03145 if(!flag_sets) {
03146 name_o = cpl_sprintf("%s_gain_table.fits", recipe_name);
03147 assert(name_o != NULL);
03148 } else {
03149 name_o =
03150 cpl_sprintf("%s_gain_table_set%02d.fits", recipe_name,
03151 which_set);
03152 assert(name_o != NULL);
03153 }
03154
03155 if (detmon_lg_config.exts >= 0) {
03156
03157 skip_if(cpl_dfs_save_table(frameset, parlist, usedframes, gain_table,
03158 NULL, recipe_name, procatg_gaintbl, qclist,
03159 NULL, package, name_o));
03160 } else {
03161 if(whichext == 1) {
03162
03163 skip_if(cpl_dfs_save_table(frameset, parlist, usedframes, gain_table,
03164 xplist, recipe_name, procatg_gaintbl, NULL,
03165 NULL, package, name_o));
03166 } else {
03167 skip_if(cpl_table_save(gain_table, NULL, xplist, name_o,
03168 CPL_IO_EXTEND));
03169 }
03170 }
03171
03172
03173 cpl_free(name_o);
03174 name_o = NULL;
03175
03176 if(detmon_lg_config.pix2pix) {
03177
03178
03179
03180
03181
03182
03183 if(!flag_sets) {
03184 name_o =
03185 cpl_sprintf("%s_coeffs_cube.fits", recipe_name);
03186 assert(name_o != NULL);
03187 } else {
03188 name_o =
03189 cpl_sprintf("%s_coeffs_cube_set%02d.fits",
03190 recipe_name, which_set);
03191 assert(name_o != NULL);
03192 }
03193
03194
03195 if(detmon_lg_config.exts >= 0) {
03196 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(4, 1, 0)
03197 skip_if(cpl_dfs_save_imagelist
03198 (frameset, parlist, usedframes, coeffs, CPL_BPP_IEEE_FLOAT,
03199 recipe_name, procatg_coeffscube, qclist, NULL, package,
03200 name_o));
03201 #else
03202 cpl_propertylist * hlist = cpl_propertylist_new();
03203 cpl_frame * product_frame = NULL;
03204
03205 product_frame = cpl_frame_new();
03206 cpl_frame_set_filename(product_frame, name_o);
03207 cpl_frame_set_tag(product_frame, procatg_coeffscube);
03208 cpl_frame_set_type(product_frame, CPL_FRAME_TYPE_IMAGE);
03209 cpl_frame_set_group(product_frame, CPL_FRAME_GROUP_PRODUCT);
03210 cpl_frame_set_level(product_frame, CPL_FRAME_LEVEL_FINAL);
03211
03212 if(cpl_dfs_setup_product_header(hlist,product_frame,frameset,
03213 parlist,recipe_name,
03214 package, "PRO-1.15") !=
03215 CPL_ERROR_NONE) {
03216 cpl_msg_error(cpl_func,
03217 "Problem in the product DFS-compliance");
03218 cpl_propertylist_delete(hlist);
03219 cpl_frame_delete(product_frame);
03220 return cpl_error_get_code();
03221 }
03222
03223 error = cpl_propertylist_append(hlist, mainplist);
03224 cpl_ensure_code(!error, error);
03225
03226 cpl_msg_info(cpl_func, "Writing DATA CUBE");
03227 error = cpl_imagelist_save(coeffs, name_o, CPL_BPP_IEEE_FLOAT,
03228 hlist, CPL_IO_DEFAULT);
03229 cpl_ensure_code(!error, error);
03230 cpl_propertylist_delete(hlist);
03231 cpl_frameset_insert(frameset, product_frame);
03232 #endif
03233 } else {
03234 if(whichext == 1) {
03235 skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
03236 CPL_BPP_IEEE_FLOAT, recipe_name,
03237 procatg_coeffscube, NULL, NULL,
03238 package, name_o));
03239 skip_if(cpl_imagelist_save(coeffs,
03240 name_o, CPL_BPP_IEEE_FLOAT, xplist,
03241 CPL_IO_EXTEND));
03242 } else {
03243 skip_if(cpl_imagelist_save(coeffs,
03244 name_o, CPL_BPP_IEEE_FLOAT, xplist,
03245 CPL_IO_EXTEND));
03246 }
03247 }
03248 cpl_free(name_o);
03249 name_o = NULL;
03250
03251
03252
03253
03254
03255
03256 if(!flag_sets) {
03257 name_o = cpl_sprintf("%s_bpm.fits", recipe_name);
03258 assert(name_o != NULL);
03259 } else {
03260 name_o =
03261 cpl_sprintf("%s_bpm_set%02d.fits", recipe_name, which_set);
03262 assert(name_o != NULL);
03263 }
03264
03265
03266 if(detmon_lg_config.exts >= 0) {
03267 skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, bpms,
03268 CPL_BPP_IEEE_FLOAT, recipe_name,
03269 procatg_bpm, qclist, NULL, package,
03270 name_o));
03271 } else {
03272 if (whichext == 1) {
03273 skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
03274 CPL_BPP_IEEE_FLOAT, recipe_name,
03275 procatg_bpm, NULL, NULL, package,
03276 name_o));
03277 skip_if(cpl_image_save(bpms, name_o, CPL_BPP_IEEE_FLOAT,
03278 xplist, CPL_IO_EXTEND));
03279 } else {
03280 skip_if(cpl_image_save(bpms, name_o, CPL_BPP_IEEE_FLOAT,
03281 xplist, CPL_IO_EXTEND));
03282 }
03283 }
03284
03285 cpl_free(name_o);
03286 name_o = NULL;
03287
03288 }
03289
03290 if(detmon_lg_config.intermediate) {
03291
03292
03293
03294 int j;
03295
03296 nb_images = cpl_imagelist_get_size(autocorr_images);
03297 cpl_ensure_code(nb_images > 0, CPL_ERROR_DATA_NOT_FOUND);
03298
03299
03300 for(i = 0; i < nb_images; i++) {
03301
03302 if(!flag_sets) {
03303 name_o =
03304 cpl_sprintf("%s_autocorr_%d.fits", recipe_name, i);
03305 assert(name_o != NULL);
03306 } else {
03307 name_o =
03308 cpl_sprintf("%s_autocorr_%d_set%02d.fits",
03309 recipe_name, i, which_set);
03310 assert(name_o != NULL);
03311 }
03312
03313
03314
03315 if(detmon_lg_config.exts >= 0) {
03316 skip_if(cpl_dfs_save_image
03317 (frameset, parlist, usedframes,
03318 cpl_imagelist_get(autocorr_images, i), CPL_BPP_IEEE_FLOAT,
03319 recipe_name, procatg_corr, qclist, NULL, package,
03320 name_o));
03321 } else {
03322 if(whichext == 1) {
03323 skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
03324 CPL_BPP_IEEE_FLOAT, recipe_name,
03325 procatg_corr, NULL, NULL,
03326 package, name_o));
03327 skip_if(cpl_image_save(cpl_imagelist_get(autocorr_images, i),
03328 name_o, CPL_BPP_IEEE_FLOAT, xplist,
03329 CPL_IO_EXTEND));
03330 } else {
03331 skip_if(cpl_image_save(cpl_imagelist_get(autocorr_images, i),
03332 name_o, CPL_BPP_IEEE_FLOAT, xplist,
03333 CPL_IO_EXTEND));
03334 }
03335 }
03336 cpl_free(name_o);
03337 name_o = NULL;
03338 }
03339
03340
03341
03342
03343
03344 for(i = 0; i < nb_images; i++) {
03345
03346 if(!flag_sets) {
03347 name_o =
03348 cpl_sprintf("%s_diff_flat_%d.fits", recipe_name, i);
03349 assert(name_o != NULL);
03350 } else {
03351 name_o =
03352 cpl_sprintf("%s_diff_flat_%d_set%02d.fits",
03353 recipe_name, i, which_set);
03354 assert(name_o != NULL);
03355 }
03356
03357
03358
03359 if(detmon_lg_config.exts >= 0) {
03360 skip_if(cpl_dfs_save_image
03361 (frameset, parlist, usedframes,
03362 cpl_imagelist_get(diff_flats, i), CPL_BPP_IEEE_FLOAT,
03363 recipe_name, procatg_diff, qclist, NULL, package,
03364 name_o));
03365 } else {
03366 skip_if(cpl_dfs_save_image(frameset, parlist, usedframes, NULL,
03367 CPL_BPP_IEEE_FLOAT, recipe_name,
03368 procatg_diff, NULL, NULL,
03369 package, name_o));
03370
03371 for(j = 0; j < detmon_lg_config.nb_extensions; j++) {
03372 skip_if(cpl_image_save(cpl_imagelist_get(diff_flats, i),
03373 name_o, CPL_BPP_IEEE_FLOAT, xplist,
03374 CPL_IO_EXTEND));
03375 }
03376 }
03377 cpl_free(name_o);
03378 name_o = NULL;
03379 }
03380
03381 }
03382
03383
03384
03385
03386
03387 paflist = cpl_propertylist_new();
03388
03389
03390
03391 if(detmon_lg_config.exts >= 0) {
03392 skip_if((plist =
03393 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03394 detmon_lg_config.exts)) == NULL);
03395
03396 if(!flag_sets) {
03397 name_o = cpl_sprintf("%s.paf", detmon_lg_config.pafname);
03398 assert(name_o != NULL);
03399 } else {
03400 name_o = cpl_sprintf("%s_set%02d.paf",
03401 detmon_lg_config.pafname, which_set);
03402 assert(name_o != NULL);
03403 }
03404 } else {
03405 skip_if((plist =
03406 cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
03407 whichext)) == NULL);
03408
03409
03410 if(!flag_sets) {
03411 name_o = cpl_sprintf("%s_ext%02d.paf",
03412 detmon_lg_config.pafname, whichext);
03413 assert(name_o != NULL);
03414 } else {
03415 name_o = cpl_sprintf("%s_set%02d_ext%02d.paf",
03416 detmon_lg_config.pafname,
03417 which_set, whichext);
03418 assert(name_o != NULL);
03419 }
03420 }
03421
03422
03423 skip_if(cpl_propertylist_copy_property_regexp(paflist, plist,
03424 pafregexp, 0));
03425 skip_if(cpl_propertylist_copy_property_regexp(paflist, mainplist,
03426 pafregexp, 0));
03427
03428 skip_if(error = cpl_propertylist_append(paflist, qclist));
03429
03430
03431 skip_if(cpl_dfs_save_paf(pipeline_name, recipe_name, paflist, name_o));
03432
03433 end_skip;
03434
03435 cpl_propertylist_delete(xplist);
03436 cpl_propertylist_delete(paflist);
03437 cpl_propertylist_delete(plist);
03438 cpl_free(name_o);
03439 cpl_propertylist_delete(mainplist);
03440
03441 return cpl_error_get_code();
03442 }
03443
03444
03451
03452 static cpl_error_code
03453 irplib_detmon_opt_contamination(const cpl_image * reduced,
03454 cpl_propertylist * qclist)
03455 {
03456 cpl_error_code error;
03457 double median[5] = {0, 0, 0, 0, 0};
03458
03459 median[0] = cpl_image_get_median_window(reduced,
03460 detmon_lg_config.llx1,
03461 detmon_lg_config.lly1,
03462 detmon_lg_config.urx1,
03463 detmon_lg_config.ury1);
03464 cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03465 error = cpl_propertylist_append_double(qclist, "ESO QC CONTAM1",
03466 median[0]);
03467 cpl_ensure_code(!error, error);
03468
03469 median[1] = cpl_image_get_median_window(reduced,
03470 detmon_lg_config.llx2,
03471 detmon_lg_config.lly2,
03472 detmon_lg_config.urx2,
03473 detmon_lg_config.ury2);
03474 cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03475 error = cpl_propertylist_append_double(qclist, "ESO QC CONTAM2",
03476 median[1]);
03477 cpl_ensure_code(!error, error);
03478
03479 median[2] = cpl_image_get_median_window(reduced,
03480 detmon_lg_config.llx3,
03481 detmon_lg_config.lly3,
03482 detmon_lg_config.urx3,
03483 detmon_lg_config.ury3);
03484 cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03485 error = cpl_propertylist_append_double(qclist, "ESO QC CONTAM3",
03486 median[2]);
03487 cpl_ensure_code(!error, error);
03488
03489 median[3] = cpl_image_get_median_window(reduced,
03490 detmon_lg_config.llx4,
03491 detmon_lg_config.lly4,
03492 detmon_lg_config.urx4,
03493 detmon_lg_config.ury4);
03494 cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03495 error = cpl_propertylist_append_double(qclist, "ESO QC CONTAM4",
03496 median[3]);
03497 cpl_ensure_code(!error, error);
03498
03499 median[4] = cpl_image_get_median_window(reduced,
03500 detmon_lg_config.llx5,
03501 detmon_lg_config.lly5,
03502 detmon_lg_config.urx5,
03503 detmon_lg_config.ury5);
03504 cpl_ensure_code(!cpl_error_get_code(), cpl_error_get_code());
03505 error = cpl_propertylist_append_double(qclist, "ESO QC CONTAM5",
03506 median[4]);
03507 cpl_ensure_code(!error, error);
03508
03509 return cpl_error_get_code();
03510 }
03511
03512
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03566
03567 int
03568 irplib_detmon_lg_dfs_set_groups(cpl_frameset * set,
03569 const char *tag_on, const char *tag_off)
03570 {
03571 cpl_frame *cur_frame;
03572 const char *tag;
03573 int nframes;
03574 int i;
03575
03576
03577 if(set == NULL)
03578 return -1;
03579
03580
03581 nframes = cpl_frameset_get_size(set);
03582
03583
03584 for(i = 0; i < nframes; i++) {
03585 cur_frame = cpl_frameset_get_frame(set, i);
03586 tag = cpl_frame_get_tag(cur_frame);
03587
03588
03589 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
03590 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
03591
03592
03593
03594
03595
03596 }
03597 return 0;
03598 }
03599
03600
03612
03613 static cpl_error_code
03614 irplib_detmon_lg_reduce_all(const cpl_table * linear_table,
03615 cpl_propertylist * qclist,
03616 cpl_imagelist ** coeffs_ptr,
03617 cpl_image ** bpms_ptr,
03618 const cpl_imagelist * linearity_inputs,
03619 const cpl_table * gain_table,
03620 int which_ext)
03621 {
03622
03623 int nbpixs = 0;
03624 const int nsets = cpl_table_get_nrow(linear_table);
03625 int i;
03626 double autocorr;
03627 cpl_polynomial *poly_linfit = NULL;
03628 cpl_image *fiterror = NULL;
03629 char * name_o1 = NULL;
03630 char * name_o2 = NULL;
03631 double * pcoeffs = cpl_malloc(sizeof(double)*(detmon_lg_config.order + 1));
03632 unsigned mode = detmon_lg_config.autocorr ? IRPLIB_GAIN_WITH_AUTOCORR : 0;
03633
03634
03635
03636 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
03637
03638 skip_if(cpl_propertylist_append_string(qclist, DETMON_QC_METHOD,
03639 detmon_lg_config.method));
03640 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_METHOD,
03641 DETMON_QC_METHOD_C));
03642
03643 if (!strcmp(detmon_lg_config.method, "PTC")) {
03644
03645 if (detmon_lg_config.exts >= 0) {
03646 cpl_msg_info(cpl_func,
03647 "Polynomial fitting for the GAIN (constant term method)");
03648 } else {
03649 cpl_msg_info(cpl_func,
03650 "Polynomial fitting for the GAIN (constant term method)"
03651 " for extension nb %d", which_ext);
03652 }
03653 skip_if(irplib_detmon_lg_qc_ptc(gain_table, qclist, mode));
03654 } else {
03655 skip_if(irplib_detmon_lg_qc_med(gain_table, qclist));
03656 }
03657
03658
03659
03660 if(detmon_lg_config.lamp_ok) {
03661 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LAMP_FLUX,
03662 detmon_lg_config.cr));
03663 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LAMP_FLUX,
03664 DETMON_QC_LAMP_FLUX_C));
03665 }
03666
03667
03668 if(detmon_lg_config.autocorr == TRUE) {
03669 autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
03670 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
03671 autocorr));
03672 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
03673 DETMON_QC_AUTOCORR_C));
03674 }
03675 if (detmon_lg_config.exts >= 0) {
03676 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix");
03677 } else {
03678 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix"
03679 " for extension nb %d", which_ext);
03680 }
03681
03682 if(!detmon_lg_config.pix2pix) {
03683 double mse = 0;
03684
03685 const cpl_vector *y =
03686 cpl_vector_wrap(nsets,
03687 (double *)cpl_table_get_data_double_const(linear_table,
03688 "MED"));
03689 const cpl_vector *x =
03690 cpl_vector_wrap(nsets,
03691 (double *)cpl_table_get_data_double_const(linear_table,
03692 "DIT"));
03693
03694 if(x == NULL || y == NULL) {
03695 cpl_vector_unwrap((cpl_vector *)x);
03696 cpl_vector_unwrap((cpl_vector *)y);
03697
03698
03699
03700
03701
03702
03703 skip_if(1);
03704 }
03705
03706 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
03707 poly_linfit = cpl_polynomial_fit_1d_create(x, y,
03708 detmon_lg_config.order,
03709 &mse);
03710
03711 if(detmon_lg_config.order == cpl_vector_get_size(x) - 1) {
03712 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
03713 mse = 0;
03714 }
03715
03716 if(poly_linfit == NULL) {
03717 cpl_vector_unwrap((cpl_vector *)x);
03718 cpl_vector_unwrap((cpl_vector *)y);
03719
03720 skip_if(1);
03721 }
03722
03723 cpl_vector_unwrap((cpl_vector *)x);
03724 cpl_vector_unwrap((cpl_vector *)y);
03725
03726 for(i = 0; i <= detmon_lg_config.order; i++) {
03727 const double coeff =
03728 cpl_polynomial_get_coeff(poly_linfit, &i);
03729 char *name_o =
03730 cpl_sprintf("ESO QC LIN COEF%d", i);
03731 assert(name_o != NULL);
03732 skip_if(cpl_propertylist_append_double(qclist, name_o, coeff));
03733 cpl_free(name_o);
03734 pcoeffs[i] = coeff;
03735 }
03736 skip_if(cpl_propertylist_append_double(qclist, "ESO QC ERRFIT", mse));
03737 } else {
03738 const cpl_vector *x =
03739 cpl_vector_wrap(nsets,
03740 (double *)cpl_table_get_data_double_const(linear_table,
03741 "DIT"));
03742
03743 const cpl_image * first = cpl_imagelist_get_const(linearity_inputs, 0);
03744 int sizex = cpl_image_get_size_x(first);
03745 int sizey = cpl_image_get_size_y(first);
03746
03747 double vsize = cpl_vector_get_size(x);
03748
03749 fiterror = cpl_image_new(sizex, sizey, CPL_TYPE_FLOAT);
03750
03751 *coeffs_ptr =
03752 cpl_fit_imagelist_polynomial(x, linearity_inputs, 0,
03753 detmon_lg_config.order, FALSE,
03754 CPL_TYPE_FLOAT, fiterror);
03755
03756 cpl_vector_unwrap((cpl_vector*)x);
03757 irplib_ensure(*coeffs_ptr != NULL, CPL_ERROR_UNSPECIFIED,
03758 "Failed polynomial fit");
03759
03760 for(i = 0; i <= detmon_lg_config.order; i++) {
03761 cpl_image *image = cpl_imagelist_get(*coeffs_ptr, i);
03762 const double coeff = cpl_image_get_median(image);
03763 pcoeffs[i] = coeff;
03764 name_o1 = cpl_sprintf("ESO QC LIN COEF%d", i);
03765 name_o2 = cpl_sprintf("ESO QC LIN COEF%d ERR", i);
03766 assert(name_o1 != NULL);
03767 assert(name_o2 != NULL);
03768 skip_if(cpl_propertylist_append_double(qclist, name_o1, coeff));
03769 cpl_free(name_o1);
03770 name_o1= NULL;
03771 skip_if(cpl_propertylist_append_double(qclist, name_o2,
03772 cpl_image_get_stdev(image)));
03773 cpl_free(name_o2);
03774 name_o2= NULL;
03775 }
03776
03777 if(detmon_lg_config.order == vsize - 1) {
03778 cpl_msg_warning(cpl_func, "The fitting is not over-determined.");
03779 skip_if(cpl_propertylist_append_double(qclist, "ESO QC ERRFIT",
03780 0.0));
03781
03782 } else {
03783 skip_if(cpl_propertylist_append_double(qclist, "ESO QC ERRFIT",
03784 cpl_image_get_median(fiterror)));
03785 }
03786 }
03787
03788 skip_if(irplib_detmon_lg_lineff(pcoeffs, qclist));
03789
03790
03791 if (detmon_lg_config.exts >= 0) {
03792 cpl_msg_info(cpl_func, "Bad pixel detection");
03793 } else {
03794 cpl_msg_info(cpl_func, "Bad pixel detection"
03795 " for extension nb %d", which_ext);
03796 }
03797
03798 if(detmon_lg_config.pix2pix) {
03799 *bpms_ptr = irplib_detmon_bpixs(*coeffs_ptr, &nbpixs);
03800 skip_if(*bpms_ptr == NULL);
03801 }
03802
03803 skip_if(cpl_propertylist_append_int(qclist, DETMON_QC_NUM_BPM, nbpixs));
03804 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_NUM_BPM,
03805 DETMON_QC_NUM_BPM_C));
03806
03807 if(detmon_lg_config.lamp_stability != 0.0) {
03808 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LAMP_STAB,
03809 detmon_lg_config.lamp_stability));
03810 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LAMP_STAB,
03811 DETMON_QC_LAMP_STAB_C));
03812 }
03813 end_skip;
03814
03815 cpl_free(pcoeffs);
03816 cpl_free(name_o1);
03817 cpl_free(name_o2);
03818 cpl_image_delete(fiterror);
03819 cpl_polynomial_delete(poly_linfit);
03820
03821 return cpl_error_get_code();
03822 }
03823
03824
03831
03832 static cpl_error_code
03833 irplib_detmon_lg_lineff(double * pcoeffs,
03834 cpl_propertylist * qclist)
03835 {
03836 double lineff = 0;
03837 double root = 0;
03838 cpl_polynomial * poly = cpl_polynomial_new(1);
03839 int i;
03840
03841 double residual, slope;
03842
03843
03844
03845
03846
03847 pcoeffs[0] -= detmon_lg_config.ref_level;
03848
03849 for (i = 2; i <= detmon_lg_config.order; i++) {
03850 int j;
03851 for(j = 0; j < i; j++) {
03852 pcoeffs[i] /= pcoeffs[1];
03853 }
03854 }
03855
03856 pcoeffs[1] = 1;
03857
03858 for (i = 0; i <= detmon_lg_config.order; i++) {
03859 skip_if(cpl_polynomial_set_coeff(poly, &i, pcoeffs[i]));
03860 }
03861
03862
03863
03864
03865
03866
03867
03868 residual = cpl_polynomial_eval_1d(poly, 0.0, &slope);
03869
03870 skip_if(slope <= 0.0);
03871 skip_if(residual >= 0.0);
03872
03873 skip_if(cpl_polynomial_solve_1d(poly, 0.0, &root, 1));
03874
03875 lineff = (root - detmon_lg_config.ref_level) /
03876 detmon_lg_config.ref_level;
03877
03878 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_LIN_EFF,
03879 lineff));
03880 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_LIN_EFF,
03881 DETMON_QC_LIN_EFF_C));
03882
03883 end_skip;
03884
03885 cpl_polynomial_delete(poly);
03886
03887 return cpl_error_get_code();
03888 }
03889
03890
03897
03898 static cpl_error_code
03899 irplib_detmon_lg_qc_ptc(const cpl_table * gain_table,
03900 cpl_propertylist * qclist, unsigned mode)
03901 {
03902 double mse = 0;
03903 cpl_polynomial *poly_fit = NULL;
03904 cpl_polynomial *poly_fit2 = NULL;
03905 int i;
03906 const int nsets = cpl_table_get_nrow(gain_table);
03907
03908
03909
03910
03911
03912 const cpl_vector *x;
03913 const cpl_vector *y;
03914
03915 cpl_errorstate prestate;
03916 double coef = 0;
03917
03918 cpl_ensure_code(gain_table != NULL, CPL_ERROR_NULL_INPUT);
03919 cpl_ensure_code(qclist != NULL, CPL_ERROR_NULL_INPUT);
03920
03921 x = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT"));
03922
03923 y = cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
03924
03925 skip_if(x == NULL || y == NULL);
03926
03927 poly_fit = cpl_polynomial_fit_1d_create(x, y, 1, &mse);
03928 skip_if(poly_fit == NULL);
03929
03930
03931 i = 1;
03932 prestate = cpl_errorstate_get();
03933 coef = cpl_polynomial_get_coeff(poly_fit, &i);
03934 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
03935
03936 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_CONAD, coef));
03937 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_CONAD,
03938 DETMON_QC_CONAD_C));
03939
03940 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
03941 1 / coef));
03942 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
03943 DETMON_QC_GAIN_C));
03944
03945 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE, mse));
03946 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
03947 DETMON_QC_GAIN_MSE_C));
03948 i = 0;
03949 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_RON,
03950 cpl_polynomial_get_coeff(poly_fit, &i)));
03951 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_RON,
03952 DETMON_QC_RON_C));
03953
03954 if(mode & IRPLIB_GAIN_WITH_AUTOCORR){
03955 const cpl_vector *x2 =
03956 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "X_FIT_CORR"));
03957 const cpl_vector *y2 =
03958 cpl_vector_wrap(nsets, (double *)cpl_table_get_data_double_const(gain_table, "Y_FIT"));
03959
03960 if(x2 == NULL || y2 == NULL) {
03961 cpl_vector_unwrap((cpl_vector *)x2);
03962 cpl_vector_unwrap((cpl_vector *)y2);
03963
03964
03965
03966
03967
03968
03969 skip_if(1);
03970 }
03971
03972
03973 poly_fit2 = cpl_polynomial_fit_1d_create(x2, y2, 1, &mse);
03974 if(poly_fit2 == NULL) {
03975 cpl_vector_unwrap((cpl_vector *)x2);
03976 cpl_vector_unwrap((cpl_vector *)y2);
03977
03978 skip_if(1);
03979 }
03980
03981 cpl_vector_unwrap((cpl_vector *)x2);
03982 cpl_vector_unwrap((cpl_vector *)y2);
03983
03984
03985 i = 1;
03986 prestate = cpl_errorstate_get();
03987 coef = cpl_polynomial_get_coeff(poly_fit2, &i);
03988 skip_if (!cpl_errorstate_is_equal(prestate) || coef == 0);
03989
03990 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
03991 1 / coef));
03992 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
03993 DETMON_QC_GAIN_CORR_C));
03994 }
03995
03996 end_skip;
03997
03998
03999 cpl_vector_unwrap((cpl_vector *)x);
04000 cpl_vector_unwrap((cpl_vector *)y);
04001 cpl_polynomial_delete(poly_fit);
04002 cpl_polynomial_delete(poly_fit2);
04003
04004 return cpl_error_get_code();
04005 }
04006
04007
04014
04015 static cpl_error_code
04016 irplib_detmon_lg_qc_med(const cpl_table * gain_table,
04017 cpl_propertylist * qclist)
04018 {
04019 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN,
04020 cpl_table_get_column_median
04021 (gain_table, "GAIN")));
04022 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN,
04023 DETMON_QC_GAIN_C));
04024
04025 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_MSE,
04026 cpl_table_get_column_stdev
04027 (gain_table, "GAIN")));
04028 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_MSE,
04029 DETMON_QC_GAIN_MSE_C));
04030
04031 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_GAIN_CORR,
04032 cpl_table_get_column_median
04033 (gain_table, "GAIN_CORR")));
04034 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_GAIN_CORR,
04035 DETMON_QC_GAIN_CORR_C));
04036 end_skip;
04037
04038 return cpl_error_get_code();
04039 }
04040
04041
04042
04051
04052 static cpl_error_code
04053 irplib_detmon_lg_rescale(cpl_imagelist * to_rescale)
04054 {
04055 double med1 =
04056 cpl_image_get_median(cpl_imagelist_get(to_rescale, 0));
04057 double med2 =
04058 cpl_image_get_median(cpl_imagelist_get(to_rescale, 1));
04059
04060 skip_if(0);
04061
04062 if(fabs(med1 / med2 - 1) > 0.001) {
04063 if(med1 > med2)
04064 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 0),
04065 med1 / med2));
04066 else
04067 skip_if(cpl_image_divide_scalar(cpl_imagelist_get(to_rescale, 1),
04068 med2 / med1));
04069 }
04070
04071 end_skip;
04072
04073 return cpl_error_get_code();
04074 }
04075
04076
04094
04095 static cpl_error_code
04096 irplib_detmon_pair_extract(const cpl_frameset * set,
04097 int * selection, int selected,
04098 int nsets_extracted,
04099 int * with_equal_dit,
04100 int onoff,
04101 cpl_frameset ** pair)
04102 {
04103 int new_with_equal_dit = 0;
04104
04105 cpl_ensure_code(set != NULL, CPL_ERROR_NULL_INPUT);
04106 cpl_ensure_code(selection != NULL, CPL_ERROR_NULL_INPUT);
04107 cpl_ensure_code(with_equal_dit != NULL, CPL_ERROR_NULL_INPUT);
04108 cpl_ensure_code(pair != NULL, CPL_ERROR_NULL_INPUT);
04109
04110 *pair = cpl_frameset_extract(set, selection, selected);
04111 cpl_ensure_code(*pair != NULL, cpl_error_get_code());
04112
04113
04114
04115
04116 skip_if(cpl_frameset_get_size(*pair) % 2 != 0);
04117
04118
04119 if(cpl_frameset_get_size(*pair) != 2) {
04120 new_with_equal_dit = cpl_frameset_get_size(*pair) / 2;
04121 if(onoff == 1) {
04122 *with_equal_dit = new_with_equal_dit;
04123 } else {
04124 skip_if (*with_equal_dit != 0 &&
04125 new_with_equal_dit != *with_equal_dit);
04126 }
04127 }
04128
04129
04130 if (new_with_equal_dit != 0) {
04131 int found = 0;
04132 int j;
04133 for(j = 0; j < cpl_frameset_get_size(set); j++) {
04134
04135 if(selection[j] == selected) {
04136 found++;
04137
04138 if((found - 1) / 2 != 0) {
04139 selection[j] =
04140 nsets_extracted + (found - 1) / 2 - 1;
04141 }
04142 }
04143 }
04144 cpl_frameset_delete(*pair);
04145 *pair = cpl_frameset_extract(set, selection, selected);
04146
04147 }
04148
04149 end_skip;
04150
04151 return cpl_error_get_code();
04152 }
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165 static int
04166 irplib_detmon_lg_compare_pairs(const cpl_frame * frame1,
04167 const cpl_frame * frame2)
04168 {
04169 int comparison;
04170 cpl_propertylist *plist1;
04171 cpl_propertylist *plist2;
04172 double dval1, dval2;
04173
04174
04175 if(frame1 == NULL || frame2 == NULL)
04176 return -1;
04177
04178
04179 if((plist1 = cpl_propertylist_load(cpl_frame_get_filename(frame1),
04180 0)) == NULL) {
04181 cpl_msg_error(cpl_func, "getting header from reference frame");
04182 return -1;
04183 }
04184 if((plist2 = cpl_propertylist_load(cpl_frame_get_filename(frame2),
04185 0)) == NULL) {
04186 cpl_msg_error(cpl_func, "getting header from reference frame");
04187 cpl_propertylist_delete(plist1);
04188 return -1;
04189 }
04190
04191
04192 if(cpl_error_get_code()) {
04193 cpl_propertylist_delete(plist1);
04194 cpl_propertylist_delete(plist2);
04195 return -1;
04196 }
04197
04198
04199 comparison = 1;
04200 dval1 = irplib_pfits_get_exptime(plist1);
04201 dval2 = irplib_pfits_get_exptime(plist2);
04202 if(cpl_error_get_code()) {
04203 cpl_msg_error(cpl_func, "cannot get exposure time");
04204 cpl_propertylist_delete(plist1);
04205 cpl_propertylist_delete(plist2);
04206 return -1;
04207 }
04208 if(fabs(dval1 - dval2) > detmon_lg_config.tolerance)
04209 comparison = 0;
04210
04211
04212 cpl_propertylist_delete(plist1);
04213 cpl_propertylist_delete(plist2);
04214 return comparison;
04215 }
04216
04217
04261
04262
04263 cpl_table *
04264 irplib_detmon_gain(const cpl_imagelist * imlist_on,
04265 const cpl_imagelist * imlist_off,
04266 const cpl_vector * exptimes,
04267 int llx,
04268 int lly,
04269 int urx,
04270 int ury,
04271 double kappa,
04272 int nclip,
04273 int m,
04274 int n,
04275 cpl_propertylist * qclist,
04276 unsigned mode,
04277 cpl_imagelist ** diff_imlist,
04278 cpl_imagelist ** autocorr_imlist)
04279 {
04280 cpl_table * gain_table = NULL;
04281 cpl_imagelist * difflist = NULL;
04282 cpl_imagelist * autocorrlist = NULL;
04283 cpl_imagelist * c_onlist = NULL;
04284 cpl_imagelist * c_offlist = NULL;
04285 cpl_vector * dits = NULL;
04286 int ndits;
04287 int i, j;
04288
04289 cpl_ensure(imlist_on != NULL, CPL_ERROR_NULL_INPUT, NULL);
04290 cpl_ensure(imlist_off != NULL, CPL_ERROR_NULL_INPUT, NULL);
04291 cpl_ensure(exptimes != NULL, CPL_ERROR_NULL_INPUT, NULL);
04292 cpl_ensure(qclist != NULL, CPL_ERROR_NULL_INPUT, NULL);
04293
04294
04295 gain_table = cpl_table_new(cpl_vector_get_size(exptimes) / 2);
04296 skip_if(irplib_detmon_gain_table_create(gain_table));
04297
04298
04299 dits = irplib_detmon_lg_find_dits(exptimes);
04300 ndits = cpl_vector_get_size(dits);
04301
04302
04303 if (mode & IRPLIB_GAIN_WITH_AUTOCORR && (diff_imlist || autocorr_imlist)) {
04304 difflist = cpl_imagelist_new();
04305 autocorrlist = cpl_imagelist_new();
04306 }
04307
04308 if (mode & IRPLIB_GAIN_COLLAPSE) {
04309 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
04310 c_offlist = cpl_imagelist_duplicate(imlist_off);
04311 skip_if(irplib_detmon_lg_rescale(c_offlist));
04312 } else {
04313 c_offlist = (cpl_imagelist *) imlist_off;
04314 }
04315 }
04316
04317 for (i = 0; i < ndits; i++) {
04318 int c_nons;
04319 int c_noffs = 0;
04320
04321 c_onlist = cpl_imagelist_new();
04322 c_nons = 0;
04323
04324 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
04325 c_offlist = cpl_imagelist_new();
04326 c_noffs = 0;
04327 }
04328
04329 for(j = 0; j < cpl_vector_get_size(exptimes); j++) {
04330 if (cpl_vector_get(dits, i) == cpl_vector_get(exptimes, j)) {
04331
04332
04333
04334
04335
04336
04337
04338
04339 cpl_image * im_on;
04340 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
04341 const cpl_image * im =
04342 cpl_imagelist_get_const(imlist_on, j);
04343 im_on = cpl_image_duplicate(im);
04344 } else {
04345 im_on = (cpl_image *)cpl_imagelist_get_const(imlist_on, j);
04346 }
04347 skip_if(cpl_imagelist_set(c_onlist, im_on, c_nons));
04348 c_nons++;
04349
04350
04351
04352
04353
04354 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
04355 cpl_image * im_off;
04356 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
04357 const cpl_image * im =
04358 cpl_imagelist_get_const(imlist_off, j);
04359 im_off = cpl_image_duplicate(im);
04360 } else {
04361 im_off =
04362 (cpl_image *) cpl_imagelist_get_const(imlist_off, j);
04363 }
04364 skip_if(cpl_imagelist_set(c_offlist, im_off, c_noffs));
04365 c_noffs++;
04366 }
04367 }
04368 }
04369
04370
04371 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
04372 skip_if (c_nons != c_noffs);
04373
04374
04375 skip_if (c_nons == 0 || c_nons % 2 != 0);
04376
04377
04378 if(mode & IRPLIB_GAIN_WITH_RESCALE) {
04379 skip_if(irplib_detmon_lg_rescale(c_onlist));
04380 if (mode & IRPLIB_GAIN_NO_COLLAPSE)
04381 skip_if(irplib_detmon_lg_rescale(c_offlist));
04382 }
04383
04384
04385
04386 while(c_nons > 0) {
04387 skip_if(irplib_detmon_gain_table_fill_row(gain_table, autocorrlist,
04388 difflist, c_onlist,
04389 c_offlist, kappa, nclip,
04390 llx, lly, urx, ury,
04391 m, n, i, mode));
04392 if (mode & IRPLIB_GAIN_WITH_RESCALE) {
04393 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
04394 cpl_image_delete(cpl_imagelist_unset(c_onlist, 0));
04395 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
04396 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
04397 cpl_image_delete(cpl_imagelist_unset(c_offlist, 0));
04398 }
04399 } else {
04400 cpl_imagelist_unset(c_onlist, 0);
04401 skip_if(0);
04402 cpl_imagelist_unset(c_onlist, 0);
04403 skip_if(0);
04404 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
04405 cpl_imagelist_unset(c_offlist, 0);
04406 skip_if(0);
04407 cpl_imagelist_unset(c_offlist, 0);
04408 skip_if(0);
04409 }
04410 }
04411 skip_if(0);
04412 c_nons -= 2;
04413 }
04414
04415 cpl_imagelist_delete(c_onlist);
04416 if (mode & IRPLIB_GAIN_NO_COLLAPSE) {
04417 cpl_imagelist_delete(c_offlist);
04418 }
04419 }
04420
04421
04422 if (mode & IRPLIB_GAIN_PTC) {
04423 skip_if(irplib_detmon_lg_qc_ptc(gain_table, qclist, mode));
04424 } else {
04425 skip_if(irplib_detmon_lg_qc_med(gain_table, qclist));
04426 }
04427
04428 if(mode & IRPLIB_GAIN_WITH_AUTOCORR) {
04429 double autocorr = cpl_table_get_column_median(gain_table, "AUTOCORR");
04430 skip_if(cpl_propertylist_append_double(qclist, DETMON_QC_AUTOCORR,
04431 autocorr));
04432 skip_if(cpl_propertylist_set_comment(qclist, DETMON_QC_AUTOCORR,
04433 DETMON_QC_AUTOCORR_C));
04434 }
04435
04436 if (diff_imlist != NULL) *diff_imlist = difflist;
04437 if (autocorr_imlist != NULL) *autocorr_imlist = autocorrlist;
04438
04439 end_skip;
04440
04441 cpl_vector_delete(dits);
04442
04443 return gain_table;
04444 }
04445
04446 static cpl_error_code
04447 irplib_detmon_gain_table_create(cpl_table * gain_table)
04448 {
04449 skip_if(cpl_table_new_column(gain_table, "DIT", CPL_TYPE_DOUBLE));
04450 skip_if(cpl_table_new_column(gain_table, "EXPTIME", CPL_TYPE_DOUBLE));
04451 skip_if(cpl_table_new_column(gain_table, "MEAN_ON1", CPL_TYPE_DOUBLE));
04452 skip_if(cpl_table_new_column(gain_table, "MEAN_ON2", CPL_TYPE_DOUBLE));
04453 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF1", CPL_TYPE_DOUBLE));
04454 skip_if(cpl_table_new_column(gain_table, "MEAN_OFF2", CPL_TYPE_DOUBLE));
04455 skip_if(cpl_table_new_column(gain_table, "SIG_ON_DIF", CPL_TYPE_DOUBLE));
04456 skip_if(cpl_table_new_column(gain_table, "SIG_OFF_DIF", CPL_TYPE_DOUBLE));
04457 skip_if(cpl_table_new_column(gain_table, "GAIN", CPL_TYPE_DOUBLE));
04458 skip_if(cpl_table_new_column(gain_table, "AUTOCORR", CPL_TYPE_DOUBLE));
04459 skip_if(cpl_table_new_column(gain_table, "GAIN_CORR", CPL_TYPE_DOUBLE));
04460 skip_if(cpl_table_new_column(gain_table, "ADU", CPL_TYPE_DOUBLE));
04461 skip_if(cpl_table_new_column(gain_table, "X_FIT", CPL_TYPE_DOUBLE));
04462 skip_if(cpl_table_new_column(gain_table, "X_FIT_CORR", CPL_TYPE_DOUBLE));
04463 skip_if(cpl_table_new_column(gain_table, "Y_FIT", CPL_TYPE_DOUBLE));
04464
04465 end_skip;
04466
04467 return cpl_error_get_code();
04468 }
04469
04470 static cpl_vector *
04471 irplib_detmon_lg_find_dits(const cpl_vector * exptimes)
04472 {
04473 cpl_vector * dits = cpl_vector_new(cpl_vector_get_size(exptimes) / 2);
04474 int ndits = 0;
04475
04476 int i, j;
04477
04478
04479 cpl_vector_set(dits, 0, cpl_vector_get(exptimes, 0));
04480 ndits = 1;
04481
04482
04483 for(i = 1; i < cpl_vector_get_size(exptimes); i++) {
04484 int ndiffs = 0;
04485 for (j = 0; j < ndits; j++) {
04486 if (cpl_vector_get(exptimes, i) != cpl_vector_get(dits, j))
04487 ndiffs++;
04488 }
04489 if(ndiffs == ndits) {
04490 cpl_vector_set(dits, ndits, cpl_vector_get(exptimes, i));
04491 ndits++;
04492 }
04493 }
04494
04495 cpl_vector_set_size(dits, ndits);
04496
04497 return dits;
04498 }