00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032
00033
00034
00035
00036
00037 #ifdef HAVE_FFTW
00038 #include <complex.h>
00039 #include <fftw3.h>
00040 #endif
00041
00042 #include <math.h>
00043 #include <string.h>
00044 #include <assert.h>
00045
00046 #include <cpl.h>
00047
00048 #include "irplib_detmon.h"
00049
00050 #include "irplib_utils.h"
00051 #include "irplib_dfs.h"
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 enum pixeltypes
00067 {
00068 HOT = 0,
00069 DEAD = 1,
00070 NOISY = 2
00071 };
00072
00073 static struct
00074 {
00075
00076 int order;
00077 int kappa;
00078 int niter;
00079 int threshold_min;
00080 int threshold_max;
00081 int llx;
00082 int lly;
00083 int urx;
00084 int ury;
00085 int ref_level;
00086 int threshold;
00087 int m;
00088 int n;
00089 int llx1;
00090 int lly1;
00091 int urx1;
00092 int ury1;
00093 int llx2;
00094 int lly2;
00095 int urx2;
00096 int ury2;
00097 int llx3;
00098 int lly3;
00099 int urx3;
00100 int ury3;
00101 int llx4;
00102 int lly4;
00103 int urx4;
00104 int ury4;
00105 int llx5;
00106 int lly5;
00107 int urx5;
00108 int ury5;
00109 cpl_boolean autocorr;
00110 cpl_boolean intermediate;
00111 cpl_boolean collapse;
00112
00113 double cr;
00114 } detmon_lg_config;
00115
00116 #define NIR TRUE
00117 #define OPT FALSE
00118
00119 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(3, 1, 90)
00120 #define irplib_sprintf cpl_sprintf
00121 #endif
00122
00123
00124
00125
00126
00127 static cpl_error_code
00128 irplib_detmon_retrieve_params(const char *,
00129 const char *,
00130 const cpl_parameterlist *);
00131
00132 static cpl_error_code
00133 irplib_detmon_lg_split_onoff(const cpl_frameset *,
00134 cpl_frameset *,
00135 cpl_frameset *,
00136 const char *, const char *, const cpl_boolean);
00137
00138 int
00139 irplib_detmon_compare_dits(const cpl_frame *, const cpl_frame *);
00140
00141 static cpl_error_code
00142 irplib_detmon_lg_reduce(const cpl_frameset *,
00143 const cpl_frameset *,
00144 const int *,
00145 const int *,
00146 const int,
00147 cpl_imagelist **,
00148 cpl_table **,
00149 cpl_table **,
00150 cpl_image **, cpl_propertylist *, const cpl_boolean);
00151
00152 double
00153 irplib_pfits_get_exptime(const cpl_propertylist *);
00154
00155
00156
00157
00158 static cpl_error_code
00159 irplib_detmon_linearity(const cpl_frameset *,
00160 cpl_table **,
00161 cpl_table **,
00162 cpl_imagelist **,
00163 cpl_vector **,
00164 const cpl_imagelist *,
00165 const cpl_imagelist *,
00166 const int,
00167 const int, cpl_propertylist *, const cpl_boolean);
00168
00169 static cpl_error_code
00170 irplib_detmon_gain(cpl_table **,
00171 cpl_table **,
00172 const cpl_imagelist *, const cpl_imagelist *, const int);
00173
00174 static cpl_image *
00175 irplib_detmon_bpixs(const cpl_imagelist *, int *);
00176
00177 static double
00178 irplib_detmon_autocorr_factor(const cpl_image *, const int);
00179
00180 #ifdef HAVE_FFTW
00181 static cpl_image *
00182 irplib_detmon_image_autocorrelate_fftw(const cpl_image *,
00183 const int,
00184 const int);
00185 #endif
00186
00187 static cpl_image *
00188 irplib_detmon_autocorrelate(const cpl_image *,
00189 const int, const int);
00190
00191 static int
00192 irplib_get_clean_mean_window(cpl_image *,
00193 const int,
00194 const int,
00195 const int,
00196 const int,
00197 const int, const int, double *, double *);
00198
00199 static cpl_error_code
00200 irplib_detmon_lg_save(const cpl_parameterlist *,
00201 cpl_frameset *,
00202 const char *,
00203 const char *,
00204 const char *,
00205 const char *,
00206 const char *,
00207 const char *,
00208 const char *,
00209 const cpl_imagelist *,
00210 const cpl_table *,
00211 const cpl_table *,
00212 const cpl_image *,
00213 cpl_propertylist *,
00214 const int, const int, cpl_frameset *, cpl_boolean);
00215
00216 static cpl_error_code
00217 irplib_detmon_opt_contamination(const cpl_image *, cpl_propertylist *);
00218
00219 static int
00220 irplib_detmon_opt_lampcr(cpl_frameset *);
00221
00222 int
00223 irplib_detmon_dfs_set_groups(cpl_frameset *,
00224 const char *,
00225 const char *);
00226
00227 static int
00228 irplib_detmon_retrieve_par(const char *,
00229 const char *,
00230 const char *,
00231 const cpl_parameterlist *);
00232
00233 int
00234 irplib_detmon_fill_parlist(cpl_parameterlist * parlist,
00235 const char *recipe_name, const char *pipeline_name,
00236 int npars, ...);
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 int
00258 irplib_detmon_lg(cpl_frameset * frameset,
00259 const cpl_parameterlist * parlist,
00260 const char *tag_on,
00261 const char *tag_off,
00262 const char *recipe_name,
00263 const char *pipeline_name,
00264 const char *procatg_lintbl,
00265 const char *procatg_gaintbl,
00266 const char *procatg_lincoeff,
00267 const char *procatg_bpm,
00268 const char *package,
00269 int (* compare)(const cpl_frame *,
00270 const cpl_frame *), const cpl_boolean opt_nir)
00271 {
00272 int nsets;
00273 int *selection = NULL;
00274 int i;
00275
00276 #define clreturn_if(CONDITION, ERR_MSG) \
00277 do if (cpl_error_get_code() || CONDITION) { \
00278 cpl_msg_error(cpl_func, ERR_MSG); \
00279 if(selection) cpl_free(selection); \
00280 if(selection_on) cpl_free(selection_on); \
00281 if(selection_off) cpl_free(selection_off); \
00282 if(cur_fset) cpl_frameset_delete(cur_fset); \
00283 if(cur_fset_on) cpl_frameset_delete(cur_fset_on); \
00284 if(cur_fset_off) cpl_frameset_delete(cur_fset_off); \
00285 if(gain_table) cpl_table_delete(gain_table); \
00286 if(linear_table) cpl_table_delete(linear_table); \
00287 if(coeffs) cpl_imagelist_delete(coeffs); \
00288 if(bpms) cpl_image_delete(bpms); \
00289 if(qclist) cpl_propertylist_delete(qclist); \
00290 return -1; \
00291 } while(0)
00292
00293
00294 cpl_ensure(parlist != NULL, CPL_ERROR_NULL_INPUT, -1);
00295 cpl_ensure(frameset != NULL, CPL_ERROR_NULL_INPUT, -1);
00296 cpl_ensure(tag_on != NULL, CPL_ERROR_NULL_INPUT, -1);
00297 cpl_ensure(tag_off != NULL, CPL_ERROR_NULL_INPUT, -1);
00298 cpl_ensure(recipe_name != NULL, CPL_ERROR_NULL_INPUT, -1);
00299 cpl_ensure(procatg_lintbl != NULL, CPL_ERROR_NULL_INPUT, -1);
00300 cpl_ensure(procatg_gaintbl != NULL, CPL_ERROR_NULL_INPUT, -1);
00301 cpl_ensure(procatg_lincoeff != NULL, CPL_ERROR_NULL_INPUT, -1);
00302 cpl_ensure(procatg_bpm != NULL, CPL_ERROR_NULL_INPUT, -1);
00303 cpl_ensure(package != NULL, CPL_ERROR_NULL_INPUT, -1);
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 if(irplib_detmon_dfs_set_groups(frameset, tag_on, tag_off))
00315 cpl_msg_error(cpl_func, "Cannot identify RAW and CALIB frames");
00316
00317 if(irplib_detmon_retrieve_params(pipeline_name, recipe_name, parlist))
00318 cpl_msg_error(cpl_func, "Failed to retrieve input parameters");
00319
00320
00321 if(compare == NULL)
00322 nsets = 1;
00323 else {
00324 cpl_msg_info(cpl_func, "Identify the different settings");
00325 selection = cpl_frameset_labelise(frameset, compare, &nsets);
00326 if(selection == NULL)
00327 cpl_msg_error(cpl_func, "Cannot labelise input frames");
00328 }
00329
00330
00331 for(i = 0; i < nsets; i++) {
00332 int * selection_on = NULL;
00333 int * selection_off = NULL;
00334 cpl_frameset * cur_fset = NULL;
00335 cpl_frameset * cur_fset_on = NULL;
00336 cpl_frameset * cur_fset_off = NULL;
00337 cpl_table * gain_table = NULL;
00338 cpl_table * linear_table = NULL;
00339 cpl_imagelist * coeffs = NULL;
00340 cpl_image * bpms = NULL;
00341 int nsets_on = 0;
00342 int nsets_off = 0;
00343 cpl_propertylist * qclist = cpl_propertylist_new();
00344
00345
00346 cpl_msg_info(cpl_func, "Reduce data set no %d out of %d", i + 1,
00347 nsets);
00348
00349
00350
00351
00352
00353
00354
00355 if(nsets == 1)
00356 cur_fset = cpl_frameset_duplicate(frameset);
00357 else
00358 cur_fset = cpl_frameset_extract(frameset, selection, i);
00359
00360
00361
00362
00363
00364 if(opt_nir == OPT)
00365 irplib_detmon_opt_lampcr(cur_fset);
00366
00367
00368 cur_fset_on = cpl_frameset_new();
00369 cur_fset_off = cpl_frameset_new();
00370 cpl_msg_info(cpl_func, "Splitting into ON and OFF sub-framesets");
00371 irplib_detmon_lg_split_onoff(cur_fset, cur_fset_on, cur_fset_off,
00372 tag_on, tag_off, opt_nir);
00373 clreturn_if(0, "Failed to split into ON and OFF subframesets");
00374
00375
00376 clreturn_if((selection_on =
00377 cpl_frameset_labelise(cur_fset_on,
00378 irplib_detmon_compare_dits,
00379 &nsets_on)) == NULL,
00380 "Cannot labelise ON frames");
00381
00382 if(!detmon_lg_config.collapse)
00383 clreturn_if((selection_off =
00384 cpl_frameset_labelise(cur_fset_off,
00385 irplib_detmon_compare_dits,
00386 &nsets_off)) == NULL,
00387 "Cannot labelise OFF frames");
00388
00389
00390 if(!detmon_lg_config.collapse)
00391 clreturn_if(nsets_on != nsets_off,
00392 "Illegal input: different nb of ON and OFF frames");
00393
00394
00395 cpl_msg_info(cpl_func, "Starting data reduction");
00396
00397 irplib_detmon_lg_reduce(cur_fset_on, cur_fset_off,
00398 selection_on, selection_off,
00399 nsets_on, &coeffs, &gain_table,
00400 &linear_table, &bpms, qclist, opt_nir);
00401 clreturn_if(0, "Cannot perform linearity/gain reduction");
00402
00403
00404 cpl_msg_info(cpl_func, "Saving the products");
00405 if(nsets == 1) {
00406 irplib_detmon_lg_save(parlist, frameset, recipe_name,
00407 pipeline_name, procatg_lintbl,
00408 procatg_gaintbl, procatg_lincoeff,
00409 procatg_bpm, package, coeffs,
00410 gain_table, linear_table, bpms,
00411 qclist, 0, 0, cur_fset, opt_nir);
00412 } else {
00413 irplib_detmon_lg_save(parlist, frameset, recipe_name,
00414 pipeline_name, procatg_lintbl,
00415 procatg_gaintbl, procatg_lincoeff,
00416 procatg_bpm, package, coeffs,
00417 gain_table, linear_table, bpms,
00418 qclist, 1, i + 1, cur_fset, opt_nir);
00419 }
00420 clreturn_if(0, "Cannot save the products");
00421
00422
00423 cpl_free(selection_on);
00424 cpl_free(selection_off);
00425
00426 cpl_frameset_delete(cur_fset);
00427 cpl_frameset_delete(cur_fset_on);
00428 cpl_frameset_delete(cur_fset_off);
00429
00430 cpl_imagelist_delete(coeffs);
00431 cpl_table_delete(gain_table);
00432 cpl_table_delete(linear_table);
00433 cpl_image_delete(bpms);
00434 cpl_propertylist_delete(qclist);
00435 }
00436
00437
00438 if(compare != NULL)
00439 cpl_free(selection);
00440
00441 #undef clreturn_if
00442
00443 return 0;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 #ifdef HAVE_FFTW
00466
00467 cpl_image *
00468 irplib_detmon_image_correlate(const cpl_image * image1,
00469 const cpl_image * image2,
00470 const int m, const int n)
00471 {
00472 cpl_image *image1_padded;
00473 cpl_image *image2_padded;
00474 float *data1;
00475 float *data2;
00476 int nx, ny;
00477 int nx2, ny2;
00478 int i;
00479
00480 fftwf_plan p1;
00481 fftwf_complex *in1;
00482 fftwf_complex *ri1;
00483
00484 fftwf_plan p2;
00485 fftwf_complex *in2;
00486 fftwf_complex *ri2;
00487
00488 fftwf_plan p_inv;
00489 fftwf_complex *in_inv;
00490 fftwf_complex *ri_inv;
00491
00492 fftwf_complex *corr;
00493 float *corr_r;
00494
00495 cpl_image *corr_image;
00496 cpl_image *corr_image_window;
00497 cpl_image *reorganised;
00498 cpl_image *image;
00499
00500
00501 cpl_ensure(image1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
00502 cpl_ensure(image2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
00503
00504 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
00505 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
00506
00507 nx = cpl_image_get_size_x(image1);
00508 ny = cpl_image_get_size_y(image1);
00509
00510 nx2 = cpl_image_get_size_x(image2);
00511 ny2 = cpl_image_get_size_y(image2);
00512
00513
00514 cpl_ensure(nx == nx2 && ny == ny2, CPL_ERROR_ILLEGAL_INPUT, NULL);
00515
00516
00517 image1_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
00518 cpl_image_copy(image1_padded, image1, m + 1, n + 1);
00519
00520 image2_padded = cpl_image_new(nx + 2 * m, ny + 2 * n, CPL_TYPE_FLOAT);
00521 cpl_image_copy(image2_padded, image2, m + 1, n + 1);
00522
00523
00524 data1 = cpl_image_get_data_float(image1_padded);
00525 data2 = cpl_image_get_data_float(image2_padded);
00526
00527
00528 nx = nx + 2 * m;
00529 ny = ny + 2 * n;
00530
00531
00532 in1 = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00533 ri1 = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00534 p1 = fftwf_plan_dft_2d(ny, nx, in1, ri1, FFTW_FORWARD, FFTW_ESTIMATE);
00535
00536
00537 for(i = 0; i < nx * ny; i++) {
00538 *(in1 + i) = (*(data1 + i) + 0.0 * I);
00539 }
00540
00541
00542 fftwf_execute(p1);
00543
00544
00545 fftwf_destroy_plan(p1);
00546 cpl_image_delete(image1_padded);
00547
00548
00549 in2 = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00550 ri2 = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00551 p2 = fftwf_plan_dft_2d(ny, nx, in2, ri2, FFTW_FORWARD, FFTW_ESTIMATE);
00552
00553
00554 for(i = 0; i < nx * ny; i++) {
00555 *(in2 + i) = (*(data2 + i) + 0.0 * I);
00556 }
00557
00558
00559 fftwf_execute(p2);
00560
00561
00562 fftwf_destroy_plan(p2);
00563 cpl_image_delete(image2_padded);
00564
00565
00566 in_inv = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00567 ri_inv = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00568 p_inv = fftwf_plan_dft_2d(ny, nx, in_inv, ri_inv,
00569 FFTW_BACKWARD, FFTW_ESTIMATE);
00570
00571
00572 for(i = 0; i < nx * ny; i++) {
00573 in_inv[i] = conjf(ri1[i]) * ri2[i];
00574 }
00575
00576
00577 fftwf_free(in1);
00578 fftwf_free(ri1);
00579
00580 fftwf_free(in2);
00581 fftwf_free(ri2);
00582
00583
00584 fftwf_execute(p_inv);
00585
00586
00587 fftwf_destroy_plan(p_inv);
00588
00589
00590 corr = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00591 corr_r = (float *) cpl_malloc(sizeof(float) * nx * ny);
00592
00593 for(i = 0; i < nx * ny; i++) {
00594 *(corr + i) = conjf(*(ri_inv + i));
00595 *(corr + i) *= *(ri_inv + i);
00596 corr_r[i] = crealf(*(corr + i));
00597 }
00598 fftwf_free(in_inv);
00599 fftwf_free(ri_inv);
00600
00601
00602 corr_image = cpl_image_wrap_float(nx, ny, corr_r);
00603
00604
00605 fftwf_free(corr);
00606
00607
00608 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00609
00610 image = cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
00611 cpl_image_copy(reorganised, image, 1, 1);
00612 cpl_image_delete(image);
00613
00614 image = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
00615 cpl_image_copy(reorganised, image, nx / 2 + 1, 1);
00616 cpl_image_delete(image);
00617
00618 cpl_image_unwrap(corr_image);
00619 cpl_free(corr_r);
00620
00621 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00622
00623 image = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
00624 cpl_image_copy(corr_image, image, 1, 1);
00625 cpl_image_delete(image);
00626
00627 image = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
00628 cpl_image_copy(corr_image, image, 1, ny / 2 + 1);
00629 cpl_image_delete(image);
00630
00631
00632 corr_image_window = cpl_image_extract(corr_image,
00633 nx / 2 + 1 - m,
00634 ny / 2 + 1 - n,
00635 nx / 2 + 1 + m, ny / 2 + 1 + n);
00636
00637
00638 cpl_image_delete(reorganised);
00639 cpl_image_delete(corr_image);
00640
00641 if(cpl_image_divide_scalar(corr_image_window,
00642 cpl_image_get_max(corr_image_window))) {
00643 cpl_image_delete(corr_image_window);
00644 return NULL;
00645 }
00646
00647 return corr_image_window;
00648 }
00649
00650
00651 static cpl_image *
00652 irplib_detmon_image_autocorrelate_fftw(const cpl_image * image,
00653 const int m, const int n)
00654 {
00655 cpl_image *input;
00656 cpl_image *image_padded;
00657
00658 int nx, ny;
00659 int i;
00660
00661 fftwf_plan p1;
00662 fftwf_complex *fourier;
00663 fftwf_plan p_inv;
00664
00665 cpl_image *corr_image;
00666 cpl_image *corr_image_window;
00667 cpl_image *reorganised;
00668 cpl_image *image1;
00669 int npix;
00670 size_t bigsize;
00671 float *in;
00672
00673
00674 cpl_ensure(image != NULL, CPL_ERROR_NULL_INPUT, NULL);
00675
00676 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
00677 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
00678
00679 nx = cpl_image_get_size_x(image);
00680 ny = cpl_image_get_size_y(image);
00681
00682 npix = (nx + 2 * m) * (ny + 2 * n);
00683
00684
00685 bigsize = 2 * (npix / 2 + 1);
00686
00687
00688 in = (float *) fftw_malloc(sizeof(float) * bigsize);
00689
00690
00691 input = cpl_image_cast(image, CPL_TYPE_FLOAT);
00692
00693 image_padded = cpl_image_wrap_float(nx, ny, in);
00694 cpl_image_copy(image_padded, input, m + 1, n + 1);
00695 cpl_image_delete(input);
00696
00697
00698 nx = nx + 2 * m;
00699 ny = ny + 2 * n;
00700
00701
00702 fourier = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * nx * ny);
00703 p1 = fftwf_plan_dft_r2c_2d(ny, nx, in, fourier, FFTW_FORWARD);
00704
00705
00706 fftwf_execute(p1);
00707
00708
00709 fftwf_destroy_plan(p1);
00710 cpl_image_unwrap(image_padded);
00711
00712
00713 p_inv = fftwf_plan_dft_c2r_2d(ny, nx, fourier, in, FFTW_BACKWARD);
00714
00715
00716 for(i = 0; i < nx * ny; i++) {
00717 fourier[i] = conj(fourier[i]) * fourier[i];
00718 }
00719
00720
00721 fftwf_execute(p_inv);
00722
00723
00724 fftwf_destroy_plan(p_inv);
00725
00726 fftwf_free(fourier);
00727
00728
00729 corr_image = cpl_image_wrap_float(nx, ny, in);
00730
00731
00732 reorganised = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00733
00734 image1 = cpl_image_extract(corr_image, nx / 2 + 1, 1, nx, ny);
00735 cpl_image_copy(reorganised, image1, 1, 1);
00736 cpl_image_delete(image1);
00737
00738 image1 = cpl_image_extract(corr_image, 1, 1, nx / 2, ny);
00739 cpl_image_copy(reorganised, image1, nx / 2 + 1, 1);
00740 cpl_image_delete(image1);
00741
00742 cpl_image_unwrap(corr_image);
00743 fftwf_free(in);
00744
00745 corr_image = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00746 image1 = cpl_image_extract(reorganised, 1, ny / 2 + 1, nx, ny);
00747 cpl_image_copy(corr_image, image1, 1, 1);
00748 cpl_image_delete(image1);
00749
00750 image1 = cpl_image_extract(reorganised, 1, 1, nx, ny / 2);
00751 cpl_image_copy(corr_image, image1, 1, ny / 2 + 1);
00752 cpl_image_delete(image1);
00753
00754
00755 corr_image_window = cpl_image_extract(corr_image,
00756 nx / 2 + 1 - m,
00757 ny / 2 + 1 - n,
00758 nx / 2 + 1 + m, ny / 2 + 1 + n);
00759
00760
00761 cpl_image_delete(reorganised);
00762 cpl_image_delete(corr_image);
00763
00764 if(cpl_image_divide_scalar(corr_image_window,
00765 cpl_image_get_max(corr_image_window))) {
00766 cpl_image_delete(corr_image_window);
00767 return NULL;
00768 }
00769
00770 return corr_image_window;
00771 }
00772 #endif
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 static cpl_image *
00792 irplib_detmon_autocorrelate(const cpl_image * input, const int m, const int n)
00793 {
00794 cpl_image *im_re;
00795 cpl_image *im_im;
00796 int nx, ny;
00797 cpl_image *ifft_re;
00798 cpl_image *ifft_im;
00799 cpl_image *autocorr;
00800 cpl_image *autocorr_norm;
00801 double max;
00802 cpl_image *reorganised;
00803 cpl_image *image;
00804 int p;
00805
00806 cpl_ensure(input != NULL, CPL_ERROR_NULL_INPUT, NULL);
00807
00808 cpl_ensure(m > 0, CPL_ERROR_NULL_INPUT, NULL);
00809 cpl_ensure(n > 0, CPL_ERROR_NULL_INPUT, NULL);
00810
00811 nx = cpl_image_get_size_x(input) + 2 * m;
00812 ny = cpl_image_get_size_y(input) + 2 * n;
00813
00814 p = 128;
00815 while(nx > p || ny > p) {
00816 p *= 2;
00817 }
00818
00819 im_re = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00820 cpl_image_copy(im_re, input, 1, 1);
00821
00822 im_im = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00823
00824 cpl_image_fft(im_re, im_im, CPL_FFT_DEFAULT);
00825
00826 ifft_re = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00827
00828
00829 cpl_image_power(im_re, 2);
00830 cpl_image_add(ifft_re, im_re);
00831 cpl_image_delete(im_re);
00832
00833 cpl_image_power(im_im, 2);
00834 cpl_image_add(ifft_re, im_im);
00835 cpl_image_delete(im_im);
00836
00837 ifft_im = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00838
00839 cpl_image_fft(ifft_re, ifft_im, CPL_FFT_INVERSE);
00840
00841 autocorr = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00842
00843 cpl_image_power(ifft_re, 2);
00844 cpl_image_add(autocorr, ifft_re);
00845 cpl_image_delete(ifft_re);
00846
00847 cpl_image_power(ifft_im, 2);
00848 cpl_image_add(autocorr, ifft_im);
00849 cpl_image_delete(ifft_im);
00850
00851 max = cpl_image_get_max(autocorr);
00852
00853 cpl_image_divide_scalar(autocorr, max);
00854
00855
00856 reorganised = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00857
00858 image = cpl_image_extract(autocorr, p / 2 + 1, 1, p, p);
00859 cpl_image_copy(reorganised, image, 1, 1);
00860 cpl_image_delete(image);
00861
00862 image = cpl_image_extract(autocorr, 1, 1, p / 2, p);
00863 cpl_image_copy(reorganised, image, p / 2 + 1, 1);
00864 cpl_image_delete(image);
00865
00866 cpl_image_delete(autocorr);
00867
00868 autocorr = cpl_image_new(p, p, CPL_TYPE_FLOAT);
00869
00870 image = cpl_image_extract(reorganised, 1, p / 2 + 1, p, p);
00871 cpl_image_copy(autocorr, image, 1, 1);
00872 cpl_image_delete(image);
00873
00874 image = cpl_image_extract(reorganised, 1, 1, p, p / 2);
00875 cpl_image_copy(autocorr, image, 1, p / 2 + 1);
00876 cpl_image_delete(image);
00877
00878 cpl_image_delete(reorganised);
00879
00880 autocorr_norm =
00881 cpl_image_extract(autocorr, p / 2 + 1 - m, p / 2 + 1 - n,
00882 p / 2 + 1 + m, p / 2 + 1 + n);
00883
00884 cpl_image_delete(autocorr);
00885
00886 if(cpl_image_divide_scalar(autocorr_norm,
00887 cpl_image_get_max(autocorr_norm))) {
00888 cpl_image_delete(autocorr_norm);
00889 cpl_ensure(0, cpl_error_get_code(), NULL);
00890 }
00891 return autocorr_norm;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904 int
00905 irplib_detmon_fill_params(cpl_parameterlist * parlist,
00906 const char *recipe_name, const char *pipeline_name)
00907 {
00908 irplib_detmon_fill_parlist(parlist, recipe_name, pipeline_name, 36,
00909 "order",
00910 "Polynomial order for the fit",
00911 "CPL_TYPE_INT", 3,
00912
00913 "kappa",
00914 "Kappa value for the kappa-sigma clipping",
00915 "CPL_TYPE_INT", 3,
00916
00917 "niter",
00918 "Number of iterations to compute rms",
00919 "CPL_TYPE_INT", 25,
00920
00921 "threshold_min",
00922 "Minimum threshold for non-linear pixels rejection",
00923 "CPL_TYPE_INT", 0,
00924
00925 "threshold_max",
00926 "Maximum threshold for non-linear pixels rejection",
00927 "CPL_TYPE_INT", 10000,
00928
00929 "llx",
00930 "x coordinate of the lower-left "
00931 "point of the region of interest",
00932 "CPL_TYPE_INT", 1,
00933
00934 "lly",
00935 "y coordinate of the lower-left "
00936 "point of the region of interest",
00937 "CPL_TYPE_INT", 1,
00938
00939 "urx",
00940 "x coordinate of the upper-right "
00941 "point of the region of interest",
00942 "CPL_TYPE_INT", 1024,
00943
00944 "ury",
00945 "y coordinate of the upper-right "
00946 "point of the region of interest",
00947 "CPL_TYPE_INT", 1024,
00948
00949 "ref_level",
00950 "User reference level",
00951 "CPL_TYPE_INT", 10000,
00952
00953 "threshold",
00954 "Intensity of threshold pixels",
00955 "CPL_TYPE_INT", 10000,
00956
00957 "intermediate",
00958 "De-/Activate intermediate products",
00959 "CPL_TYPE_BOOL", "CPL_FALSE",
00960
00961 "autocorr",
00962 "De-/Activate the autocorr option",
00963 "CPL_TYPE_BOOL", "CPL_FALSE",
00964
00965 "collapse",
00966 "De-/Activate the collapse option",
00967 "CPL_TYPE_BOOL", "CPL_FALSE",
00968
00969 "m",
00970 "Maximum x-shift for the autocorr",
00971 "CPL_TYPE_INT", 26,
00972
00973 "n",
00974 "Maximum y-shift for the autocorr",
00975 "CPL_TYPE_INT", 26,
00976
00977 "llx1",
00978 "x coord of the lower-left point of the first "
00979 "field used for contamination measurement",
00980 "CPL_TYPE_INT", 1,
00981
00982 "lly1",
00983 "y coord of the lower-left point of the first "
00984 "field used for contamination measurement",
00985 "CPL_TYPE_INT", 1,
00986
00987 "urx1",
00988 "x coord of the upper-right point of the first "
00989 "field used for contamination measurement",
00990 "CPL_TYPE_INT", 1024,
00991
00992 "ury1",
00993 "y coord of the upper-right point of the first "
00994 "field used for contamination measurement",
00995 "CPL_TYPE_INT", 1024,
00996
00997 "llx2",
00998 "x coord of the lower-left point of the second "
00999 "field used for contamination measurement",
01000 "CPL_TYPE_INT", 1,
01001
01002 "lly2",
01003 "y coord of the lower-left point of the second "
01004 "field used for contamination measurement",
01005 "CPL_TYPE_INT", 1,
01006
01007 "urx2",
01008 "x coord of the upper-right point of the second "
01009 "field used for contamination measurement",
01010 "CPL_TYPE_INT", 512,
01011
01012 "ury2",
01013 "y coord of the upper-right point of the second "
01014 "field used for contamination measurement",
01015 "CPL_TYPE_INT", 512,
01016
01017 "llx3",
01018 "x coord of the lower-left point of the third "
01019 "field used for contamination measurement",
01020 "CPL_TYPE_INT", 512,
01021
01022 "lly3",
01023 "y coord of the lower-left point of the third "
01024 "field used for contamination measurement",
01025 "CPL_TYPE_INT", 1,
01026
01027 "urx3",
01028 "x coord of the upper-right point of the third "
01029 "field used for contamination measurement",
01030 "CPL_TYPE_INT", 1024,
01031
01032 "ury3",
01033 "y coord of the upper-right point of the third "
01034 "field used for contamination measurement",
01035 "CPL_TYPE_INT", 512,
01036
01037 "llx4",
01038 "x coord of the lower-left point of the fourth "
01039 "field used for contamination measurement",
01040 "CPL_TYPE_INT", 512,
01041
01042 "lly4",
01043 "y coord of the lower-left point of the fourth "
01044 "field used for contamination measurement",
01045 "CPL_TYPE_INT", 512,
01046
01047 "urx4",
01048 "x coord of the upper-right point of the fourth "
01049 "field used for contamination measurement",
01050 "CPL_TYPE_INT", 1024,
01051
01052 "ury4",
01053 "y coord of the upper-right point of the fourth "
01054 "field used for contamination measurement",
01055 "CPL_TYPE_INT", 1024,
01056
01057 "llx5",
01058 "x coord of the lower-left point of the fifth "
01059 "field used for contamination measurement",
01060 "CPL_TYPE_INT", 1,
01061
01062 "lly5",
01063 "y coord of the lower-left point of the fifth "
01064 "field used for contamination measurement",
01065 "CPL_TYPE_INT", 512,
01066
01067 "urx5",
01068 "x coord of the upper-right point of the fifth "
01069 "field used for contamination measurement",
01070 "CPL_TYPE_INT", 512,
01071
01072 "ury5",
01073 "y coord of the upper-right point of the fifth "
01074 "field used for contamination measurement",
01075 "CPL_TYPE_INT", 1024);
01076
01077 return 0;
01078 }
01079
01080 int
01081 irplib_detmon_fill_parlist(cpl_parameterlist * parlist,
01082 const char *recipe_name, const char *pipeline_name,
01083 int npars, ...)
01084 {
01085
01086 va_list ap;
01087
01088 char * par_name;
01089 char * group_name;
01090 cpl_parameter * p;
01091
01092 int v1;
01093 char * v2;
01094
01095 int pars_counter = 0;
01096
01097 group_name = irplib_sprintf("%s.%s", pipeline_name, recipe_name);
01098 assert(group_name != NULL);
01099
01100 #define insert_par(PARNAME, PARDESC, PARVALUE, PARTYPE) \
01101 do { \
01102 par_name = irplib_sprintf("%s.%s", group_name, PARNAME); \
01103 assert(par_name != NULL); \
01104 p = cpl_parameter_new_value(par_name, PARTYPE, \
01105 PARDESC, group_name, PARVALUE); \
01106 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, PARNAME); \
01107 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV); \
01108 cpl_parameterlist_append(parlist, p); \
01109 cpl_free(par_name); \
01110 } while(0);
01111
01112
01113 va_start(ap, npars);
01114
01115 while(pars_counter < npars) {
01116 char * name = va_arg(ap, char *);
01117 char * desc = va_arg(ap, char *);
01118 char * type = va_arg(ap, char *);
01119
01120 if(!strcmp(type, "CPL_TYPE_INT")) {
01121 v1 = va_arg(ap, int);
01122 insert_par(name, desc, v1, CPL_TYPE_INT);
01123 }
01124 else if(!strcmp(type, "CPL_TYPE_BOOL")) {
01125 v2 = va_arg(ap, char *);
01126 insert_par(name, desc, CPL_FALSE, CPL_TYPE_BOOL);
01127 }
01128
01129 pars_counter++;
01130 }
01131
01132 va_end(ap);
01133
01134 cpl_free(group_name);
01135
01136 #undef insert_par
01137 return 0;
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 static int
01152 irplib_detmon_retrieve_par(const char *parn,
01153 const char *pipeline_name,
01154 const char *recipe_name,
01155 const cpl_parameterlist * parlist)
01156 {
01157 char *par_name;
01158 cpl_parameter *par;
01159 int value;
01160
01161 par_name = irplib_sprintf("%s.%s.%s", pipeline_name, recipe_name, parn);
01162 assert(par_name != NULL);
01163 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01164 value = cpl_parameter_get_int(par);
01165 cpl_free(par_name);
01166
01167 return value;
01168 }
01169
01170 static cpl_error_code
01171 irplib_detmon_retrieve_params(const char *pipeline_name,
01172 const char *recipe_name,
01173 const cpl_parameterlist * parlist)
01174 {
01175
01176 char *par_name;
01177 cpl_parameter *par;
01178
01179
01180 detmon_lg_config.order =
01181 irplib_detmon_retrieve_par("order", pipeline_name, recipe_name,
01182 parlist);
01183
01184
01185 detmon_lg_config.kappa =
01186 irplib_detmon_retrieve_par("kappa", pipeline_name, recipe_name,
01187 parlist);
01188
01189
01190 detmon_lg_config.niter =
01191 irplib_detmon_retrieve_par("niter", pipeline_name, recipe_name,
01192 parlist);
01193
01194
01195 detmon_lg_config.threshold_min =
01196 irplib_detmon_retrieve_par("threshold_min", pipeline_name,
01197 recipe_name, parlist);
01198
01199
01200 detmon_lg_config.threshold_max =
01201 irplib_detmon_retrieve_par("threshold_max", pipeline_name,
01202 recipe_name, parlist);
01203
01204
01205 detmon_lg_config.llx =
01206 irplib_detmon_retrieve_par("llx", pipeline_name, recipe_name,
01207 parlist);
01208
01209
01210 detmon_lg_config.lly =
01211 irplib_detmon_retrieve_par("lly", pipeline_name, recipe_name,
01212 parlist);
01213
01214
01215 detmon_lg_config.urx =
01216 irplib_detmon_retrieve_par("urx", pipeline_name, recipe_name,
01217 parlist);
01218
01219
01220 detmon_lg_config.ury =
01221 irplib_detmon_retrieve_par("ury", pipeline_name, recipe_name,
01222 parlist);
01223
01224
01225 detmon_lg_config.ref_level =
01226 irplib_detmon_retrieve_par("ref_level", pipeline_name, recipe_name,
01227 parlist);
01228
01229
01230 detmon_lg_config.threshold =
01231 irplib_detmon_retrieve_par("threshold", pipeline_name, recipe_name,
01232 parlist);
01233
01234
01235 par_name =
01236 irplib_sprintf("%s.%s.intermediate", pipeline_name, recipe_name);
01237 assert(par_name != NULL);
01238 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01239 detmon_lg_config.intermediate = cpl_parameter_get_bool(par);
01240 cpl_free(par_name);
01241
01242
01243 par_name = irplib_sprintf("%s.%s.autocorr", pipeline_name, recipe_name);
01244 assert(par_name != NULL);
01245 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01246 detmon_lg_config.autocorr = cpl_parameter_get_bool(par);
01247 cpl_free(par_name);
01248
01249
01250 par_name = irplib_sprintf("%s.%s.collapse", pipeline_name, recipe_name);
01251 assert(par_name != NULL);
01252 par = cpl_parameterlist_find((cpl_parameterlist *) parlist, par_name);
01253 detmon_lg_config.collapse = cpl_parameter_get_bool(par);
01254 cpl_free(par_name);
01255
01256
01257 detmon_lg_config.m =
01258 irplib_detmon_retrieve_par("m", pipeline_name, recipe_name, parlist);
01259
01260
01261 detmon_lg_config.n =
01262 irplib_detmon_retrieve_par("n", pipeline_name, recipe_name, parlist);
01263
01264
01265 detmon_lg_config.llx1 =
01266 irplib_detmon_retrieve_par("llx1", pipeline_name, recipe_name,
01267 parlist);
01268
01269
01270 detmon_lg_config.lly1 =
01271 irplib_detmon_retrieve_par("lly1", pipeline_name, recipe_name,
01272 parlist);
01273
01274
01275 detmon_lg_config.urx1 =
01276 irplib_detmon_retrieve_par("urx1", pipeline_name, recipe_name,
01277 parlist);
01278
01279
01280 detmon_lg_config.ury1 =
01281 irplib_detmon_retrieve_par("ury1", pipeline_name, recipe_name,
01282 parlist);
01283
01284
01285 detmon_lg_config.llx2 =
01286 irplib_detmon_retrieve_par("llx2", pipeline_name, recipe_name,
01287 parlist);
01288
01289
01290 detmon_lg_config.lly2 =
01291 irplib_detmon_retrieve_par("lly2", pipeline_name, recipe_name,
01292 parlist);
01293
01294
01295 detmon_lg_config.urx2 =
01296 irplib_detmon_retrieve_par("urx2", pipeline_name, recipe_name,
01297 parlist);
01298
01299
01300 detmon_lg_config.ury2 =
01301 irplib_detmon_retrieve_par("ury2", pipeline_name, recipe_name,
01302 parlist);
01303
01304
01305 detmon_lg_config.llx3 =
01306 irplib_detmon_retrieve_par("llx3", pipeline_name, recipe_name,
01307 parlist);
01308
01309
01310 detmon_lg_config.lly3 =
01311 irplib_detmon_retrieve_par("lly3", pipeline_name, recipe_name,
01312 parlist);
01313
01314
01315 detmon_lg_config.urx3 =
01316 irplib_detmon_retrieve_par("urx3", pipeline_name, recipe_name,
01317 parlist);
01318
01319
01320 detmon_lg_config.ury3 =
01321 irplib_detmon_retrieve_par("ury3", pipeline_name, recipe_name,
01322 parlist);
01323
01324
01325 detmon_lg_config.llx4 =
01326 irplib_detmon_retrieve_par("llx4", pipeline_name, recipe_name,
01327 parlist);
01328
01329
01330 detmon_lg_config.lly4 =
01331 irplib_detmon_retrieve_par("lly4", pipeline_name, recipe_name,
01332 parlist);
01333
01334
01335 detmon_lg_config.urx4 =
01336 irplib_detmon_retrieve_par("urx4", pipeline_name, recipe_name,
01337 parlist);
01338
01339
01340 detmon_lg_config.ury4 =
01341 irplib_detmon_retrieve_par("ury4", pipeline_name, recipe_name,
01342 parlist);
01343
01344
01345 detmon_lg_config.llx5 =
01346 irplib_detmon_retrieve_par("llx5", pipeline_name, recipe_name,
01347 parlist);
01348
01349
01350 detmon_lg_config.lly5 =
01351 irplib_detmon_retrieve_par("lly5", pipeline_name, recipe_name,
01352 parlist);
01353
01354
01355 detmon_lg_config.urx5 =
01356 irplib_detmon_retrieve_par("urx5", pipeline_name, recipe_name,
01357 parlist);
01358
01359
01360 detmon_lg_config.ury5 =
01361 irplib_detmon_retrieve_par("ury5", pipeline_name, recipe_name,
01362 parlist);
01363
01364 if(cpl_error_get_code()) {
01365 cpl_msg_error(cpl_func, "Failed to retrieve the input parameters");
01366 cpl_ensure_code(0, CPL_ERROR_DATA_NOT_FOUND);
01367 }
01368
01369
01370 return CPL_ERROR_NONE;
01371 }
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 static cpl_error_code
01388 irplib_detmon_lg_split_onoff(const cpl_frameset * cur_fset,
01389 cpl_frameset * cur_fset_on,
01390 cpl_frameset * cur_fset_off,
01391 const char *tag_on,
01392 const char *tag_off, const cpl_boolean opt_nir)
01393 {
01394 int nframes;
01395 int i;
01396 cpl_frame *cur_frame;
01397 cpl_frame *cur_frame_dup;
01398 char *tag;
01399
01400 nframes = cpl_frameset_get_size(cur_fset);
01401 for(i = 0; i < nframes; i++) {
01402 if(opt_nir == OPT && i == 0)
01403 i = 2;
01404 cur_frame = cpl_frameset_get_frame(cur_fset, i);
01405
01406
01407 cur_frame_dup = cpl_frame_duplicate(cur_frame);
01408
01409 tag = (char *) cpl_frame_get_tag(cur_frame_dup);
01410
01411
01412 if(!strcmp(tag, tag_on)) {
01413 cpl_error_reset();
01414 cpl_frameset_insert(cur_fset_on, cur_frame_dup);
01415 if(cpl_error_get_code() != CPL_ERROR_NONE) {
01416 cpl_msg_error(cpl_func,
01417 "Cannot insert ON frame nb %d into "
01418 "corresponding sub-frameset", i + 1);
01419 cpl_frame_delete(cur_frame_dup);
01420 cpl_ensure_code(0, cpl_error_get_code());
01421 }
01422 } else if(!strcmp(tag, tag_off)) {
01423 cpl_error_reset();
01424 cpl_frameset_insert(cur_fset_off, cur_frame_dup);
01425 if(cpl_error_get_code() != CPL_ERROR_NONE) {
01426 cpl_msg_error(cpl_func, "Cannot insert OFF frame nb %d into "
01427 "corresponding sub-frameset", i + 1);
01428 cpl_frame_delete(cur_frame_dup);
01429 cpl_ensure_code(0, cpl_error_get_code());
01430 }
01431 } else {
01432 cpl_frame_delete(cur_frame_dup);
01433 }
01434 }
01435
01436 return CPL_ERROR_NONE;
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450 int
01451 irplib_detmon_compare_dits(const cpl_frame * frame1, const cpl_frame * frame2)
01452 {
01453 int comparison;
01454 cpl_propertylist *plist1;
01455 cpl_propertylist *plist2;
01456 double dval1, dval2;
01457
01458
01459 if(frame1 == NULL || frame2 == NULL)
01460 return -1;
01461
01462
01463 if((plist1 = cpl_propertylist_load(cpl_frame_get_filename(frame1),
01464 0)) == NULL) {
01465 cpl_msg_error(cpl_func, "getting header from reference frame");
01466 return -1;
01467 }
01468 if((plist2 = cpl_propertylist_load(cpl_frame_get_filename(frame2),
01469 0)) == NULL) {
01470 cpl_msg_error(cpl_func, "getting header from reference frame");
01471 cpl_propertylist_delete(plist1);
01472 return -1;
01473 }
01474
01475
01476 if(cpl_error_get_code()) {
01477 cpl_propertylist_delete(plist1);
01478 cpl_propertylist_delete(plist2);
01479 return -1;
01480 }
01481
01482
01483 comparison = 1;
01484 dval1 = irplib_pfits_get_exptime(plist1);
01485 dval2 = irplib_pfits_get_exptime(plist2);
01486 if(cpl_error_get_code()) {
01487 cpl_msg_error(cpl_func, "cannot get exposure time");
01488 cpl_propertylist_delete(plist1);
01489 cpl_propertylist_delete(plist2);
01490 return -1;
01491 }
01492 if(fabs(dval1 - dval2) > 1e-3)
01493 comparison = 0;
01494
01495
01496 cpl_propertylist_delete(plist1);
01497 cpl_propertylist_delete(plist2);
01498 return comparison;
01499 }
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517 static cpl_error_code
01518 irplib_detmon_lg_reduce(const cpl_frameset * set_on,
01519 const cpl_frameset * set_off,
01520 const int *selection_on,
01521 const int *selection_off,
01522 const int nsets,
01523 cpl_imagelist ** coeffs_ptr,
01524 cpl_table ** gain_table_ptr,
01525 cpl_table ** linear_table_ptr,
01526 cpl_image ** bpms_ptr,
01527 cpl_propertylist * qclist, const cpl_boolean opt_nir)
01528 {
01529 int i;
01530 cpl_frameset *pair_on = NULL;
01531 cpl_frameset *pair_off = NULL;
01532 cpl_imagelist *ons = NULL;
01533 cpl_imagelist *offs = NULL;
01534 cpl_propertylist *reflist = NULL;
01535 cpl_imagelist *linearity_inputs = NULL;
01536 cpl_table *fit_table = NULL;
01537 cpl_vector *x_pos = NULL;
01538 cpl_image *fiterror = NULL;
01539 cpl_polynomial *poly_fit = NULL;
01540 cpl_vector *x = NULL;
01541 cpl_vector *y = NULL;
01542 double mse;
01543 char *name_o = NULL;
01544 cpl_image *image = NULL;
01545 int nbpixs = 0;
01546
01547 #define clreturn_if(CONDITION, ERR_MSG, ERRCODE) \
01548 do if (cpl_error_get_code() || CONDITION) { \
01549 cpl_msg_error(cpl_func, ERR_MSG); \
01550 if(x) cpl_vector_unwrap(x); \
01551 if(y) cpl_vector_unwrap(y); \
01552 if(pair_on) cpl_frameset_delete(pair_on); \
01553 if(pair_off) cpl_frameset_delete(pair_off); \
01554 if(ons) cpl_imagelist_delete(ons); \
01555 if(offs) cpl_imagelist_delete(offs); \
01556 if(reflist) cpl_propertylist_delete(reflist); \
01557 if(linearity_inputs) cpl_imagelist_delete(linearity_inputs); \
01558 if(fit_table) cpl_table_delete(fit_table); \
01559 if(x_pos) cpl_vector_delete(x_pos); \
01560 if(fiterror) cpl_image_delete(fiterror); \
01561 if(poly_fit) cpl_polynomial_delete(poly_fit); \
01562 if(name_o) cpl_free(name_o); \
01563 if(image) cpl_image_delete(image); \
01564 return ERRCODE; \
01565 } while(0)
01566
01567
01568
01569 cpl_ensure(set_on != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
01570 cpl_ensure(set_off != NULL, CPL_ERROR_NULL_INPUT, CPL_ERROR_NULL_INPUT);
01571
01572
01573 *gain_table_ptr = cpl_table_new(nsets);
01574 cpl_table_new_column(*gain_table_ptr, "DIT", CPL_TYPE_DOUBLE);
01575 cpl_table_new_column(*gain_table_ptr, "EXPTIME", CPL_TYPE_DOUBLE);
01576 cpl_table_new_column(*gain_table_ptr, "MEAN_ON1", CPL_TYPE_DOUBLE);
01577 cpl_table_new_column(*gain_table_ptr, "MEAN_ON2", CPL_TYPE_DOUBLE);
01578 cpl_table_new_column(*gain_table_ptr, "MEAN_OFF1", CPL_TYPE_DOUBLE);
01579 cpl_table_new_column(*gain_table_ptr, "MEAN_OFF2", CPL_TYPE_DOUBLE);
01580 cpl_table_new_column(*gain_table_ptr, "SIG_ON_DIF", CPL_TYPE_DOUBLE);
01581 cpl_table_new_column(*gain_table_ptr, "SIG_OFF_DIF", CPL_TYPE_DOUBLE);
01582 cpl_table_new_column(*gain_table_ptr, "GAIN", CPL_TYPE_DOUBLE);
01583 cpl_table_new_column(*gain_table_ptr, "ADU", CPL_TYPE_DOUBLE);
01584
01585
01586 *linear_table_ptr = cpl_table_new(nsets);
01587 cpl_table_new_column(*linear_table_ptr, "DIT", CPL_TYPE_DOUBLE);
01588 cpl_table_new_column(*linear_table_ptr, "EXPTIME", CPL_TYPE_DOUBLE);
01589 cpl_table_new_column(*linear_table_ptr, "MED", CPL_TYPE_DOUBLE);
01590 cpl_table_new_column(*linear_table_ptr, "MEAN", CPL_TYPE_DOUBLE);
01591 cpl_table_new_column(*linear_table_ptr, "MED_DIT", CPL_TYPE_DOUBLE);
01592 cpl_table_new_column(*linear_table_ptr, "MEAN_DIT", CPL_TYPE_DOUBLE);
01593 cpl_table_new_column(*linear_table_ptr, "ADL", CPL_TYPE_DOUBLE);
01594
01595 fit_table = cpl_table_new(nsets);
01596 cpl_table_new_column(fit_table, "Y", CPL_TYPE_DOUBLE);
01597 cpl_table_new_column(fit_table, "X", CPL_TYPE_DOUBLE);
01598
01599 if(opt_nir == NIR) {
01600 linearity_inputs = cpl_imagelist_new();
01601 x_pos = cpl_vector_new(nsets);
01602 }
01603
01604
01605 for(i = 0; i < nsets; i++) {
01606
01607
01608 clreturn_if((pair_on = cpl_frameset_extract(set_on,
01609 selection_on, i)) == NULL,
01610 "Cannot extract ON pair", cpl_error_get_code());
01611
01612
01613 clreturn_if((ons =
01614 cpl_imagelist_load_frameset(pair_on, CPL_TYPE_FLOAT, 1,
01615 0)) == NULL,
01616 "Cannot load the ON images", cpl_error_get_code());
01617
01618
01619 clreturn_if(cpl_frameset_get_size(pair_on) != 2,
01620 "Some frames are not a pair", CPL_ERROR_ILLEGAL_INPUT);
01621
01622 if(!detmon_lg_config.collapse) {
01623 clreturn_if((pair_off = cpl_frameset_extract(set_off,
01624 selection_off,
01625 i)) == NULL,
01626 "Cannot extract OFF pair", cpl_error_get_code());
01627 clreturn_if(cpl_frameset_get_size(pair_off) != 2,
01628 "Some frames are not a pair", CPL_ERROR_ILLEGAL_INPUT);
01629 clreturn_if((offs =
01630 cpl_imagelist_load_frameset(pair_off, CPL_TYPE_FLOAT, 1,
01631 0)) == NULL,
01632 "Cannot load the OFF images", cpl_error_get_code());
01633 }
01634
01635
01636 cpl_msg_info(cpl_func,
01637 "Producing image nb %d required for polynomial fit",
01638 i + 1);
01639
01640 if(!detmon_lg_config.collapse)
01641 irplib_detmon_linearity(pair_on, linear_table_ptr, gain_table_ptr,
01642 &linearity_inputs, &x_pos, ons, offs, i,
01643 nsets, qclist, opt_nir);
01644 else {
01645
01646
01647
01648
01649 cpl_imagelist * masterl =
01650 cpl_imagelist_load_frameset(set_off, CPL_TYPE_FLOAT, 1, 0);
01651 cpl_image * collapse = cpl_imagelist_collapse_create(masterl);
01652
01653
01654 cpl_imagelist_set(masterl, collapse, 0);
01655
01656 irplib_detmon_linearity(pair_on, linear_table_ptr, gain_table_ptr,
01657 &linearity_inputs, &x_pos, ons, masterl, i,
01658 nsets, qclist, opt_nir);
01659
01660 cpl_imagelist_delete(masterl);
01661 }
01662
01663 clreturn_if(0, "Cannot reduce linearity part", cpl_error_get_code());
01664
01665
01666 cpl_msg_info(cpl_func, "Computing GAIN for DIT value nb %d", i + 1);
01667 if(!detmon_lg_config.collapse)
01668 irplib_detmon_gain(gain_table_ptr, &fit_table, ons, offs, i);
01669 else {
01670 cpl_frame * first = cpl_frameset_get_first(set_off);
01671 cpl_frame * dup_first = cpl_frame_duplicate(first);
01672
01673 cpl_frame * second = cpl_frameset_get_next(set_off);
01674 cpl_frame * dup_second = cpl_frame_duplicate(second);
01675
01676 cpl_frameset * raw_offs = cpl_frameset_new();
01677
01678 cpl_imagelist * opt_offs;
01679
01680 cpl_frameset_insert(raw_offs, dup_first);
01681 cpl_frameset_insert(raw_offs, dup_second);
01682
01683 opt_offs =
01684 cpl_imagelist_load_frameset(raw_offs, CPL_TYPE_FLOAT, 1, 0);
01685 irplib_detmon_gain(gain_table_ptr, &fit_table, ons, opt_offs, i);
01686 cpl_frameset_delete(raw_offs);
01687 cpl_imagelist_delete(opt_offs);
01688
01689 }
01690 clreturn_if(0, "Cannot reduce gain part", cpl_error_get_code());
01691
01692 cpl_frameset_delete(pair_on);
01693 cpl_imagelist_delete(ons);
01694
01695 if(!detmon_lg_config.collapse) {
01696 cpl_frameset_delete(pair_off);
01697 cpl_imagelist_delete(offs);
01698 }
01699 }
01700
01701 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE >= CPL_VERSION(3, 1, 90)
01702
01703 cpl_msg_info(cpl_func, "Polynomial fitting pix-to-pix");
01704
01705 if(opt_nir == OPT) {
01706
01707 cpl_msg_info(cpl_func, "Polynomial fitting for the LINEARITY");
01708
01709 x = cpl_vector_wrap(nsets,
01710 cpl_table_get_data_double(*linear_table_ptr,
01711 "MED"));
01712 y = cpl_vector_wrap(nsets,
01713 cpl_table_get_data_double(*linear_table_ptr,
01714 "DIT"));
01715 clreturn_if(x == NULL
01716 || y == NULL, "Cannot read LINEAR table",
01717 cpl_error_get_code());
01718 clreturn_if((poly_fit =
01719 cpl_polynomial_fit_1d_create(x, y,
01720 detmon_lg_config.order,
01721 &mse)) == NULL,
01722 "Cannot fit to a linear", cpl_error_get_code());
01723
01724 for(i = 1; i <= detmon_lg_config.order; i++) {
01725 const double coeff = cpl_polynomial_get_coeff(poly_fit, &i);
01726 name_o = irplib_sprintf("ESO QC LIN COEF%d", i);
01727 assert(name_o != NULL);
01728 cpl_propertylist_append_double(qclist, name_o, coeff);
01729 cpl_free(name_o);
01730 }
01731
01732 cpl_vector_unwrap(x);
01733 cpl_vector_unwrap(y);
01734 cpl_polynomial_delete(poly_fit);
01735
01736 } else {
01737 clreturn_if((*coeffs_ptr =
01738 cpl_fit_imagelist_polynomial(x_pos, linearity_inputs, 0,
01739 detmon_lg_config.order,
01740 FALSE, CPL_TYPE_FLOAT,
01741 fiterror)) == NULL,
01742 "Cannot compute the polynomial image fit",
01743 cpl_error_get_code());
01744
01745 for(i = 0; i < detmon_lg_config.order; i++) {
01746 image = cpl_imagelist_get(*coeffs_ptr, i);
01747 name_o = irplib_sprintf("ESO QC LIN COEF%d", i);
01748 assert(name_o != NULL);
01749 cpl_propertylist_append_double(qclist, name_o,
01750 cpl_image_get_median(image));
01751 cpl_free(name_o);
01752 name_o = irplib_sprintf("ESO QC LIN COEF%d ERR", i);
01753 assert(name_o != NULL);
01754 cpl_propertylist_append_double(qclist, name_o,
01755 cpl_image_get_stdev(image));
01756 cpl_free(name_o);
01757 }
01758 }
01759 #else
01760 cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
01761 #endif
01762
01763 cpl_msg_info(cpl_func, "Bad pixel detection");
01764 if(opt_nir == NIR)
01765 clreturn_if((*bpms_ptr =
01766 irplib_detmon_bpixs(*coeffs_ptr, &nbpixs)) == NULL,
01767 "Cannot detect bad pixels", CPL_ERROR_DATA_NOT_FOUND);
01768
01769
01770 cpl_msg_info(cpl_func,
01771 "Polynomial fitting for the GAIN (constant term method)");
01772
01773 x = cpl_vector_wrap(nsets, cpl_table_get_data_double(fit_table, "X"));
01774 y = cpl_vector_wrap(nsets, cpl_table_get_data_double(fit_table, "Y"));
01775 clreturn_if(x == NULL || y == NULL, "Cannot read FIT table",
01776 cpl_error_get_code());
01777
01778 clreturn_if((poly_fit =
01779 cpl_polynomial_fit_1d_create(x, y, 1, &mse)) == NULL,
01780 "Cannot fit to a linear", cpl_error_get_code());
01781
01782 cpl_propertylist_append_double(qclist, "ESO QC LAMP FLUX",
01783 detmon_lg_config.cr);
01784
01785 cpl_propertylist_append_double(qclist, "ESO QC GAIN MED",
01786 cpl_table_get_column_median
01787 (*gain_table_ptr, "GAIN"));
01788 cpl_propertylist_append_double(qclist, "ESO QC GAIN STD",
01789 cpl_table_get_column_stdev(*gain_table_ptr,
01790 "GAIN"));
01791 i = 1;
01792 cpl_propertylist_append_double(qclist, "ESO QC CONAD FIT",
01793 cpl_polynomial_get_coeff(poly_fit, &i));
01794
01795 i = 1;
01796 cpl_propertylist_append_double(qclist, "ESO QC GAIN FIT",
01797 1 / cpl_polynomial_get_coeff(poly_fit,
01798 &i));
01799
01800 i = 0;
01801 cpl_propertylist_append_double(qclist, "ESO QC READNOISE",
01802 cpl_polynomial_get_coeff(poly_fit, &i));
01803
01804 cpl_propertylist_append_double(qclist, "ESO QC NUM BPM", nbpixs);
01805
01806 if(linearity_inputs)
01807 cpl_imagelist_delete(linearity_inputs);
01808 if(x_pos)
01809 cpl_vector_delete(x_pos);
01810 if(fiterror)
01811 cpl_image_delete(fiterror);
01812 if(x)
01813 cpl_vector_unwrap(x);
01814 if(y)
01815 cpl_vector_unwrap(y);
01816 if(fit_table)
01817 cpl_table_delete(fit_table);
01818 cpl_polynomial_delete(poly_fit);
01819
01820 reflist = cpl_propertylist_new();
01821 cpl_propertylist_append_bool(reflist, "ADU", FALSE);
01822
01823 cpl_table_sort(*gain_table_ptr, reflist);
01824
01825 clreturn_if(0, "Cannot sort the GAIN table", cpl_error_get_code());
01826
01827 cpl_propertylist_delete(reflist);
01828
01829 #undef clreturn_if
01830
01831 return CPL_ERROR_NONE;
01832 }
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869 double
01870 irplib_pfits_get_exptime(const cpl_propertylist * plist)
01871 {
01872 double exptime;
01873
01874 exptime = cpl_propertylist_get_double(plist, "EXPTIME");
01875
01876 return exptime;
01877 }
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897 static cpl_error_code
01898 irplib_detmon_linearity(const cpl_frameset * pair,
01899 cpl_table ** linear_table_ptr,
01900 cpl_table ** gain_table_ptr,
01901 cpl_imagelist ** linearity_inputs_ptr,
01902 cpl_vector ** x_pos_ptr,
01903 const cpl_imagelist * ons,
01904 const cpl_imagelist * offs,
01905 const int pos,
01906 const int nsets,
01907 cpl_propertylist * qclist, const cpl_boolean opt_nir)
01908 {
01909 const char *filename;
01910 cpl_propertylist *plist;
01911 cpl_image *dif1;
01912 cpl_image *dif2;
01913 cpl_image *dif_avg;
01914 double med_dit;
01915 double mean_dit;
01916 double exptime, dit;
01917
01918
01919 filename = cpl_frame_get_filename(cpl_frameset_get_first(pair));
01920 if((plist = cpl_propertylist_load(filename, 0)) == NULL) {
01921 cpl_msg_error(cpl_func, "getting header from reference frame");
01922 cpl_ensure_code(0, cpl_error_get_code());
01923 }
01924
01925 dit = irplib_pfits_get_exptime(plist);
01926 exptime = irplib_pfits_get_exptime(plist);
01927
01928 cpl_table_set(*linear_table_ptr, "DIT", pos, dit);
01929 cpl_table_set(*gain_table_ptr, "DIT", pos, dit);
01930
01931 cpl_table_set(*linear_table_ptr, "EXPTIME", pos, exptime);
01932 cpl_table_set(*gain_table_ptr, "EXPTIME", pos, exptime);
01933
01934
01935 dif1 = cpl_image_subtract_create(cpl_imagelist_get(ons, 0),
01936 cpl_imagelist_get(offs, 0));
01937 if(!detmon_lg_config.collapse)
01938 dif2 = cpl_image_subtract_create(cpl_imagelist_get(ons, 1),
01939 cpl_imagelist_get(offs, 1));
01940 else
01941 dif2 = cpl_image_subtract_create(cpl_imagelist_get(ons, 1),
01942 cpl_imagelist_get(offs, 0));
01943
01944 dif_avg = cpl_image_average_create(dif1, dif2);
01945
01946 if(opt_nir == OPT && pos == nsets / 2) {
01947 irplib_detmon_opt_contamination(dif_avg, qclist);
01948 }
01949
01950 cpl_table_set(*linear_table_ptr, "MED", pos,
01951 cpl_image_get_median(dif_avg));
01952 cpl_table_set(*linear_table_ptr, "MEAN", pos,
01953 cpl_image_get_mean(dif_avg));
01954
01955 med_dit = cpl_image_get_median(dif_avg) / irplib_pfits_get_exptime(plist);
01956 mean_dit = cpl_image_get_mean(dif_avg) / irplib_pfits_get_exptime(plist);
01957
01958 cpl_table_set(*linear_table_ptr, "MED_DIT", pos, med_dit);
01959 cpl_table_set(*linear_table_ptr, "MEAN_DIT", pos, mean_dit);
01960
01961
01962 if(pos == 0)
01963 detmon_lg_config.cr = cpl_image_get_mean(dif_avg) / dit;
01964
01965 cpl_image_delete(dif1);
01966 cpl_image_delete(dif2);
01967 cpl_propertylist_delete(plist);
01968
01969
01970 if(opt_nir == NIR) {
01971 cpl_imagelist_set(*linearity_inputs_ptr, dif_avg, pos);
01972 cpl_vector_set(*x_pos_ptr, pos, dit);
01973 } else {
01974 cpl_image_delete(dif_avg);
01975 }
01976
01977 return CPL_ERROR_NONE;
01978 }
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994 static cpl_error_code
01995 irplib_detmon_gain(cpl_table ** gain_table_ptr,
01996 cpl_table ** fit_table_ptr,
01997 const cpl_imagelist * ons,
01998 const cpl_imagelist * offs, const int pos)
01999 {
02000 cpl_image *image;
02001 double std;
02002 cpl_image *on_dif;
02003 cpl_image *off_dif;
02004 double avg_on1, avg_on2;
02005 double avg_off1, avg_off2;
02006 double avg_on_dif, sig_on_dif;
02007 double avg_off_dif, sig_off_dif;
02008 double double_adu, autocorr, gain;
02009 double sigma_corr;
02010 cpl_propertylist *plist;
02011
02012 std = 0;
02013
02014 if((image = cpl_imagelist_get(ons, 0)) == NULL) {
02015 cpl_ensure_code(0, cpl_error_get_code());
02016 }
02017 irplib_get_clean_mean_window(image,
02018 detmon_lg_config.llx,
02019 detmon_lg_config.lly,
02020 detmon_lg_config.urx,
02021 detmon_lg_config.ury,
02022 detmon_lg_config.kappa,
02023 detmon_lg_config.niter, &avg_on1, &std);
02024 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02025 cpl_error_get_code());
02026 cpl_table_set_double(*gain_table_ptr, "MEAN_ON1", pos, avg_on1);
02027
02028 if((image = cpl_imagelist_get(ons, 1)) == NULL) {
02029 cpl_ensure_code(0, cpl_error_get_code());
02030 }
02031 irplib_get_clean_mean_window(image,
02032 detmon_lg_config.llx,
02033 detmon_lg_config.lly,
02034 detmon_lg_config.urx,
02035 detmon_lg_config.ury,
02036 detmon_lg_config.kappa,
02037 detmon_lg_config.niter, &avg_on2, &std);
02038 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02039 cpl_error_get_code());
02040 cpl_table_set_double(*gain_table_ptr, "MEAN_ON2", pos, avg_on2);
02041
02042 on_dif =
02043 cpl_image_subtract_create(cpl_imagelist_get(ons, 0),
02044 cpl_imagelist_get(ons, 1));
02045 irplib_get_clean_mean_window(on_dif, detmon_lg_config.llx,
02046 detmon_lg_config.lly,
02047 detmon_lg_config.urx,
02048 detmon_lg_config.ury,
02049 detmon_lg_config.kappa,
02050 detmon_lg_config.niter, &avg_on_dif,
02051 &sig_on_dif);
02052 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02053 cpl_error_get_code());
02054 cpl_table_set_double(*gain_table_ptr, "SIG_ON_DIF", pos, sig_on_dif);
02055 cpl_msg_info(cpl_func, "Computing autocorr factor for DIT value nb %d ",
02056 pos);
02057 autocorr = irplib_detmon_autocorr_factor(on_dif, pos);
02058
02059 if(detmon_lg_config.intermediate) {
02060 char * frame_name = irplib_sprintf("dif%d.fits", pos);
02061 plist = cpl_propertylist_new();
02062 cpl_propertylist_append_double(plist, "ESO DET DIT", 3);
02063 cpl_propertylist_append_double(plist, "EXPTIME", 3);
02064 cpl_image_save(on_dif, frame_name, CPL_BPP_IEEE_FLOAT, plist,
02065 CPL_IO_DEFAULT);
02066 cpl_propertylist_delete(plist);
02067 cpl_free(frame_name);
02068 }
02069
02070 cpl_image_delete(on_dif);
02071
02072 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02073 cpl_error_get_code());
02074
02075 irplib_get_clean_mean_window(cpl_imagelist_get(offs, 0),
02076 detmon_lg_config.llx,
02077 detmon_lg_config.lly,
02078 detmon_lg_config.urx,
02079 detmon_lg_config.ury,
02080 detmon_lg_config.kappa,
02081 detmon_lg_config.niter, &avg_off1, &std);
02082 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02083 cpl_error_get_code());
02084 cpl_table_set_double(*gain_table_ptr, "MEAN_OFF1", pos, avg_off1);
02085 irplib_get_clean_mean_window(cpl_imagelist_get(offs, 1),
02086 detmon_lg_config.llx,
02087 detmon_lg_config.lly,
02088 detmon_lg_config.urx,
02089 detmon_lg_config.ury,
02090 detmon_lg_config.kappa,
02091 detmon_lg_config.niter, &avg_off2, &std);
02092 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02093 cpl_error_get_code());
02094 cpl_table_set_double(*gain_table_ptr, "MEAN_OFF2", pos, avg_off2);
02095
02096 off_dif =
02097 cpl_image_subtract_create(cpl_imagelist_get(offs, 0),
02098 cpl_imagelist_get(offs, 1));
02099 irplib_get_clean_mean_window(off_dif, detmon_lg_config.llx,
02100 detmon_lg_config.lly,
02101 detmon_lg_config.urx,
02102 detmon_lg_config.ury,
02103 detmon_lg_config.kappa,
02104 detmon_lg_config.niter, &avg_off_dif,
02105 &sig_off_dif);
02106 cpl_ensure_code(cpl_error_get_code() == CPL_ERROR_NONE,
02107 cpl_error_get_code());
02108 cpl_table_set_double(*gain_table_ptr, "SIG_OFF_DIF", pos, sig_off_dif);
02109
02110 cpl_image_delete(off_dif);
02111
02112 double_adu = (avg_on1 + avg_on2) - (avg_off1 + avg_off2);
02113
02114 sigma_corr = autocorr *
02115 ((sig_on_dif * sig_on_dif) - (sig_off_dif * sig_off_dif));
02116
02117 gain = double_adu / sigma_corr;
02118
02119 if(cpl_table_set_double(*gain_table_ptr, "GAIN", pos, gain)) {
02120 cpl_ensure_code(0, cpl_error_get_code());
02121 }
02122 if(cpl_table_set_double(*gain_table_ptr, "ADU", pos, double_adu / 2)) {
02123 cpl_ensure_code(0, cpl_error_get_code());
02124 }
02125
02126
02127
02128
02129 if(cpl_table_set_double
02130 (*fit_table_ptr, "Y", pos, sig_on_dif * sig_on_dif)) {
02131 cpl_ensure_code(0, cpl_error_get_code());
02132 }
02133 if(cpl_table_set_double(*fit_table_ptr, "X", pos, double_adu / autocorr)) {
02134 cpl_ensure_code(0, cpl_error_get_code());
02135 }
02136 return CPL_ERROR_NONE;
02137 }
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150 static cpl_image *
02151 irplib_detmon_bpixs(const cpl_imagelist * coeffs, int *nbpixs)
02152 {
02153 int size;
02154 int i;
02155 cpl_image *cur_coeff;
02156 cpl_stats *stats;
02157 double cur_mean;
02158 double cur_stdev;
02159 double lo_cut;
02160 double hi_cut;
02161 cpl_mask *cur_mask;
02162 cpl_image *cur_image;
02163 cpl_image *bpm = NULL;
02164 double p;
02165
02166 size = cpl_imagelist_get_size(coeffs);
02167
02168 for(i = 0; i < size; i++) {
02169 cur_coeff = cpl_imagelist_get(coeffs, i);
02170 if(!i) {
02171 bpm = cpl_image_new(cpl_image_get_size_x(cur_coeff),
02172 cpl_image_get_size_y(cur_coeff),
02173 CPL_TYPE_INT);
02174 }
02175 stats = cpl_stats_new_from_image(cur_coeff,
02176 CPL_STATS_MEAN | CPL_STATS_STDEV);
02177 cur_mean = cpl_stats_get_mean(stats);
02178 cur_stdev = cpl_stats_get_stdev(stats);
02179
02180 lo_cut = cur_mean - detmon_lg_config.kappa * cur_stdev;
02181 hi_cut = cur_mean + detmon_lg_config.kappa * cur_stdev;
02182
02183 cur_mask = cpl_mask_threshold_image_create(cur_coeff, lo_cut, hi_cut);
02184 cpl_mask_not(cur_mask);
02185
02186 *nbpixs += cpl_mask_count(cur_mask);
02187
02188 cur_image = cpl_image_new_from_mask(cur_mask);
02189 p = pow(2, i);
02190 cpl_image_power(cur_image, p);
02191 cpl_image_add(bpm, cur_image);
02192
02193 cpl_mask_delete(cur_mask);
02194 cpl_image_delete(cur_image);
02195 cpl_stats_delete(stats);
02196 }
02197
02198 return bpm;
02199 }
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213 static double
02214 irplib_detmon_autocorr_factor(const cpl_image * image, const int pos)
02215 {
02216
02217 cpl_image *autocorr_image;
02218 double autocorr;
02219 cpl_propertylist *plist;
02220
02221 #ifdef HAVE_FFTW
02222 if(detmon_lg_config.autocorr) {
02223 cpl_msg_info(cpl_func, "Autocorr via FFTW");
02224
02225 autocorr_image =
02226 irplib_detmon_image_correlate(image, image, detmon_lg_config.m,
02227 detmon_lg_config.m);
02228 if(autocorr_image == NULL) {
02229 return -1;
02230 }
02231 } else {
02232 cpl_msg_info(cpl_func, "Autocorr deactivated by user");
02233 autocorr = 1.0;
02234 return autocorr;
02235 }
02236 #else
02237 if(detmon_lg_config.autocorr) {
02238 cpl_msg_info(cpl_func, "Autocorr via cpl_image_fft()");
02239 autocorr_image =
02240 irplib_detmon_autocorrelate(image, detmon_lg_config.m,
02241 detmon_lg_config.m);
02242 if(autocorr_image == NULL) {
02243 return -1;
02244 }
02245 } else {
02246 cpl_msg_info(cpl_func, "Autocorr deactivated by user");
02247 autocorr = 1.0;
02248 return autocorr;
02249 }
02250 #endif
02251
02252 autocorr = cpl_image_get_flux(autocorr_image);
02253
02254 if(detmon_lg_config.intermediate) {
02255 char * frame_name = irplib_sprintf("corr%d.fits", pos);
02256 plist = cpl_propertylist_new();
02257 cpl_propertylist_append_double(plist, "ESO DET DIT", 3);
02258 cpl_propertylist_append_double(plist, "EXPTIME", 3);
02259 cpl_image_save(autocorr_image, frame_name, CPL_BPP_IEEE_FLOAT, plist,
02260 CPL_IO_DEFAULT);
02261 cpl_propertylist_delete(plist);
02262 cpl_free(frame_name);
02263 }
02264
02265 cpl_image_delete(autocorr_image);
02266
02267 return autocorr;
02268 }
02269
02284 static int
02285 irplib_get_clean_mean_window(cpl_image * img,
02286 const int llx,
02287 const int lly,
02288 const int urx, int ury,
02289 const int kappa,
02290 const int nclip,
02291 double *clean_mean, double *clean_stdev)
02292 {
02293
02294
02295 double mean = 0;
02296 double stdev = 0;
02297 double threshold = 0;
02298 double lo_cut = 0;
02299 double hi_cut = 0;
02300 double lo_cut_p = 0;
02301 double hi_cut_p = 0;
02302
02303 cpl_mask *mask = NULL;
02304 cpl_image *tmp = NULL;
02305 cpl_stats *stats = NULL;
02306 int i = 0;
02307
02308 if((tmp = cpl_image_extract(img, llx, lly, urx, ury)) == NULL) {
02309 cpl_msg_error(cpl_func, "Error extracting window");
02310 return -1;
02311 }
02312 cpl_image_accept_all(tmp);
02313 for(i = 0; i < nclip; i++) {
02314
02315
02316 cpl_stats_delete(stats);
02317 stats =
02318 cpl_stats_new_from_image(tmp, CPL_STATS_MEAN | CPL_STATS_STDEV);
02319 mean = cpl_stats_get_mean(stats);
02320 stdev = cpl_stats_get_stdev(stats);
02321
02322 threshold = kappa * stdev;
02323 lo_cut = mean - threshold;
02324 hi_cut = mean + threshold;
02325
02326 cpl_image_accept_all(tmp);
02327 mask = cpl_mask_threshold_image_create(tmp, lo_cut, hi_cut);
02328
02329 cpl_mask_not(mask);
02330 cpl_image_reject_from_mask(tmp, mask);
02331 cpl_mask_delete(mask);
02332 if(lo_cut_p == lo_cut && hi_cut_p == hi_cut)
02333 break;
02334 else {
02335 lo_cut_p = lo_cut;
02336 hi_cut_p = hi_cut;
02337 }
02338
02339 }
02340 *clean_mean = mean;
02341 *clean_stdev = stdev;
02342 cpl_image_delete(tmp);
02343 cpl_stats_delete(stats);
02344
02345 return 0;
02346
02347
02348 }
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358 static cpl_error_code
02359 irplib_detmon_lg_save(const cpl_parameterlist * parlist,
02360 cpl_frameset * frameset,
02361 const char *recipe_name,
02362 const char *pipeline_name,
02363 const char *procatg_lintbl,
02364 const char *procatg_gaintbl,
02365 const char *procatg_lincoeff,
02366 const char *procatg_bpm,
02367 const char *package,
02368 const cpl_imagelist * coeffs,
02369 const cpl_table * gain_table,
02370 const cpl_table * linear_table,
02371 const cpl_image * bpms,
02372 cpl_propertylist * qclist,
02373 const int flag_sets,
02374 const int which_set,
02375 cpl_frameset * usedframes, cpl_boolean opt_nir)
02376 {
02377
02378 cpl_frame *ref_frame;
02379 cpl_propertylist *plist;
02380 char *name_o;
02381 char *name_coeff;
02382
02383
02384 int nb_images;
02385 int i;
02386 cpl_propertylist *paflist;
02387
02388
02389
02390
02391
02392
02393 if(!flag_sets) {
02394 name_o = irplib_sprintf("%s_gain_table.fits", recipe_name);
02395 assert(name_o != NULL);
02396 } else {
02397 name_o =
02398 irplib_sprintf("%s_gain_table_set%02d.fits", recipe_name,
02399 which_set);
02400 assert(name_o != NULL);
02401 }
02402
02403
02404 if(irplib_table_save(frameset, parlist, usedframes, gain_table,
02405 NULL, recipe_name, procatg_gaintbl, qclist, NULL,
02406 package, name_o)) {
02407 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
02408 cpl_free(name_o);
02409 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
02410 }
02411
02412
02413 cpl_free(name_o);
02414
02415
02416
02417
02418
02419
02420 if(!flag_sets) {
02421 name_o = irplib_sprintf("%s_linearity_table.fits", recipe_name);
02422 assert(name_o != NULL);
02423 } else {
02424 name_o =
02425 irplib_sprintf("%s_linearity_table_set%02d.fits", recipe_name,
02426 which_set);
02427 assert(name_o != NULL);
02428 }
02429
02430
02431 if(irplib_table_save(frameset, parlist, usedframes, linear_table,
02432 NULL, recipe_name, procatg_lintbl, qclist, NULL,
02433 package, name_o)) {
02434 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
02435 cpl_free(name_o);
02436 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
02437 }
02438
02439
02440 cpl_free(name_o);
02441
02442 if(opt_nir == NIR) {
02443
02444
02445
02446
02447
02448 nb_images = cpl_imagelist_get_size(coeffs);
02449
02450 for(i = 0; i < nb_images; i++) {
02451
02452 if(!flag_sets) {
02453 name_o =
02454 irplib_sprintf("%s_lin_coeff_%d.fits", recipe_name, i);
02455 assert(name_o != NULL);
02456 } else {
02457 name_o =
02458 irplib_sprintf("%s_lin_coeff_%d_set%02d.fits",
02459 recipe_name, i, which_set);
02460 assert(name_o != NULL);
02461 }
02462
02463 name_coeff = irplib_sprintf("%s_%d", procatg_lincoeff, i);
02464 assert(name_coeff != NULL);
02465
02466
02467 if(irplib_image_save(frameset, parlist, usedframes,
02468 cpl_imagelist_get(coeffs, i),
02469 CPL_BPP_IEEE_FLOAT, recipe_name, name_coeff,
02470 qclist, NULL, package, name_o)) {
02471 cpl_msg_error(cpl_func, "Could not save product");
02472 cpl_free(name_o);
02473 cpl_free(name_coeff);
02474 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
02475 }
02476
02477
02478 cpl_free(name_o);
02479 cpl_free(name_coeff);
02480 }
02481
02482
02483
02484
02485
02486
02487 if(!flag_sets) {
02488 name_o = irplib_sprintf("%s_bpm.fits", recipe_name);
02489 assert(name_o != NULL);
02490 } else {
02491 name_o =
02492 irplib_sprintf("%s_bpm_set%02d.fits", recipe_name, which_set);
02493 assert(name_o != NULL);
02494 }
02495
02496
02497 if(irplib_image_save(frameset, parlist, usedframes, bpms,
02498 CPL_BPP_IEEE_FLOAT, recipe_name, procatg_bpm,
02499 qclist, NULL, package, name_o)) {
02500 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
02501 cpl_free(name_o);
02502 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
02503 }
02504
02505
02506 cpl_free(name_o);
02507
02508 }
02509
02510
02511
02512
02513
02514
02515 ref_frame = cpl_frameset_get_first(frameset);
02516 if((plist = cpl_propertylist_load(cpl_frame_get_filename(ref_frame),
02517 0)) == NULL) {
02518 cpl_msg_error(cpl_func, "getting header from reference frame");
02519 cpl_ensure_code(0, cpl_error_get_code());
02520 }
02521
02522
02523 paflist = cpl_propertylist_new();
02524 cpl_propertylist_copy_property_regexp(paflist, plist,
02525 "^(ARCFILE|MJD-OBS|ESO TPL ID|"
02526 "DATE-OBS|ESO DET DIT|ESO DET NDIT|"
02527 "ESO DET NCORRS|"
02528 "ESO DET MODE NAME)$", 0);
02529
02530 cpl_propertylist_append(paflist, qclist);
02531
02532
02533 if(!flag_sets) {
02534 name_o = irplib_sprintf("%s.paf", recipe_name);
02535 assert(name_o != NULL);
02536 } else {
02537 name_o = irplib_sprintf("%s_set%02d.paf", recipe_name, which_set);
02538 assert(name_o != NULL);
02539 }
02540
02541
02542 if(irplib_paf_save(pipeline_name, recipe_name, paflist, name_o)) {
02543 cpl_msg_error(cpl_func, "Cannot save the product: %s", name_o);
02544 cpl_free(name_o);
02545 cpl_propertylist_delete(paflist);
02546 cpl_propertylist_delete(plist);
02547 cpl_free(name_o);
02548 cpl_ensure_code(0, CPL_ERROR_FILE_NOT_CREATED);
02549 }
02550
02551 cpl_propertylist_delete(plist);
02552 cpl_propertylist_delete(paflist);
02553 cpl_free(name_o);
02554
02555 return CPL_ERROR_NONE;
02556 }
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567 static cpl_error_code
02568 irplib_detmon_opt_contamination(const cpl_image * reduced,
02569 cpl_propertylist * qclist)
02570 {
02571 double flux[5];
02572
02573 flux[0] = cpl_image_get_flux_window(reduced,
02574 detmon_lg_config.llx1,
02575 detmon_lg_config.lly1,
02576 detmon_lg_config.urx1,
02577 detmon_lg_config.ury1);
02578
02579 flux[1] = cpl_image_get_flux_window(reduced,
02580 detmon_lg_config.llx2,
02581 detmon_lg_config.lly2,
02582 detmon_lg_config.urx2,
02583 detmon_lg_config.ury2);
02584 cpl_propertylist_append_double(qclist, "ESO QC CONTAM2",
02585 flux[1] / flux[0]);
02586
02587 flux[2] = cpl_image_get_flux_window(reduced,
02588 detmon_lg_config.llx3,
02589 detmon_lg_config.lly3,
02590 detmon_lg_config.urx3,
02591 detmon_lg_config.ury3);
02592 cpl_propertylist_append_double(qclist, "ESO QC CONTAM3",
02593 flux[2] / flux[0]);
02594
02595 flux[3] = cpl_image_get_flux_window(reduced,
02596 detmon_lg_config.llx4,
02597 detmon_lg_config.lly4,
02598 detmon_lg_config.urx4,
02599 detmon_lg_config.ury4);
02600 cpl_propertylist_append_double(qclist, "ESO QC CONTAM4",
02601 flux[3] / flux[0]);
02602
02603 flux[4] = cpl_image_get_flux_window(reduced,
02604 detmon_lg_config.llx5,
02605 detmon_lg_config.lly5,
02606 detmon_lg_config.urx5,
02607 detmon_lg_config.ury5);
02608 cpl_propertylist_append_double(qclist, "ESO QC CONTAM5",
02609 flux[4] / flux[0]);
02610
02611 return CPL_ERROR_NONE;
02612 }
02613
02614 static int
02615 irplib_detmon_opt_lampcr(cpl_frameset * cur_fset)
02616 {
02617 cpl_image *on;
02618 cpl_image *off;
02619 cpl_frame *first_off;
02620 cpl_frame *first_on;
02621 cpl_propertylist *plist;
02622 double dit;
02623
02624 if((first_off = cpl_frameset_get_first(cur_fset)) == NULL) {
02625 cpl_ensure_code(0, cpl_error_get_code());
02626 }
02627 if((first_on = cpl_frameset_get_next(cur_fset)) == NULL) {
02628 cpl_ensure_code(0, cpl_error_get_code());
02629 }
02630
02631 on = cpl_image_load(cpl_frame_get_filename(first_on),
02632 CPL_TYPE_FLOAT, 0, 0);
02633 off = cpl_image_load(cpl_frame_get_filename(first_off),
02634 CPL_TYPE_FLOAT, 0, 0);
02635 cpl_image_subtract(on, off);
02636
02637 plist = cpl_propertylist_load(cpl_frame_get_filename(first_on), 0);
02638 if(plist == NULL) {
02639 cpl_msg_error(cpl_func, "getting header from reference frame");
02640 cpl_image_delete(on);
02641 cpl_image_delete(off);
02642 cpl_ensure_code(0, cpl_error_get_code());
02643 }
02644
02645 dit = irplib_pfits_get_exptime(plist);
02646
02647 detmon_lg_config.cr = cpl_image_get_mean(on) / dit;
02648
02649 cpl_image_delete(on);
02650 cpl_image_delete(off);
02651 cpl_propertylist_delete(plist);
02652
02653 return 0;
02654 }
02655
02656 int
02657 irplib_detmon_dfs_set_groups(cpl_frameset * set,
02658 const char *tag_on, const char *tag_off)
02659 {
02660 cpl_frame *cur_frame;
02661 const char *tag;
02662 int nframes;
02663 int i;
02664
02665
02666 if(set == NULL)
02667 return -1;
02668
02669
02670 nframes = cpl_frameset_get_size(set);
02671
02672
02673 for(i = 0; i < nframes; i++) {
02674 cur_frame = cpl_frameset_get_frame(set, i);
02675 tag = cpl_frame_get_tag(cur_frame);
02676
02677
02678 if(!strcmp(tag, tag_on) || !strcmp(tag, tag_off))
02679 cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
02680
02681
02682
02683
02684
02685 }
02686 return 0;
02687 }