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_plot.h"
00050 #include "irplib_framelist.h"
00051
00052
00053
00054
00055
00056
00057 #define VISIR_HCYCLE_BPM_THRESHOLD 65000.0
00058
00059 #ifndef VISIR_DESTRIPE_DETECT
00060 #define VISIR_DESTRIPE_DETECT (3.5 * 1.64)
00061 #endif
00062
00063 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00064 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00065 #endif
00066
00067
00068
00069
00070
00071
00072 #include "visir_destripe.h"
00073
00074 static cpl_image * visir_load_average(const char *,
00075 const cpl_propertylist *);
00076 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00077 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00078 static cpl_error_code visir_rem_glitch(cpl_image *);
00079 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00080 static cpl_error_code visir_offset_hcycle(cpl_image *);
00081
00082
00086
00087
00090
00173
00174 cpl_imagelist * visir_inputs_combine(const char * recipename,
00175 const cpl_parameterlist * parlist,
00176 const irplib_framelist * rawframes,
00177 const char * badpix,
00178 const char * flat,
00179 int * nodding_p,
00180 cpl_boolean do_spc_fix,
00181 double wlen,
00182 visir_spc_resol resol)
00183 {
00184 const char * fnodpos;
00185 int nfiles;
00186 cpl_imagelist * in = NULL;
00187 cpl_image * collapsed = NULL;
00188 cpl_image * prev = NULL;
00189 cpl_vector * nods_vec = NULL;
00190 double * nods_data;
00191 int * nod_pos = NULL;
00192 cpl_image ** images = NULL;
00193 cpl_imagelist * nodded = NULL;
00194 int nnod;
00195 cpl_image * flat_image = NULL;
00196 cpl_image * bpm_im_int = NULL;
00197 cpl_mask * bpm_im_bin = NULL;
00198 cpl_imagelist * hcycle = NULL;
00199 cpl_boolean no_rem;
00200 cpl_boolean is_nodding = CPL_FALSE;
00201 int i, j;
00202 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00203 int ndestripe;
00204 cpl_boolean morpho_destripe;
00205
00206
00207 skip_if (0);
00208 skip_if(recipename == NULL);
00209 skip_if(parlist == NULL);
00210 skip_if(rawframes == NULL);
00211
00212
00213 nfiles = irplib_framelist_get_size(rawframes);
00214
00215
00216 if (nfiles % 2) {
00217 if (nfiles == 1) {
00218 cpl_msg_error(cpl_func, "At least two files are required");
00219 skip_if (1);
00220 }
00221 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00222 "ignoring the last of %d files", nfiles);
00223 nfiles--;
00224 }
00225
00226 nnod = nfiles/2;
00227
00228 skip_if (nnod <= 0);
00229
00230 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00231 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00232 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00233 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00234 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00235 CPL_TYPE_INT, CPL_FALSE, 0.0));
00236 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00237 CPL_TYPE_INT, CPL_FALSE, 0.0));
00238
00239
00240
00241 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00242 VISIR_PARAM_NODPOS);
00243 skip_if (0);
00244
00245 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00246 VISIR_PARAM_AUTOBPM);
00247 skip_if (0);
00248
00249 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00250 VISIR_PARAM_GLITCH);
00251 skip_if (0);
00252
00253 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00254 VISIR_PARAM_PURGE);
00255 skip_if (0);
00256
00257 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00258 VISIR_PARAM_STRIPITE);
00259 bug_if (0);
00260
00261 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00262 visir_parameterlist_get_bool(parlist, recipename,
00263 VISIR_PARAM_STRIPMOR);
00264 bug_if (0);
00265
00266 no_rem = !rem_glitch && !rem_bad;
00267
00268
00269
00270 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00271 j = 0;
00272 if (fnodpos != NULL && strlen(fnodpos) > 0) {
00273
00274 nods_vec = cpl_vector_read(fnodpos);
00275 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00276 nods_data = cpl_vector_get_data(nods_vec);
00277 skip_if (0);
00278 for (i=0 ; i<nfiles ; i++) {
00279 if ((int)nods_data[i] == 0) {
00280 nod_pos[i] = 1;
00281 j++;
00282 } else if ((int)nods_data[i] == 1) {
00283 nod_pos[i] = -1;
00284 is_nodding = CPL_TRUE;
00285 } else {
00286 cpl_msg_error(cpl_func, "Wrong values in line %d in %s", i+1,
00287 fnodpos);
00288 skip_if (1);
00289 }
00290 }
00291 } else {
00292 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00293 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00294 }
00295
00296 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00297 "frames requested: Using fast I/O method");
00298
00299
00300 if (badpix != NULL) {
00301
00302 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00303
00304 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00305 skip_if (0);
00306
00307
00308 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00309 cpl_image_delete(bpm_im_int);
00310 bpm_im_int = NULL;
00311 skip_if (cpl_mask_not(bpm_im_bin));
00312 }
00313
00314
00315 if (flat != NULL) {
00316 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00317
00318 if ((flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0)) == NULL) {
00319 cpl_msg_error(cpl_func, "Cannot load the flat field %s", flat);
00320 skip_if (1);
00321 }
00322 }
00323
00324
00325 nodded = cpl_imagelist_new();
00326 for (i=0; i < nfiles ; i++) {
00327 const char * file =
00328 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00329 const cpl_propertylist * plist;
00330
00331 double dit;
00332 double factor;
00333
00334
00335 plist = irplib_framelist_get_propertylist_const(rawframes, i);
00336 skip_if(plist == NULL);
00337
00338 if (nods_vec == NULL) {
00339 const char * sval = visir_pfits_get_nodpos(plist);
00340 if (sval == NULL) {
00341 cpl_msg_error(cpl_func, "Cannot get nodding pos for file %d",
00342 i+1);
00343 skip_if (1);
00344 }
00345 if (!strcmp(sval, "A")) {
00346 nod_pos[i] = 1;
00347 j++;
00348 } else {
00349 nod_pos[i] = -1;
00350 is_nodding = CPL_TRUE;
00351 }
00352 }
00353
00354
00355 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00356 nod_pos[i]==1 ? '+' : '-');
00357
00358
00359 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00360 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00361 "on-object (A) and an off-object (B) image: %s", i-1,
00362 i, nod_pos[i] == 1 ? "A" : "B");
00363 }
00364
00365
00366 dit = visir_pfits_get_dit(plist);
00367 skip_if (0);
00368
00369 if (dit <= 0) {
00370 cpl_msg_error(cpl_func, "DIT in file %d is too small: %g", i+1, dit);
00371 skip_if (1);
00372 }
00373
00374 factor = dit * nod_pos[i] * 2.0;
00375
00376 if (i == 0 && badpix == NULL && auto_bpm) {
00377
00378
00379 hcycle = visir_load_imagelist(rawframes, i, CPL_FALSE);
00380 skip_if (0);
00381
00382 bpm_im_bin =
00383 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00384 VISIR_HCYCLE_BPM_THRESHOLD,
00385 DBL_MAX);
00386 cpl_imagelist_delete(hcycle);
00387 hcycle = NULL;
00388 skip_if (0);
00389 }
00390
00391 if (no_rem) {
00392 collapsed = visir_load_average(file, plist);
00393 } else {
00394 if ((in = visir_load_intermint(rawframes, i)) == NULL) {
00395 cpl_msg_error(cpl_func, "Cannot load the image set %d", i+1);
00396 skip_if (1);
00397 }
00398
00399
00400
00401 skip_if (visir_imagelist_unpack_interm(in));
00402
00403
00404
00405 if (rem_glitch) {
00406 int jj;
00407 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00408 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00409 cpl_msg_error(cpl_func, "Cannot remove glitch in image "
00410 "%d in set %d", jj+1, i+1);
00411 skip_if (1);
00412 }
00413 }
00414 }
00415
00416
00417 if (rem_bad) {
00418 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00419 if (visir_rem_bad_images(in)) {
00420 cpl_msg_error(cpl_func, "Cannot remove bad images in list "
00421 "%d", i+1);
00422 skip_if (1);
00423 }
00424 }
00425
00426 collapsed = cpl_imagelist_collapse_create(in);
00427
00428 cpl_imagelist_delete(in);
00429 in = NULL;
00430
00431 }
00432
00433 skip_if (0);
00434
00435
00436 skip_if (cpl_image_divide_scalar(collapsed, 2*factor));
00437
00438
00439 if (i & 1) {
00440 bug_if (cpl_image_add(prev, collapsed));
00441 cpl_image_delete(collapsed);
00442 collapsed = NULL;
00443
00444
00445
00446
00447 if (bpm_im_bin != NULL) {
00448
00449 bug_if (cpl_image_reject_from_mask(prev, bpm_im_bin));
00450 bug_if (cpl_detector_interpolate_rejected(prev));
00451 }
00452
00453 if (ndestripe > 0)
00454 skip_if(visir_destripe_image(prev, ndestripe,
00455 VISIR_DESTRIPE_DETECT,
00456 VISIR_DESTRIPE_DETECT_THRESHOLD,
00457 morpho_destripe));
00458
00459 if (flat_image != NULL) {
00460
00461 skip_if (cpl_image_divide(prev, flat_image));
00462 }
00463
00464 bug_if (cpl_imagelist_set(nodded, prev, i/2));
00465 prev = NULL;
00466 } else {
00467 prev = collapsed;
00468 collapsed = NULL;
00469 }
00470 }
00471
00472 cpl_vector_delete(nods_vec);
00473 nods_vec = NULL;
00474
00475 cpl_image_delete(flat_image);
00476 flat_image = NULL;
00477
00478 cpl_mask_delete(bpm_im_bin);
00479 bpm_im_bin = NULL;
00480
00481 if (nod_pos != nodding_p) cpl_free(nod_pos);
00482 nod_pos = NULL;
00483
00484 if (is_nodding && j != nnod) {
00485 cpl_msg_error(cpl_func, "With nodding exactly half of the images "
00486 "must be on-object, not %d of %d", j, 2*nnod);
00487 skip_if (1);
00488 }
00489
00490 if (do_spc_fix) {
00491 const double ksi = visir_parameterlist_get_double(parlist, recipename,
00492 VISIR_PARAM_SPECSKEW);
00493 const double eps = visir_parameterlist_get_double(parlist, recipename,
00494 VISIR_PARAM_VERTARC);
00495 const double delta = visir_parameterlist_get_double(parlist, recipename,
00496 VISIR_PARAM_HORIARC);
00497 const double phi = visir_parameterlist_get_double(parlist, recipename,
00498 VISIR_PARAM_SLITSKEW);
00499 const int doplot = visir_parameterlist_get_int(parlist, recipename,
00500 VISIR_PARAM_PLOT);
00501
00502
00503 skip_if (0);
00504
00505 images = cpl_malloc(nnod * sizeof(cpl_image*));
00506
00507 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00508
00509 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00510 phi, ksi, eps, delta, doplot));
00511 }
00512
00513 end_skip;
00514
00515 cpl_free(images);
00516 cpl_imagelist_delete(in);
00517
00518 if (nod_pos != nodding_p) cpl_free(nod_pos);
00519 cpl_vector_delete(nods_vec);
00520 cpl_image_delete(bpm_im_int);
00521 cpl_mask_delete(bpm_im_bin);
00522 cpl_image_delete(collapsed);
00523 cpl_image_delete(prev);
00524 if (cpl_error_get_code() && nodded != NULL) {
00525 cpl_imagelist_delete(nodded);
00526 nodded = NULL;
00527 }
00528
00529 return nodded;
00530 }
00531
00532
00579
00580 cpl_image ** visir_img_recombine(const char * recipename,
00581 const cpl_parameterlist * parlist,
00582 const irplib_framelist * rawframes,
00583 const char * badpix,
00584 const char * flat,
00585 cpl_geom_combine combine_mode,
00586 cpl_boolean * pdid_resize,
00587 cpl_boolean do_spc_fix,
00588 double wlen,
00589 visir_spc_resol resol)
00590 {
00591 int nfiles;
00592 int * nod_pos = NULL;
00593 cpl_imagelist * nodded = NULL;
00594 int nnod;
00595 cpl_bivector * offsets_est = NULL;
00596 cpl_bivector * objs = NULL;
00597 cpl_image ** combined = NULL;
00598 const cpl_vector * sigmas = NULL;
00599 double xoff, yoff;
00600 int i;
00601
00602
00603 bug_if (0);
00604
00605 bug_if (recipename == NULL);
00606 bug_if (parlist == NULL);
00607 bug_if (rawframes == NULL);
00608 bug_if (pdid_resize == NULL);
00609
00610
00611 nfiles = irplib_framelist_get_size(rawframes);
00612
00613
00614 if (nfiles % 2) {
00615 if (nfiles == 1) {
00616 cpl_msg_error(cpl_func, "At least two files are required");
00617 skip_if (1);
00618 }
00619 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00620 "ignoring the last of %d files", nfiles);
00621 nfiles--;
00622 }
00623
00624 skip_if ( nfiles <= 0);
00625
00626
00627 nod_pos = cpl_malloc(nfiles * sizeof(int));
00628
00629
00630 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00631 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00632 nod_pos, do_spc_fix, wlen, resol);
00633
00634 skip_if (nodded == NULL);
00635 nnod = cpl_imagelist_get_size(nodded);
00636
00637
00638 if (nnod == 1) {
00639
00640 combined = cpl_malloc(2*sizeof(cpl_image*));
00641 combined[1] = NULL;
00642
00643 combined[0] = cpl_imagelist_unset(nodded, 0);
00644 bug_if (combined[0] == NULL);
00645
00646 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00647 cpl_image_get_size_y(combined[0]),
00648 CPL_TYPE_INT);
00649 bug_if (combined[1] == NULL);
00650
00651
00652 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00653
00654 *pdid_resize = CPL_FALSE;
00655
00656 } else {
00657 const double psigmas[] = {5, 2, 1, 0.5};
00658 const char * sval;
00659 const char * offsets;
00660 const char * objects;
00661 int sx, sy, mx, my;
00662 int rej_low, rej_high;
00663 cpl_boolean refine;
00664
00665
00666 refine = visir_parameterlist_get_bool(parlist, recipename,
00667 VISIR_PARAM_REFINE);
00668 skip_if (0);
00669
00670 offsets = visir_parameterlist_get_string(parlist, recipename,
00671 VISIR_PARAM_OFFSETS);
00672 skip_if (0);
00673
00674 objects = visir_parameterlist_get_string(parlist, recipename,
00675 VISIR_PARAM_OBJECTS);
00676 skip_if (0);
00677
00678 sval = visir_parameterlist_get_string(parlist, recipename,
00679 VISIR_PARAM_XCORR);
00680 skip_if (0);
00681
00682 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
00683
00684 sval = visir_parameterlist_get_string(parlist, recipename,
00685 VISIR_PARAM_REJECT);
00686 skip_if (0);
00687
00688 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
00689
00690
00691 cpl_msg_info(cpl_func, "Get the offsets estimation");
00692 if (offsets != NULL && strlen(offsets)) {
00693
00694 offsets_est = cpl_bivector_read(offsets);
00695 skip_if (offsets_est==NULL);
00696
00697 if (cpl_bivector_get_size(offsets_est) != nnod) {
00698 cpl_msg_error(cpl_func, "The offsets file %s must have %d "
00699 "entries, not %d", offsets, nnod,
00700 cpl_bivector_get_size(offsets_est));
00701 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00702 skip_if (1);
00703 }
00704 } else {
00705 double * offsets_est_x;
00706 double * offsets_est_y;
00707 double xoff0 = 0.0;
00708 double yoff0 = 0.0;
00709
00710
00711 offsets_est = cpl_bivector_new(nnod);
00712 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00713 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00714
00715 skip_if (0);
00716
00717 offsets_est_x[0] = 0.0;
00718 offsets_est_y[0] = 0.0;
00719
00720 for (i=0; i < nnod ; i++) {
00721 const cpl_propertylist * plist;
00722
00723
00724 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
00725
00726 plist = irplib_framelist_get_propertylist_const(rawframes,
00727 iframe);
00728 skip_if(plist == NULL);
00729
00730 xoff = visir_pfits_get_cumoffsetx(plist);
00731 yoff = visir_pfits_get_cumoffsety(plist);
00732
00733 skip_if (0);
00734
00735 if (i == 0) {
00736 xoff0 = xoff;
00737 yoff0 = yoff;
00738 } else {
00739
00740 offsets_est_x[i] = xoff0 - xoff;
00741 offsets_est_y[i] = yoff0 - yoff;
00742 }
00743 }
00744 }
00745 cpl_free(nod_pos);
00746 nod_pos = NULL;
00747
00748
00749
00750 if (objects != NULL && strlen(objects) > 0 &&
00751 (objs = cpl_bivector_read(objects)) == NULL) {
00752 cpl_msg_error(cpl_func, "Could not read objects from %s", objects);
00753 skip_if (1);
00754 }
00755
00756 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
00757 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
00758 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
00759 CPL_GEOM_FIRST, rej_low, rej_high);
00760
00761 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00762 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
00763 cpl_bivector_dump(offsets_est, stdout);
00764 }
00765
00766 sigmas = cpl_vector_wrap(4, (double*)psigmas);
00767 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
00768 objs, sigmas, NULL, sx, sy,
00769 mx, my, rej_low, rej_high,
00770 combine_mode);
00771 if (combined == NULL) {
00772 cpl_msg_error(cpl_func, "Could not recombine the images");
00773 skip_if(1);
00774 }
00775
00776 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
00777 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
00778 cpl_image_get_size_y(combined[0])
00779 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
00780 }
00781
00782 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
00783 visir_image_plot("", "t 'The combined image'", "", combined[0]);
00784
00785 end_skip;
00786
00787 cpl_free(nod_pos);
00788 cpl_imagelist_delete(nodded);
00789 cpl_bivector_delete(offsets_est);
00790 cpl_bivector_delete(objs);
00791 cpl_vector_unwrap((cpl_vector*)sigmas);
00792
00793 return combined;
00794 }
00795
00796
00819
00820 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
00821 {
00822 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
00823 }
00824
00825
00836
00837 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
00838 {
00839
00840 cpl_image * im_bpm = NULL;
00841 cpl_mask * bpm = NULL;
00842 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
00843
00844
00845 skip_if (0);
00846
00847 skip_if (self == NULL);
00848
00849 if (bpmfile == NULL) {
00850 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
00851 skip_if (0);
00852 } else {
00853
00854
00855 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
00856
00857 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
00858 if (cpl_error_get_code()) {
00859 cpl_msg_error(cpl_func,"Cannot load the bad pixel map %s", bpmfile);
00860 skip_if (1);
00861 }
00862
00863 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
00864 skip_if (0);
00865 cpl_image_delete(im_bpm);
00866 im_bpm = NULL;
00867
00868 skip_if (cpl_mask_not(bpm));
00869 }
00870
00871 skip_if (cpl_image_reject_from_mask(self, bpm));
00872
00873 end_skip;
00874
00875 cpl_image_delete(im_bpm);
00876 cpl_mask_delete(bpm);
00877
00878 return cpl_error_get_code();
00879
00880 }
00881
00882
00883
00890
00891 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
00892 {
00893 cpl_imagelist * self = NULL;
00894 int naxis3;
00895
00896
00897 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00898 CPL_TYPE_INT, CPL_TRUE, 0.0));
00899
00900 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
00901 rawframes,
00902 0));
00903
00904
00905 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
00906 0);
00907
00908 skip_if (self == NULL);
00909
00910 end_skip;
00911
00912 return self;
00913
00914 }
00915
00916
00917
00927
00928 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
00929 int pos, cpl_boolean is_interm)
00930 {
00931 cpl_errorstate cleanstate = cpl_errorstate_get();
00932 cpl_imagelist * self = NULL;
00933 cpl_image * image = NULL;
00934 const char * file = NULL;
00935 const cpl_propertylist * plist;
00936 int nchop, naxis3;
00937
00938
00939
00940 skip_if (0);
00941
00942 skip_if (rawframes == NULL);
00943
00944 file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
00945 skip_if (file == NULL);
00946
00947
00948 plist = irplib_framelist_get_propertylist_const(rawframes, pos);
00949 skip_if (plist == NULL);
00950
00951 naxis3 = visir_pfits_get_naxis3(plist);
00952 nchop = visir_pfits_get_chop_ncycles(plist);
00953
00954 skip_if (0);
00955
00956 if (nchop == 0 && naxis3 == 1 && is_interm) {
00957 self = cpl_imagelist_load(file, CPL_TYPE_FLOAT, 0);
00958 } else {
00959 const char * sval;
00960
00961
00962 const int plane_step = (naxis3 == 2 * nchop + 1) ? 2 : 1;
00963 const cpl_type pixel_type = CPL_TYPE_FLOAT;
00964 int nsize;
00965 int iplane;
00966 int i;
00967
00968
00969 if (nchop <= 0) {
00970 cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
00971 "NAXIS3=%d): %d", file, naxis3, nchop);
00972 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00973 skip_if (1);
00974 }
00975
00976 if (plane_step == 1 && naxis3 != nchop+2) {
00977 cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
00978 "not a valid VISIR INTERM+Half-Cycle format", naxis3,
00979 nchop, file);
00980 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
00981 skip_if (1);
00982 }
00983
00984 if (plane_step == 1 && nchop > 1)
00985 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
00986 "Cycle frame (old CUBE1-format)", file, nchop);
00987
00988
00989 sval = visir_pfits_get_frame_type(plist);
00990 if (sval == NULL) {
00991
00992 visir_error_reset("Could not get FITS key");
00993
00994 } else if (strlen(sval) == 0) {
00995
00996 } else if (plane_step == 1) {
00997 if (strcmp(sval, "CUBE2")==0)
00998 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
00999 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01000 " the frame type is really CUBE1", file,
01001 naxis3, nchop);
01002 } else if (nchop > 1) {
01003
01004 if (strcmp(sval, "CUBE1")==0)
01005 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01006 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01007 " the frame type is really CUBE2", file,
01008 naxis3, nchop);
01009 }
01010
01011 self = cpl_imagelist_new();
01012
01013 if (plane_step == 1) {
01014
01015 iplane = is_interm ? 0 : nchop;
01016
01017 nsize = is_interm ? nchop : 1;
01018 } else {
01019
01020 iplane = is_interm ? 1 : 0;
01021 nsize = nchop;
01022 }
01023
01024 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01025
01026 image = cpl_image_load(file, pixel_type, iplane, 0);
01027 skip_if (image == NULL);
01028
01029 skip_if (!is_interm && visir_offset_hcycle(image));
01030
01031 skip_if (cpl_imagelist_set(self, image, i));
01032
01033 image = NULL;
01034 }
01035
01036 skip_if (i < nsize);
01037 }
01038
01039 end_skip;
01040
01041 if (cpl_error_get_code()) {
01042 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01043 "frame(s) from: %s",
01044 is_interm ? "INTERM" : "Half-Cycle",
01045 file);
01046 cpl_image_delete(image);
01047 cpl_imagelist_delete(self);
01048 self = NULL;
01049 }
01050
01051 return self;
01052 }
01053
01054
01057
01081
01082 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01083 int pos)
01084 {
01085 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01086
01087 }
01088
01089
01098
01099 static cpl_image * visir_load_average(const char * file,
01100 const cpl_propertylist * plist)
01101 {
01102 cpl_errorstate cleanstate = cpl_errorstate_get();
01103 cpl_image * self = NULL;
01104 int nchop, naxis3;
01105
01106
01107 skip_if (0);
01108 skip_if (file == NULL);
01109 skip_if (plist == NULL);
01110
01111 naxis3 = visir_pfits_get_naxis3(plist);
01112 nchop = visir_pfits_get_chop_ncycles(plist);
01113
01114 skip_if (0);
01115
01116 if (nchop == 0 && naxis3 == 1) {
01117 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01118 } else {
01119 const char * sval;
01120
01121
01122 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01123
01124
01125 if (nchop <= 0) {
01126 cpl_msg_error(cpl_func, "CHOP NCYCLES in %s is non-positive (and "
01127 "NAXIS3=%d): %d", file, naxis3, nchop);
01128 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01129 skip_if (1);
01130 }
01131
01132 if (plane_offset == 3 && naxis3 != nchop+2) {
01133 cpl_msg_error(cpl_func, "NAXIS3=%d and CHOP NCYCLES=%d in %s is "
01134 "not a valid VISIR INTERM+Half-Cycle format", naxis3,
01135 nchop, file);
01136 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01137 skip_if (1);
01138 }
01139
01140 if (plane_offset == 3 && nchop > 1)
01141 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01142 "Cycle frame (old CUBE1-format)", file, nchop);
01143
01144
01145 sval = visir_pfits_get_frame_type(plist);
01146 if (sval == NULL) {
01147
01148 visir_error_reset("Could not get FITS key");
01149
01150 } else if (strlen(sval) == 0) {
01151
01152 } else if (plane_offset == 3) {
01153 if (strcmp(sval, "CUBE2")==0)
01154 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01155 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01156 " the frame type is really CUBE1", file,
01157 naxis3, nchop);
01158 } else if (nchop > 1) {
01159
01160 if (strcmp(sval, "CUBE1")==0)
01161 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01162 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01163 " the frame type is really CUBE2", file,
01164 naxis3, nchop);
01165 }
01166
01167
01168 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01169
01170 }
01171
01172 skip_if (0);
01173
01174 end_skip;
01175
01176 if (cpl_error_get_code()) {
01177 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01178 "%s", file ? file : "<NULL>");
01179 cpl_image_delete(self);
01180 self = NULL;
01181 }
01182
01183 return self;
01184 }
01185
01186
01209
01210 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01211 {
01212 cpl_image * iprev;
01213 cpl_image * image;
01214 const int n = cpl_imagelist_get_size(self);
01215 int i;
01216
01217
01218 skip_if (0);
01219
01220 if (n == 1) return CPL_ERROR_NONE;
01221
01222 iprev = cpl_imagelist_get(self, n - 1);
01223
01224 skip_if (0);
01225
01226 skip_if (cpl_image_multiply_scalar(iprev, n));
01227
01228
01229 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01230 image = cpl_imagelist_get(self, i-1);
01231
01232 skip_if (0);
01233
01234 skip_if (cpl_image_multiply_scalar(image, i));
01235
01236 skip_if (cpl_image_subtract(iprev, image));
01237
01238 }
01239
01240 image = cpl_imagelist_get(self, 0);
01241
01242 skip_if (0);
01243
01244 skip_if (cpl_image_subtract(iprev, image));
01245
01246 end_skip;
01247
01248 return cpl_error_get_code();
01249 }
01250
01251
01264
01265 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
01266 {
01267 cpl_image * med_filt = NULL;
01268 cpl_mask * bpm = NULL;
01269 cpl_matrix * kernel = NULL;
01270 double mean, stdev;
01271 double low_thresh, high_thresh;
01272 const int nx = cpl_image_get_size_x(glitchy);
01273 const int ny = cpl_image_get_size_y(glitchy);
01274 int i;
01275
01276
01277 double factor1 = 3.0;
01278 double factor2 = 10.0;
01279 const int niterations = 5;
01280 const double median_corr = 1.5;
01281
01282
01283 skip_if (0);
01284
01285
01286 kernel = cpl_matrix_new(3, 3);
01287 skip_if (cpl_matrix_fill(kernel, 1.0));
01288
01289
01290 med_filt = cpl_image_filter_median(glitchy, kernel);
01291 cpl_matrix_delete(kernel);
01292 kernel = NULL;
01293
01294
01295 skip_if (cpl_image_subtract(glitchy, med_filt));
01296
01297
01298 for (i=0 ; i < niterations ; i++) {
01299
01300 mean = cpl_image_get_mean(glitchy);
01301 stdev = cpl_image_get_stdev(glitchy);
01302
01303 skip_if (0);
01304
01305
01306 low_thresh = mean - factor1 * stdev;
01307 high_thresh = mean + factor1 * stdev;
01308
01309
01310 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01311 skip_if (cpl_mask_not(bpm));
01312 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01313 cpl_mask_delete(bpm);
01314 bpm = NULL;
01315
01316
01317 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01318 }
01319
01320
01321
01322 mean = cpl_image_get_mean(glitchy);
01323 stdev = cpl_image_get_stdev(glitchy) * median_corr;
01324
01325 skip_if (0);
01326
01327 low_thresh = mean - factor2 * stdev;
01328 high_thresh = mean + factor2 * stdev;
01329
01330 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01331 skip_if (cpl_mask_not(bpm));
01332 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01333 cpl_mask_delete(bpm);
01334 bpm = NULL;
01335
01336
01337 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01338
01339
01340 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01341 skip_if (cpl_image_accept_all(glitchy));
01342
01343
01344 skip_if (cpl_image_add(glitchy, med_filt));
01345
01346 end_skip;
01347
01348 cpl_image_delete(med_filt);
01349 cpl_mask_delete(bpm);
01350 cpl_matrix_delete(kernel);
01351
01352 return cpl_error_get_code();
01353 }
01354
01355
01366
01367 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
01368 {
01369 cpl_vector * medians = NULL;
01370 cpl_vector * stdevs = NULL;
01371 cpl_vector * selection = NULL;
01372 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01373 const double threshold = 3;
01374 const int nima = cpl_imagelist_get_size(in);
01375 int i;
01376
01377
01378
01379 skip_if (0);
01380
01381 if (nima <= 3) return CPL_ERROR_NONE;
01382
01383
01384 medians = cpl_vector_new(nima);
01385 stdevs = cpl_vector_new(nima);
01386
01387
01388 for (i=0 ; i < nima ; i++) {
01389 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01390 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01391
01392 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01393 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
01394 cpl_stats_delete(stats);
01395 }
01396
01397 skip_if( 0);
01398
01399
01400 mean_medians = cpl_vector_get_mean(medians);
01401 stdev_medians = cpl_vector_get_stdev(medians);
01402 mean_stdevs = cpl_vector_get_mean(stdevs);
01403 stdev_stdevs = cpl_vector_get_stdev(stdevs);
01404
01405 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01406 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
01407
01408 stdev_medians *= threshold;
01409 stdev_stdevs *= threshold;
01410
01411
01412 selection = cpl_vector_new(nima);
01413 skip_if( cpl_vector_fill(selection, 0));
01414 for (i=0 ; i < nima ; i++) {
01415 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01416 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
01417
01418 cpl_vector_set(selection, i, -1);
01419 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01420 i+1, nima, stdev_medians, stdev_stdevs);
01421 }
01422
01423
01424 cpl_imagelist_erase(in, selection);
01425
01426 end_skip;
01427
01428 cpl_vector_delete(medians);
01429 cpl_vector_delete(stdevs);
01430
01431 cpl_vector_delete(selection);
01432
01433 return CPL_ERROR_NONE;
01434
01435 }
01436
01437
01446
01447 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
01448 {
01449 double minval;
01450
01451
01452 skip_if (0);
01453
01454 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01455
01456 minval = cpl_image_get_min(hcycle);
01457
01458
01459 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01460
01461 end_skip;
01462
01463 return CPL_ERROR_NONE;
01464 }
01465
01466 #include "visir_destripe.c"