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 #include <string.h>
00037 #include <math.h>
00038 #include <float.h>
00039 #include <assert.h>
00040
00041 #include <cpl.h>
00042
00043 #include "visir_utils.h"
00044 #include "visir_pfits.h"
00045 #include "visir_parameter.h"
00046 #include "visir_pfits.h"
00047 #include "visir_spc_distortion.h"
00048 #include "visir_inputs.h"
00049 #include "irplib_framelist.h"
00050
00051
00052
00053
00054
00055
00056 #define VISIR_HCYCLE_BPM_THRESHOLD 65000.0
00057
00058 #ifndef VISIR_DESTRIPE_DETECT
00059 #define VISIR_DESTRIPE_DETECT (3.5 * 1.64)
00060 #endif
00061
00062 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00063 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00064 #endif
00065
00066
00067
00068
00069
00070
00071 #include "visir_destripe.h"
00072
00073 static cpl_image * visir_load_average(const char *,
00074 const cpl_propertylist *);
00075 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00076 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00077 static cpl_error_code visir_rem_glitch(cpl_image *);
00078 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00079 static cpl_error_code visir_offset_hcycle(cpl_image *);
00080
00081
00085
00086
00089
00172
00173 cpl_imagelist * visir_inputs_combine(const char * recipename,
00174 const cpl_parameterlist * parlist,
00175 const irplib_framelist * rawframes,
00176 const char * badpix,
00177 const char * flat,
00178 int * nodding_p,
00179 cpl_boolean do_spc_fix,
00180 double wlen,
00181 visir_spc_resol resol)
00182 {
00183 const char * fnodpos;
00184 int nfiles;
00185 cpl_imagelist * in = NULL;
00186 cpl_image * collapsed = NULL;
00187 cpl_image * prev = NULL;
00188 cpl_vector * nods_vec = NULL;
00189 double * nods_data;
00190 int * nod_pos = NULL;
00191 cpl_image ** images = NULL;
00192 cpl_imagelist * nodded = NULL;
00193 int nnod;
00194 cpl_image * flat_image = NULL;
00195 cpl_image * bpm_im_int = NULL;
00196 cpl_mask * bpm_im_bin = NULL;
00197 cpl_imagelist * hcycle = NULL;
00198 cpl_boolean no_rem;
00199 cpl_boolean is_nodding = CPL_FALSE;
00200 int i, j;
00201 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00202 int ndestripe;
00203 cpl_boolean morpho_destripe;
00204 #ifdef _OPENMP
00205 double tstart, tstop;
00206 #endif
00207 cpl_error_code didfail = CPL_ERROR_NONE;
00208 cpl_errorstate cleanstate = cpl_errorstate_get();
00209
00210
00211 skip_if (0);
00212 skip_if(recipename == NULL);
00213 skip_if(parlist == NULL);
00214 skip_if(rawframes == NULL);
00215
00216
00217 nfiles = irplib_framelist_get_size(rawframes);
00218
00219
00220 if (nfiles % 2) {
00221 if (nfiles == 1) {
00222 cpl_msg_error(cpl_func, "At least two files are required");
00223 skip_if (1);
00224 }
00225 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00226 "ignoring the last of %d files", nfiles);
00227 nfiles--;
00228 }
00229
00230 nnod = nfiles/2;
00231
00232 skip_if (nnod <= 0);
00233
00234 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00235 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00236 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00237 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00238 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00239 CPL_TYPE_INT, CPL_FALSE, 0.0));
00240 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00241 CPL_TYPE_INT, CPL_FALSE, 0.0));
00242
00243
00244
00245 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00246 VISIR_PARAM_NODPOS);
00247 skip_if (0);
00248
00249 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00250 VISIR_PARAM_AUTOBPM);
00251 skip_if (0);
00252
00253 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00254 VISIR_PARAM_GLITCH);
00255 skip_if (0);
00256
00257 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00258 VISIR_PARAM_PURGE);
00259 skip_if (0);
00260
00261 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00262 VISIR_PARAM_STRIPITE);
00263 bug_if (0);
00264
00265 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00266 visir_parameterlist_get_bool(parlist, recipename,
00267 VISIR_PARAM_STRIPMOR);
00268 bug_if (0);
00269
00270 no_rem = !rem_glitch && !rem_bad;
00271
00272
00273
00274 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00275 j = 0;
00276 if (fnodpos != NULL && strlen(fnodpos) > 0) {
00277
00278 nods_vec = cpl_vector_read(fnodpos);
00279 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00280 nods_data = cpl_vector_get_data(nods_vec);
00281 skip_if (0);
00282 for (i=0 ; i<nfiles ; i++) {
00283 if ((int)nods_data[i] == 0) {
00284 nod_pos[i] = 1;
00285 j++;
00286 } else if ((int)nods_data[i] == 1) {
00287 nod_pos[i] = -1;
00288 is_nodding = CPL_TRUE;
00289 } else {
00290 cpl_msg_error(cpl_func, "Wrong values in line %d in %s", i+1,
00291 fnodpos);
00292 skip_if (1);
00293 }
00294 }
00295 } else {
00296 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00297 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00298 }
00299
00300 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00301 "frames requested: Using fast I/O method");
00302
00303
00304 if (badpix != NULL) {
00305
00306 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00307
00308 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00309 skip_if (0);
00310
00311
00312 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00313 cpl_image_delete(bpm_im_int);
00314 bpm_im_int = NULL;
00315 skip_if (cpl_mask_not(bpm_im_bin));
00316 } else if (auto_bpm) {
00317
00318
00319
00320 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00321 skip_if(0);
00322
00323 bpm_im_bin =
00324 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00325 VISIR_HCYCLE_BPM_THRESHOLD,
00326 DBL_MAX);
00327 cpl_imagelist_delete(hcycle);
00328 hcycle = NULL;
00329 skip_if(0);
00330 }
00331
00332
00333 if (flat != NULL) {
00334 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00335
00336 if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00337 cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
00338 skip_if (1);
00339 }
00340 }
00341
00342
00343 nodded = cpl_imagelist_new();
00344
00345 #ifdef _OPENMP
00346 tstart = cpl_test_get_walltime();
00347 #endif
00348
00349
00350
00351 for (i=0; i < nfiles/2 ; i++) {
00352
00353 cpl_image * empty = cpl_image_new(256, 256, CPL_TYPE_FLOAT);
00354
00355 bug_if (cpl_imagelist_set(nodded, empty, i));
00356 }
00357
00358 #ifdef _OPENMP
00359 #pragma omp parallel for private(i, prev, collapsed) schedule(static, 2)
00360 #endif
00361 for (i=0; i < nfiles ; i++) {
00362 const char * file =
00363 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00364 const cpl_propertylist * plist;
00365
00366 double dit;
00367 double factor;
00368
00369
00370 if (didfail) continue;
00371
00372 plist = irplib_framelist_get_propertylist_const(rawframes, i);
00373 if (plist == NULL) {
00374 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00375 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00376 continue;
00377 }
00378
00379 if (nods_vec == NULL) {
00380 const char * sval = visir_pfits_get_nodpos(plist);
00381 if (sval == NULL) {
00382 cpl_msg_error(cpl_func, "Cannot get nodding pos for file %d",
00383 i+1);
00384 didfail = cpl_error_set(cpl_func, CPL_ERROR_UNSPECIFIED);
00385 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00386 continue;
00387 }
00388 if (!strcmp(sval, "A")) {
00389 nod_pos[i] = 1;
00390 j++;
00391 } else {
00392 nod_pos[i] = -1;
00393 is_nodding = CPL_TRUE;
00394 }
00395 }
00396
00397
00398 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00399 nod_pos[i]==1 ? '+' : '-');
00400
00401
00402 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00403 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00404 "on-object (A) and an off-object (B) image: %s", i-1,
00405 i, nod_pos[i] == 1 ? "A" : "B");
00406 }
00407
00408
00409 dit = visir_pfits_get_dit(plist);
00410 if (cpl_error_get_code()) {
00411 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00412 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00413 continue;
00414 }
00415
00416 if (dit <= 0) {
00417 cpl_msg_error(cpl_func, "DIT in file %d is too small: %g", i+1, dit);
00418 didfail = cpl_error_set(cpl_func, CPL_ERROR_UNSPECIFIED);
00419 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00420 continue;
00421 }
00422
00423 factor = dit * nod_pos[i] * 2.0;
00424
00425 if (no_rem){
00426 collapsed = visir_load_average(file, plist);
00427 } else {
00428 in = visir_load_intermint(rawframes, i);
00429 if (in == NULL) {
00430 cpl_msg_error(cpl_func, "Cannot load the image set %d", i+1);
00431 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00432 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00433 continue;
00434 }
00435
00436
00437
00438 if (visir_imagelist_unpack_interm(in)) {
00439 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00440 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00441 continue;
00442 }
00443
00444
00445
00446 if (rem_glitch) {
00447 int jj;
00448 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00449 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00450 cpl_msg_error(cpl_func, "Cannot remove glitch in image "
00451 "%d in set %d", jj+1, i+1);
00452 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00453 irplib_error_recover(cleanstate, "Failure for file %d",
00454 i+1);
00455 continue;
00456 }
00457 }
00458 }
00459
00460
00461 if (rem_bad) {
00462 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00463 if (visir_rem_bad_images(in)) {
00464 cpl_msg_error(cpl_func, "Cannot remove bad images in list "
00465 "%d", i+1);
00466 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00467 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00468 continue;
00469 }
00470 }
00471
00472 collapsed = cpl_imagelist_collapse_create(in);
00473
00474 cpl_imagelist_delete(in);
00475 in = NULL;
00476
00477 }
00478
00479 if (cpl_error_get_code()) {
00480 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00481 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00482 continue;
00483 }
00484
00485
00486 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
00487 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00488 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00489 continue;
00490 }
00491
00492
00493 if (i & 1) {
00494 if (cpl_image_add(prev, collapsed)) {
00495 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00496 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00497 continue;
00498 }
00499 cpl_image_delete(collapsed);
00500 collapsed = NULL;
00501
00502
00503
00504
00505 if (bpm_im_bin != NULL) {
00506
00507 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
00508 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00509 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00510 continue;
00511 }
00512 if (cpl_detector_interpolate_rejected(prev)) {
00513 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00514 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00515 continue;
00516 }
00517 }
00518
00519 if (ndestripe > 0)
00520 if(visir_destripe_image(prev, ndestripe,
00521 VISIR_DESTRIPE_DETECT,
00522 VISIR_DESTRIPE_DETECT_THRESHOLD,
00523 morpho_destripe)) {
00524 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00525 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00526 continue;
00527 }
00528
00529 if (flat_image != NULL) {
00530
00531 if (cpl_image_divide(prev, flat_image)) {
00532 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00533 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00534 continue;
00535 }
00536 }
00537
00538 if (cpl_imagelist_set(nodded, prev, i/2)) {
00539 didfail = cpl_error_set(cpl_func, cpl_error_get_code());
00540 irplib_error_recover(cleanstate, "Failure for file %d", i+1);
00541 continue;
00542 }
00543 prev = NULL;
00544 } else {
00545 prev = collapsed;
00546 collapsed = NULL;
00547 }
00548 }
00549
00550 skip_if(didfail);
00551
00552 #ifdef _OPENMP
00553 tstop = cpl_test_get_walltime();
00554
00555 cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
00556 tstop - tstart);
00557 #endif
00558
00559 cpl_vector_delete(nods_vec);
00560 nods_vec = NULL;
00561
00562 cpl_image_delete(flat_image);
00563 flat_image = NULL;
00564
00565 cpl_mask_delete(bpm_im_bin);
00566 bpm_im_bin = NULL;
00567
00568 if (nod_pos != nodding_p) cpl_free(nod_pos);
00569 nod_pos = NULL;
00570
00571 if (is_nodding && j != nnod) {
00572 cpl_msg_error(cpl_func, "With nodding exactly half of the images "
00573 "must be on-object, not %d of %d", j, 2*nnod);
00574 skip_if (1);
00575 }
00576
00577 if (do_spc_fix) {
00578 const double ksi = visir_parameterlist_get_double(parlist, recipename,
00579 VISIR_PARAM_SPECSKEW);
00580 const double eps = visir_parameterlist_get_double(parlist, recipename,
00581 VISIR_PARAM_VERTARC);
00582 const double delta = visir_parameterlist_get_double(parlist, recipename,
00583 VISIR_PARAM_HORIARC);
00584 const double phi = visir_parameterlist_get_double(parlist, recipename,
00585 VISIR_PARAM_SLITSKEW);
00586 const int doplot = visir_parameterlist_get_int(parlist, recipename,
00587 VISIR_PARAM_PLOT);
00588
00589
00590 skip_if (0);
00591
00592 images = cpl_malloc(nnod * sizeof(cpl_image*));
00593
00594 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00595
00596 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00597 phi, ksi, eps, delta, doplot));
00598 }
00599
00600 end_skip;
00601
00602 cpl_msg_set_time_off();
00603
00604 cpl_free(images);
00605 cpl_imagelist_delete(in);
00606
00607 if (nod_pos != nodding_p) cpl_free(nod_pos);
00608 cpl_vector_delete(nods_vec);
00609 cpl_image_delete(bpm_im_int);
00610 cpl_mask_delete(bpm_im_bin);
00611 cpl_image_delete(collapsed);
00612 cpl_image_delete(prev);
00613 if (cpl_error_get_code() && nodded != NULL) {
00614 cpl_imagelist_delete(nodded);
00615 nodded = NULL;
00616 }
00617
00618 return nodded;
00619 }
00620
00621
00668
00669 cpl_image ** visir_img_recombine(const char * recipename,
00670 const cpl_parameterlist * parlist,
00671 const irplib_framelist * rawframes,
00672 const char * badpix,
00673 const char * flat,
00674 cpl_geom_combine combine_mode,
00675 cpl_boolean * pdid_resize,
00676 cpl_boolean do_spc_fix,
00677 double wlen,
00678 visir_spc_resol resol)
00679 {
00680 int nfiles;
00681 int * nod_pos = NULL;
00682 cpl_imagelist * nodded = NULL;
00683 int nnod;
00684 cpl_bivector * offsets_est = NULL;
00685 cpl_bivector * objs = NULL;
00686 cpl_image ** combined = NULL;
00687 const cpl_vector * sigmas = NULL;
00688 double xoff, yoff;
00689 int i;
00690
00691
00692 bug_if (0);
00693
00694 bug_if (recipename == NULL);
00695 bug_if (parlist == NULL);
00696 bug_if (rawframes == NULL);
00697 bug_if (pdid_resize == NULL);
00698
00699
00700 nfiles = irplib_framelist_get_size(rawframes);
00701
00702
00703 if (nfiles % 2) {
00704 if (nfiles == 1) {
00705 cpl_msg_error(cpl_func, "At least two files are required");
00706 skip_if (1);
00707 }
00708 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00709 "ignoring the last of %d files", nfiles);
00710 nfiles--;
00711 }
00712
00713 skip_if ( nfiles <= 0);
00714
00715
00716 nod_pos = cpl_malloc(nfiles * sizeof(int));
00717
00718
00719 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00720 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00721 nod_pos, do_spc_fix, wlen, resol);
00722
00723 skip_if (nodded == NULL);
00724 nnod = cpl_imagelist_get_size(nodded);
00725
00726
00727 if (nnod == 1) {
00728
00729 combined = cpl_malloc(2*sizeof(cpl_image*));
00730 combined[1] = NULL;
00731
00732 combined[0] = cpl_imagelist_unset(nodded, 0);
00733 bug_if (combined[0] == NULL);
00734
00735 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00736 cpl_image_get_size_y(combined[0]),
00737 CPL_TYPE_INT);
00738 bug_if (combined[1] == NULL);
00739
00740
00741 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00742
00743 *pdid_resize = CPL_FALSE;
00744
00745 } else {
00746 const double psigmas[] = {5, 2, 1, 0.5};
00747 const char * sval;
00748 const char * offsets;
00749 const char * objects;
00750 int sx, sy, mx, my;
00751 int rej_low, rej_high;
00752 cpl_boolean refine;
00753
00754
00755 refine = visir_parameterlist_get_bool(parlist, recipename,
00756 VISIR_PARAM_REFINE);
00757 skip_if (0);
00758
00759 offsets = visir_parameterlist_get_string(parlist, recipename,
00760 VISIR_PARAM_OFFSETS);
00761 skip_if (0);
00762
00763 objects = visir_parameterlist_get_string(parlist, recipename,
00764 VISIR_PARAM_OBJECTS);
00765 skip_if (0);
00766
00767 sval = visir_parameterlist_get_string(parlist, recipename,
00768 VISIR_PARAM_XCORR);
00769 skip_if (0);
00770
00771 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
00772
00773 sval = visir_parameterlist_get_string(parlist, recipename,
00774 VISIR_PARAM_REJECT);
00775 skip_if (0);
00776
00777 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
00778
00779
00780 cpl_msg_info(cpl_func, "Get the offsets estimation");
00781 if (offsets != NULL && strlen(offsets)) {
00782
00783 offsets_est = cpl_bivector_read(offsets);
00784 skip_if (offsets_est==NULL);
00785
00786 if (cpl_bivector_get_size(offsets_est) != nnod) {
00787 cpl_msg_error(cpl_func, "The offsets file %s must have %d "
00788 "entries, not %d", offsets, nnod,
00789 cpl_bivector_get_size(offsets_est));
00790 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00791 skip_if (1);
00792 }
00793 } else {
00794 double * offsets_est_x;
00795 double * offsets_est_y;
00796 double xoff0 = 0.0;
00797 double yoff0 = 0.0;
00798
00799
00800 offsets_est = cpl_bivector_new(nnod);
00801 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00802 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00803
00804 skip_if (0);
00805
00806 offsets_est_x[0] = 0.0;
00807 offsets_est_y[0] = 0.0;
00808
00809 for (i=0; i < nnod ; i++) {
00810 const cpl_propertylist * plist;
00811
00812
00813 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
00814
00815 plist = irplib_framelist_get_propertylist_const(rawframes,
00816 iframe);
00817 skip_if(plist == NULL);
00818
00819 xoff = visir_pfits_get_cumoffsetx(plist);
00820 yoff = visir_pfits_get_cumoffsety(plist);
00821
00822 skip_if (0);
00823
00824 if (i == 0) {
00825 xoff0 = xoff;
00826 yoff0 = yoff;
00827 } else {
00828
00829 offsets_est_x[i] = xoff0 - xoff;
00830 offsets_est_y[i] = yoff0 - yoff;
00831 }
00832 }
00833 }
00834 cpl_free(nod_pos);
00835 nod_pos = NULL;
00836
00837
00838
00839 if (objects != NULL && strlen(objects) > 0 &&
00840 (objs = cpl_bivector_read(objects)) == NULL) {
00841 cpl_msg_error(cpl_func, "Could not read objects from %s", objects);
00842 skip_if (1);
00843 }
00844
00845 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
00846 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
00847 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
00848 CPL_GEOM_FIRST, rej_low, rej_high);
00849
00850 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00851 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
00852 cpl_bivector_dump(offsets_est, stdout);
00853 }
00854
00855 sigmas = cpl_vector_wrap(4, (double*)psigmas);
00856 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
00857 objs, sigmas, NULL, sx, sy,
00858 mx, my, rej_low, rej_high,
00859 combine_mode);
00860 if (combined == NULL) {
00861 cpl_msg_error(cpl_func, "Could not recombine the images");
00862 skip_if(1);
00863 }
00864
00865 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
00866 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
00867 cpl_image_get_size_y(combined[0])
00868 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
00869 }
00870
00871 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
00872 visir_image_plot("", "t 'The combined image'", "", combined[0]);
00873
00874 end_skip;
00875
00876 cpl_free(nod_pos);
00877 cpl_imagelist_delete(nodded);
00878 cpl_bivector_delete(offsets_est);
00879 cpl_bivector_delete(objs);
00880 cpl_vector_unwrap((cpl_vector*)sigmas);
00881
00882 return combined;
00883 }
00884
00885
00908
00909 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
00910 {
00911 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
00912 }
00913
00914
00925
00926 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
00927 {
00928
00929 cpl_image * im_bpm = NULL;
00930 cpl_mask * bpm = NULL;
00931 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
00932
00933
00934 skip_if (0);
00935
00936 skip_if (self == NULL);
00937
00938 if (bpmfile == NULL) {
00939 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
00940 skip_if (0);
00941 } else {
00942
00943
00944 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
00945
00946 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
00947 if (cpl_error_get_code()) {
00948 cpl_msg_error(cpl_func,"Cannot load the bad pixel map %s", bpmfile);
00949 skip_if (1);
00950 }
00951
00952 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
00953 skip_if (0);
00954 cpl_image_delete(im_bpm);
00955 im_bpm = NULL;
00956
00957 skip_if (cpl_mask_not(bpm));
00958 }
00959
00960 skip_if (cpl_image_reject_from_mask(self, bpm));
00961
00962 end_skip;
00963
00964 cpl_image_delete(im_bpm);
00965 cpl_mask_delete(bpm);
00966
00967 return cpl_error_get_code();
00968
00969 }
00970
00971
00972
00979
00980 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
00981 {
00982 cpl_imagelist * self = NULL;
00983 int naxis3;
00984
00985
00986 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00987 CPL_TYPE_INT, CPL_TRUE, 0.0));
00988
00989 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
00990 rawframes,
00991 0));
00992
00993
00994 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
00995 0);
00996
00997 skip_if (self == NULL);
00998
00999 end_skip;
01000
01001 return self;
01002
01003 }
01004
01005
01006
01016
01017 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01018 int pos, cpl_boolean is_interm)
01019 {
01020 cpl_errorstate cleanstate = cpl_errorstate_get();
01021 cpl_imagelist * self = NULL;
01022 cpl_image * image = NULL;
01023 const char * file = NULL;
01024 const cpl_propertylist * plist;
01025 int nchop, naxis3;
01026
01027
01028
01029 skip_if (0);
01030
01031 skip_if (rawframes == NULL);
01032
01033 file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
01034 skip_if (file == NULL);
01035
01036
01037 plist = irplib_framelist_get_propertylist_const(rawframes, pos);
01038 skip_if (plist == NULL);
01039
01040 naxis3 = visir_pfits_get_naxis3(plist);
01041 nchop = visir_pfits_get_chop_ncycles(plist);
01042
01043 skip_if (0);
01044
01045 if (nchop == 0 && naxis3 == 1 && is_interm) {
01046 self = cpl_imagelist_load(file, CPL_TYPE_FLOAT, 0);
01047 } else {
01048 const char * sval;
01049
01050
01051 const int plane_step = (naxis3 == 2 * nchop + 1) ? 2 : 1;
01052 const cpl_type pixel_type = CPL_TYPE_FLOAT;
01053 int nsize;
01054 int iplane;
01055 int i;
01056
01057
01058 if (nchop <= 0) {
01059 cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01060 "NAXIS3=%d): %d", file, naxis3, nchop);
01061 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01062 skip_if (1);
01063 }
01064
01065 if (plane_step == 1 && naxis3 != nchop+2) {
01066 cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01067 "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01068 nchop, file);
01069 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01070 skip_if (1);
01071 }
01072
01073 if (plane_step == 1 && nchop > 1)
01074 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01075 "Cycle frame (old CUBE1-format)", file, nchop);
01076
01077
01078 sval = visir_pfits_get_frame_type(plist);
01079 if (sval == NULL) {
01080
01081 visir_error_reset("Could not get FITS key");
01082
01083 } else if (strlen(sval) == 0) {
01084
01085 } else if (plane_step == 1) {
01086 if (strcmp(sval, "CUBE2")==0)
01087 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01088 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01089 " the frame type is really CUBE1", file,
01090 naxis3, nchop);
01091 } else if (nchop > 1) {
01092
01093 if (strcmp(sval, "CUBE1")==0)
01094 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01095 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01096 " the frame type is really CUBE2", file,
01097 naxis3, nchop);
01098 }
01099
01100 self = cpl_imagelist_new();
01101
01102 if (plane_step == 1) {
01103
01104 iplane = is_interm ? 0 : nchop;
01105
01106 nsize = is_interm ? nchop : 1;
01107 } else {
01108
01109 iplane = is_interm ? 1 : 0;
01110 nsize = nchop;
01111 }
01112
01113 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01114
01115 image = cpl_image_load(file, pixel_type, iplane, 0);
01116 skip_if (image == NULL);
01117
01118 skip_if (!is_interm && visir_offset_hcycle(image));
01119
01120 skip_if (cpl_imagelist_set(self, image, i));
01121
01122 image = NULL;
01123 }
01124
01125 skip_if (i < nsize);
01126 }
01127
01128 end_skip;
01129
01130 if (cpl_error_get_code()) {
01131 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01132 "frame(s) from: %s",
01133 is_interm ? "INTERM" : "Half-Cycle",
01134 file);
01135 cpl_image_delete(image);
01136 cpl_imagelist_delete(self);
01137 self = NULL;
01138 }
01139
01140 return self;
01141 }
01142
01143
01146
01170
01171 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01172 int pos)
01173 {
01174 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01175
01176 }
01177
01178
01187
01188 static cpl_image * visir_load_average(const char * file,
01189 const cpl_propertylist * plist)
01190 {
01191 cpl_errorstate cleanstate = cpl_errorstate_get();
01192 cpl_image * self = NULL;
01193 int nchop, naxis3;
01194
01195
01196 skip_if (0);
01197 skip_if (file == NULL);
01198 skip_if (plist == NULL);
01199
01200 naxis3 = visir_pfits_get_naxis3(plist);
01201 nchop = visir_pfits_get_chop_ncycles(plist);
01202
01203 skip_if (0);
01204
01205 if (nchop == 0 && naxis3 == 1) {
01206 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01207 } else {
01208 const char * sval;
01209
01210
01211 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01212
01213
01214 if (nchop <= 0) {
01215 cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01216 "NAXIS3=%d): %d", file, naxis3, nchop);
01217 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01218 skip_if (1);
01219 }
01220
01221 if (plane_offset == 3 && naxis3 != nchop+2) {
01222 cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01223 "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01224 nchop, file);
01225 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01226 skip_if (1);
01227 }
01228
01229 if (plane_offset == 3 && nchop > 1)
01230 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01231 "Cycle frame (old CUBE1-format)", file, nchop);
01232
01233
01234 sval = visir_pfits_get_frame_type(plist);
01235 if (sval == NULL) {
01236
01237 visir_error_reset("Could not get FITS key");
01238
01239 } else if (strlen(sval) == 0) {
01240
01241 } else if (plane_offset == 3) {
01242 if (strcmp(sval, "CUBE2")==0)
01243 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01244 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01245 " the frame type is really CUBE1", file,
01246 naxis3, nchop);
01247 } else if (nchop > 1) {
01248
01249 if (strcmp(sval, "CUBE1")==0)
01250 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01251 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01252 " the frame type is really CUBE2", file,
01253 naxis3, nchop);
01254 }
01255
01256
01257 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01258
01259 }
01260
01261 skip_if (0);
01262
01263 end_skip;
01264
01265 if (cpl_error_get_code()) {
01266 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01267 "%s", file ? file : "<NULL>");
01268 cpl_image_delete(self);
01269 self = NULL;
01270 }
01271
01272 return self;
01273 }
01274
01275
01298
01299 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01300 {
01301 cpl_image * iprev;
01302 cpl_image * image;
01303 const int n = cpl_imagelist_get_size(self);
01304 int i;
01305
01306
01307 skip_if (0);
01308
01309 if (n == 1) return CPL_ERROR_NONE;
01310
01311 iprev = cpl_imagelist_get(self, n - 1);
01312
01313 skip_if (0);
01314
01315 skip_if (cpl_image_multiply_scalar(iprev, n));
01316
01317
01318 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01319 image = cpl_imagelist_get(self, i-1);
01320
01321 skip_if (0);
01322
01323 skip_if (cpl_image_multiply_scalar(image, i));
01324
01325 skip_if (cpl_image_subtract(iprev, image));
01326
01327 }
01328
01329 image = cpl_imagelist_get(self, 0);
01330
01331 skip_if (0);
01332
01333 skip_if (cpl_image_subtract(iprev, image));
01334
01335 end_skip;
01336
01337 return cpl_error_get_code();
01338 }
01339
01340
01353
01354 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
01355 {
01356 cpl_image * med_filt = NULL;
01357 cpl_mask * bpm = NULL;
01358 cpl_mask * kernel = cpl_mask_new(3, 3);
01359 double mean, stdev;
01360 double low_thresh, high_thresh;
01361 const int nx = cpl_image_get_size_x(glitchy);
01362 const int ny = cpl_image_get_size_y(glitchy);
01363 int i;
01364
01365
01366 double factor1 = 3.0;
01367 double factor2 = 10.0;
01368 const int niterations = 5;
01369 const double median_corr = 1.5;
01370
01371 bug_if (0);
01372
01373
01374 bug_if(cpl_mask_not(kernel));
01375
01376
01377 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
01378 cpl_image_get_size_y(glitchy),
01379 cpl_image_get_type(glitchy));
01380 bug_if(med_filt == NULL);
01381 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
01382 CPL_BORDER_FILTER));
01383 cpl_mask_delete(kernel);
01384 kernel = NULL;
01385
01386
01387 skip_if (cpl_image_subtract(glitchy, med_filt));
01388
01389
01390 for (i=0 ; i < niterations ; i++) {
01391
01392 mean = cpl_image_get_mean(glitchy);
01393 stdev = cpl_image_get_stdev(glitchy);
01394
01395 skip_if (0);
01396
01397
01398 low_thresh = mean - factor1 * stdev;
01399 high_thresh = mean + factor1 * stdev;
01400
01401
01402 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01403 skip_if (cpl_mask_not(bpm));
01404 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01405 cpl_mask_delete(bpm);
01406 bpm = NULL;
01407
01408
01409 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01410 }
01411
01412
01413
01414 mean = cpl_image_get_mean(glitchy);
01415 stdev = cpl_image_get_stdev(glitchy) * median_corr;
01416
01417 skip_if (0);
01418
01419 low_thresh = mean - factor2 * stdev;
01420 high_thresh = mean + factor2 * stdev;
01421
01422 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01423 skip_if (cpl_mask_not(bpm));
01424 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01425 cpl_mask_delete(bpm);
01426 bpm = NULL;
01427
01428
01429 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01430
01431
01432 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01433 skip_if (cpl_image_accept_all(glitchy));
01434
01435
01436 skip_if (cpl_image_add(glitchy, med_filt));
01437
01438 end_skip;
01439
01440 cpl_image_delete(med_filt);
01441 cpl_mask_delete(bpm);
01442 cpl_mask_delete(kernel);
01443
01444 return cpl_error_get_code();
01445 }
01446
01447
01458
01459 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
01460 {
01461 cpl_vector * medians = NULL;
01462 cpl_vector * stdevs = NULL;
01463 cpl_vector * selection = NULL;
01464 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01465 const double threshold = 3;
01466 const int nima = cpl_imagelist_get_size(in);
01467 int i;
01468
01469
01470
01471 skip_if (0);
01472
01473 if (nima <= 3) return CPL_ERROR_NONE;
01474
01475
01476 medians = cpl_vector_new(nima);
01477 stdevs = cpl_vector_new(nima);
01478
01479
01480 for (i=0 ; i < nima ; i++) {
01481 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01482 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01483
01484 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01485 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
01486 cpl_stats_delete(stats);
01487 }
01488
01489 skip_if( 0);
01490
01491
01492 mean_medians = cpl_vector_get_mean(medians);
01493 stdev_medians = cpl_vector_get_stdev(medians);
01494 mean_stdevs = cpl_vector_get_mean(stdevs);
01495 stdev_stdevs = cpl_vector_get_stdev(stdevs);
01496
01497 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01498 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
01499
01500 stdev_medians *= threshold;
01501 stdev_stdevs *= threshold;
01502
01503
01504 selection = cpl_vector_new(nima);
01505 skip_if( cpl_vector_fill(selection, 0));
01506 for (i=0 ; i < nima ; i++) {
01507 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01508 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
01509
01510 cpl_vector_set(selection, i, -1);
01511 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01512 i+1, nima, stdev_medians, stdev_stdevs);
01513 }
01514
01515
01516 cpl_imagelist_erase(in, selection);
01517
01518 end_skip;
01519
01520 cpl_vector_delete(medians);
01521 cpl_vector_delete(stdevs);
01522
01523 cpl_vector_delete(selection);
01524
01525 return CPL_ERROR_NONE;
01526
01527 }
01528
01529
01538
01539 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
01540 {
01541 double minval;
01542
01543
01544 skip_if (0);
01545
01546 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01547
01548 minval = cpl_image_get_min(hcycle);
01549
01550
01551 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01552
01553 end_skip;
01554
01555 return CPL_ERROR_NONE;
01556 }
01557
01558 #include "visir_destripe.c"