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 <cpl.h>
00037
00038 #include "visir_utils.h"
00039 #include "visir_pfits.h"
00040 #include "visir_parameter.h"
00041 #include "visir_pfits.h"
00042 #include "visir_spc_distortion.h"
00043 #include "visir_inputs.h"
00044 #include "irplib_framelist.h"
00045
00046 #include <string.h>
00047 #include <math.h>
00048 #include <float.h>
00049 #include <assert.h>
00050
00051
00052
00053
00054
00055 #ifndef VISIR_DESTRIPE_DETECT
00056 #define VISIR_DESTRIPE_DETECT (3.5 * 1.64)
00057 #endif
00058
00059 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00060 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00061 #endif
00062
00063
00064 #define VISIRSZ 256
00065
00066 typedef enum {
00067 VISIR_CUBE1,
00068 VISIR_CUBE2
00069 } visir_cube_type;
00070
00071
00072
00073
00074
00075
00076 #include "visir_destripe.h"
00077
00078 static cpl_image * visir_load_average(const char *,
00079 const cpl_propertylist *);
00080 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00081 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00082 static cpl_error_code visir_rem_glitch(cpl_image *);
00083 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00084 static cpl_error_code visir_offset_hcycle(cpl_image *);
00085
00086 static cpl_image ** visir_img_collapse_beam_four(cpl_propertylist *,
00087 const cpl_image *,
00088 const cpl_image *,
00089 double, double,
00090 const cpl_propertylist *);
00091
00092 static cpl_image ** visir_img_collapse_beam_three(cpl_propertylist *,
00093 const cpl_image *,
00094 const cpl_image *,
00095 double, double,
00096 const cpl_propertylist *);
00097
00098
00099 static cpl_error_code visir_img_find_beam_three(cpl_propertylist *,
00100 const cpl_image *,
00101 const cpl_image *,
00102 double, double,
00103 double *,
00104 double *);
00105
00106 static cpl_error_code visir_img_find_beam_four(cpl_propertylist *,
00107 const cpl_image *,
00108 const cpl_image *,
00109 double, double,
00110 double *,
00111 double *);
00112
00113 static cpl_error_code visir_get_type(const irplib_framelist *, int,
00114 visir_cube_type *, int *, int *);
00115
00116
00120
00121
00125
00146
00147
00148 cpl_image * visir_load_cube2_split(cpl_imagelist * alist, cpl_imagelist * blist,
00149 const irplib_framelist * rawframes, int pos)
00150 {
00151
00152 cpl_image * self = NULL;
00153 cpl_imagelist * packed = NULL;
00154 const char * file
00155 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
00156 int naxis3, nchop;
00157 visir_cube_type cube_type;
00158 int i;
00159
00160 (void)visir_get_type(rawframes, pos, &cube_type, &naxis3, &nchop);
00161
00162 any_if("Cannot split non-CUBE2 frame %d/%d in %s", 1+pos,
00163 irplib_framelist_get_size(rawframes), file);
00164 bug_if(alist == NULL);
00165 bug_if(blist == NULL);
00166
00167 error_if(cube_type != VISIR_CUBE2, CPL_ERROR_INCOMPATIBLE_INPUT, "Cannot "
00168 "split non-CUBE2 frame %d/%d w. NAXIS3=%d, NCYCLES=%d in %s",
00169 1+pos, irplib_framelist_get_size(rawframes), naxis3, nchop, file);
00170
00171 packed = cpl_imagelist_load(file, CPL_TYPE_UNSPECIFIED, 0);
00172 skip_if(cpl_imagelist_get_size(packed) != naxis3);
00173
00174 self = cpl_imagelist_unset(packed, naxis3 - 1);
00175
00176
00177 for (i = 0; i < naxis3/2; i++) {
00178 cpl_image * hcycle = cpl_imagelist_unset(packed, 0);
00179 cpl_image * image = cpl_imagelist_unset(packed, 0);
00180
00181 cpl_imagelist_set(alist, image, i);
00182 cpl_imagelist_set(blist, hcycle, i);
00183
00184 }
00185
00186 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00187
00188 bug_if(visir_imagelist_unpack_interm(alist));
00189
00190 for (i = 0; i < naxis3/2; i++) {
00191 const cpl_image * hcycle = cpl_imagelist_get_const(blist, i);
00192 cpl_image * image = cpl_imagelist_get(alist, i);
00193
00194 cpl_image_add(image, hcycle);
00195
00196 }
00197
00198
00199 end_skip;
00200
00201 cpl_imagelist_delete(packed);
00202
00203 return self;
00204
00205 }
00206
00207
00208
00230
00231 cpl_image ** visir_img_collapse_beam(cpl_propertylist * qclist,
00232 const cpl_image * self,
00233 const cpl_parameterlist * parlist,
00234 const char * recipename,
00235 visir_chopnod_mode mode,
00236 const cpl_propertylist * plist)
00237 {
00238
00239 cpl_image ** combined = NULL;
00240
00241 cpl_image * inverse = cpl_image_multiply_scalar_create(self, -1.0);
00242
00243 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
00244 VISIR_PARAM_ECCMAX);
00245
00246
00247 const char * sscale = visir_pfits_get_pixscale(plist);
00248 const double pscale = sscale ? atof(sscale) : 0.0;
00249 const double pthrow = pscale > 0.0
00250 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
00251
00252
00253 skip_if(self == NULL);
00254 skip_if(parlist == NULL);
00255 skip_if(qclist == NULL);
00256 skip_if(plist == NULL);
00257
00258 if (mode == VISIR_CHOPNOD_PERPENDICULAR) {
00259
00260 combined = visir_img_collapse_beam_four(qclist, self, inverse, eccmax,
00261 pthrow, plist);
00262 } else if (mode == VISIR_CHOPNOD_PARALLEL) {
00263
00264 combined = visir_img_collapse_beam_three(qclist, self, inverse, eccmax,
00265 pthrow, plist);
00266 } else if (mode == VISIR_CHOPNOD_AUTO) {
00267 cpl_errorstate cleanstate = cpl_errorstate_get();
00268
00269 const char * sdir = visir_pfits_get_chopnod_dir(plist);
00270
00271 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
00272
00273 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00274 eccmax, pthrow, plist);
00275 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
00276
00277 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00278 eccmax, pthrow, plist);
00279 } else {
00280 if (sdir == NULL) {
00281 visir_error_reset("Could not get FITS key");
00282 } else {
00283 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
00284 sdir);
00285 }
00286 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
00287 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
00288 "PERPENDICULAR");
00289 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00290 eccmax, pthrow, plist);
00291 if (combined == NULL) {
00292 visir_error_reset("Proceeding as if FITS card "
00293 VISIR_PFITS_STRING_CHOPNOD_DIR
00294 " had value: %s", "PARALLEL");
00295 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00296 eccmax, pthrow, plist);
00297 }
00298 }
00299 } else {
00300 bug_if(1);
00301 }
00302
00303 skip_if(combined == NULL);
00304
00305 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
00306 pthrow));
00307 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
00308 "The throw in pixels (TEL CHOP THROW "
00309 "divided by INS PFOV)"));
00310
00311 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM XPOS",
00312 "The X pixel position (centroid) "
00313 "of the one-beam object"));
00314
00315 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM YPOS",
00316 "The Y pixel position (centroid) "
00317 "of the one-beam object"));
00318 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM ECCENTRICITY",
00319 "Eccentricity: 0 for perfect, throw-"
00320 "sized square/line"));
00321
00322 end_skip;
00323
00324 cpl_image_delete(inverse);
00325
00326 return combined;
00327 }
00328
00329
00330
00413
00414 cpl_imagelist * visir_inputs_combine(const char * recipename,
00415 const cpl_parameterlist * parlist,
00416 const irplib_framelist * rawframes,
00417 const char * badpix,
00418 const char * flat,
00419 int * nodding_p,
00420 cpl_boolean do_spc_fix,
00421 double wlen,
00422 visir_spc_resol resol)
00423 {
00424 const char * fnodpos;
00425 int nfiles;
00426 cpl_imagelist * in = NULL;
00427 cpl_image * collapsed = NULL;
00428 cpl_image * prev = NULL;
00429 cpl_vector * nods_vec = NULL;
00430 double * nods_data;
00431 int * nod_pos = NULL;
00432 cpl_image ** images = NULL;
00433 cpl_imagelist * nodded = NULL;
00434 int nnod;
00435 cpl_image * flat_image = NULL;
00436 cpl_image * bpm_im_int = NULL;
00437 cpl_mask * bpm_im_bin = NULL;
00438 cpl_imagelist * hcycle = NULL;
00439 cpl_boolean no_rem;
00440 cpl_boolean is_nodding = CPL_FALSE;
00441 int i, j;
00442 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00443 int ndestripe;
00444 cpl_boolean morpho_destripe;
00445 double tstart, tstop;
00446 #ifdef _OPENMP
00447 cpl_errorstate cleanstate = cpl_errorstate_get();
00448 #endif
00449 cpl_error_code didfail = CPL_ERROR_NONE;
00450
00451
00452 skip_if (0);
00453 skip_if(recipename == NULL);
00454 skip_if(parlist == NULL);
00455 skip_if(rawframes == NULL);
00456
00457
00458 nfiles = irplib_framelist_get_size(rawframes);
00459
00460
00461 if (nfiles % 2) {
00462 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00463 "ignoring the last of %d file(s)", nfiles);
00464 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00465 "At least two files are required");
00466 nfiles--;
00467 }
00468
00469 nnod = nfiles/2;
00470
00471 skip_if (nnod <= 0);
00472
00473 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00474 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00475 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00476 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00477 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00478 CPL_TYPE_INT, CPL_FALSE, 0.0));
00479 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00480 CPL_TYPE_INT, CPL_FALSE, 0.0));
00481
00482
00483
00484 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00485 VISIR_PARAM_NODPOS);
00486 skip_if (0);
00487
00488 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00489 VISIR_PARAM_AUTOBPM);
00490 skip_if (0);
00491
00492 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00493 VISIR_PARAM_GLITCH);
00494 skip_if (0);
00495
00496 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00497 VISIR_PARAM_PURGE);
00498 skip_if (0);
00499
00500 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00501 VISIR_PARAM_STRIPITE);
00502 bug_if (0);
00503
00504 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00505 visir_parameterlist_get_bool(parlist, recipename,
00506 VISIR_PARAM_STRIPMOR);
00507 bug_if (0);
00508
00509 no_rem = !rem_glitch && !rem_bad;
00510
00511
00512
00513 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00514 j = 0;
00515 if (fnodpos != NULL && strlen(fnodpos) > 0) {
00516
00517 nods_vec = cpl_vector_read(fnodpos);
00518 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00519 nods_data = cpl_vector_get_data(nods_vec);
00520 skip_if (0);
00521 for (i=0 ; i<nfiles ; i++) {
00522 if ((int)nods_data[i] == 0) {
00523 nod_pos[i] = 1;
00524 j++;
00525 } else if ((int)nods_data[i] == 1) {
00526 nod_pos[i] = -1;
00527 is_nodding = CPL_TRUE;
00528 } else {
00529 error_if(1, CPL_ERROR_BAD_FILE_FORMAT,
00530 "Wrong values in line %d in %s", i+1, fnodpos);
00531 }
00532 }
00533 } else {
00534 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00535 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00536 }
00537
00538 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00539 "frames requested: Using fast I/O method");
00540
00541
00542 if (badpix != NULL) {
00543
00544 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00545
00546 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00547 skip_if (0);
00548
00549
00550 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00551 cpl_image_delete(bpm_im_int);
00552 bpm_im_int = NULL;
00553 skip_if (cpl_mask_not(bpm_im_bin));
00554 } else if (auto_bpm) {
00555
00556
00557
00558 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00559 skip_if(0);
00560
00561 bpm_im_bin =
00562 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00563 VISIR_HCYCLE_BPM_THRESHOLD,
00564 DBL_MAX);
00565 cpl_imagelist_delete(hcycle);
00566 hcycle = NULL;
00567 skip_if(0);
00568 }
00569
00570
00571 if (flat != NULL) {
00572 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00573
00574 flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
00575 any_if ("Cannot load the flat field %s", flat ? flat : "<NULL>");
00576 }
00577
00578
00579 nodded = cpl_imagelist_new();
00580
00581 tstart = cpl_test_get_walltime();
00582
00583
00584
00585 for (i=0; i < nfiles/2 ; i++) {
00586 cpl_image * empty = cpl_image_new(VISIRSZ, VISIRSZ, CPL_TYPE_FLOAT);
00587
00588
00589
00590
00591 bug_if (cpl_imagelist_set(nodded, empty, i));
00592 }
00593
00594 #ifdef _OPENMP
00595 #pragma omp parallel for private(i) firstprivate(prev, collapsed) \
00596 schedule(static, 2)
00597 #endif
00598 for (i = 0; i < nfiles ; i++) {
00599 cpl_error_code errori = cpl_error_get_code();
00600
00601
00602
00603
00604
00605
00606
00607 if (didfail) continue;
00608
00609 do {
00610
00611 const char * file =
00612 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00613 const cpl_propertylist * plist;
00614
00615 double dit;
00616 double factor;
00617
00618
00619 plist = irplib_framelist_get_propertylist_const(rawframes, i);
00620 if (plist == NULL) {
00621 errori = cpl_error_set_where(cpl_func);
00622 break;
00623 }
00624
00625 if (nods_vec == NULL) {
00626 const char * sval = visir_pfits_get_nodpos(plist);
00627 if (sval == NULL) {
00628 errori = cpl_error_set_message(cpl_func,
00629 CPL_ERROR_DATA_NOT_FOUND,
00630 "Cannot get nodding position "
00631 "for file %d/%d", i+1, nfiles);
00632 break;
00633 }
00634 if (!strcmp(sval, "A")) {
00635 nod_pos[i] = 1;
00636 j++;
00637 } else {
00638 nod_pos[i] = -1;
00639 is_nodding = CPL_TRUE;
00640 }
00641 }
00642
00643
00644 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00645 nod_pos[i]==1 ? '+' : '-');
00646
00647
00648 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00649 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00650 "on-object (A) and an off-object (B) image: %s", i-1,
00651 i, nod_pos[i] == 1 ? "A" : "B");
00652 }
00653
00654
00655 dit = visir_pfits_get_dit(plist);
00656 if (cpl_error_get_code()) {
00657 errori = cpl_error_set_where(cpl_func);
00658 break;
00659 }
00660
00661 if (dit <= 0) {
00662 errori = cpl_error_set_message(cpl_func,
00663 CPL_ERROR_ILLEGAL_INPUT,
00664 "DIT in file %d/%d is too small: "
00665 "%g", i+1, nfiles, dit);
00666 break;
00667 }
00668
00669 factor = dit * nod_pos[i] * 2.0;
00670
00671 if (no_rem){
00672 collapsed = visir_load_average(file, plist);
00673 } else {
00674 in = visir_load_intermint(rawframes, i);
00675 if (in == NULL) {
00676 errori = cpl_error_set_message(cpl_func,
00677 CPL_ERROR_ILLEGAL_INPUT,
00678 "Could not load image set %d",
00679 i+1);
00680 break;
00681 }
00682
00683
00684 if (visir_imagelist_unpack_interm(in)) {
00685 errori = cpl_error_set_message(cpl_func,
00686 cpl_error_get_code(),
00687 "Failure for file %d/%d",
00688 i+1, nfiles);
00689 break;
00690 }
00691
00692
00693
00694 if (rem_glitch) {
00695 int jj;
00696 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00697 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00698 errori = cpl_error_set_message(cpl_func,
00699 cpl_error_get_code(),
00700 "Could not remove "
00701 "glitch in image %d in "
00702 "set %d", jj+1, i+1);
00703 break;
00704 }
00705 }
00706 }
00707
00708
00709 if (rem_bad) {
00710 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00711 if (visir_rem_bad_images(in)) {
00712 errori = cpl_error_set_message(cpl_func,
00713 cpl_error_get_code(),
00714 "Could not remove bad "
00715 "images in list %d", i+1);
00716 break;
00717 }
00718 }
00719
00720 collapsed = cpl_imagelist_collapse_create(in);
00721
00722 cpl_imagelist_delete(in);
00723 in = NULL;
00724
00725 }
00726
00727 if (cpl_error_get_code()) {
00728 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00729 "Failure for file %d/%d",
00730 i+1, nfiles);
00731 break;
00732 }
00733
00734
00735 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
00736 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00737 "Failure for file %d/%d",
00738 i+1, nfiles);
00739 break;
00740 }
00741
00742
00743 if (i & 1) {
00744 if (cpl_image_add(prev, collapsed)) {
00745 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00746 "Failure for file %d/%d",
00747 i+1, nfiles);
00748 break;
00749 }
00750 cpl_image_delete(collapsed);
00751 collapsed = NULL;
00752
00753
00754
00755
00756 if (bpm_im_bin != NULL) {
00757
00758 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
00759 errori = cpl_error_set_message(cpl_func,
00760 cpl_error_get_code(),
00761 "Failure for file %d/%d",
00762 i+1, nfiles);
00763 break;
00764 }
00765 if (cpl_detector_interpolate_rejected(prev)) {
00766 errori = cpl_error_set_message(cpl_func,
00767 cpl_error_get_code(),
00768 "Failure for file %d/%d",
00769 i+1, nfiles);
00770 break;
00771 }
00772 }
00773
00774 if (ndestripe > 0)
00775 if(visir_destripe_image(prev, ndestripe,
00776 VISIR_DESTRIPE_DETECT,
00777 VISIR_DESTRIPE_DETECT_THRESHOLD,
00778 morpho_destripe)) {
00779 errori = cpl_error_set_message(cpl_func,
00780 cpl_error_get_code(),
00781 "Failure for file %d/%d",
00782 i+1, nfiles);
00783 break;
00784 }
00785
00786 if (flat_image != NULL) {
00787
00788 if (cpl_image_divide(prev, flat_image)) {
00789 errori = cpl_error_set_message(cpl_func,
00790 cpl_error_get_code(),
00791 "Failure for file %d/%d",
00792 i+1, nfiles);
00793 break;
00794 }
00795 }
00796
00797 if (cpl_imagelist_set(nodded, prev, i/2)) {
00798 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00799 "Failure for file %d/%d",
00800 i+1, nfiles);
00801 break;
00802 }
00803 prev = NULL;
00804 } else {
00805 prev = collapsed;
00806 collapsed = NULL;
00807 }
00808 } while (0);
00809
00810 if (errori) {
00811 #ifdef _OPENMP
00812
00813
00814 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
00815 cpl_errorstate_set(cleanstate);
00816
00817
00818 cpl_image_delete(prev); prev = NULL;
00819 cpl_image_delete(collapsed); collapsed = NULL;
00820
00821 #pragma omp critical(visir_inputs_combine)
00822 #endif
00823 didfail = errori;
00824 }
00825 }
00826
00827 error_if(didfail, didfail, "Failed to create %d nodded images from %d "
00828 "files", nnod, nfiles);
00829
00830 tstop = cpl_test_get_walltime();
00831 cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
00832 tstop - tstart);
00833
00834 cpl_vector_delete(nods_vec);
00835 nods_vec = NULL;
00836
00837 cpl_image_delete(flat_image);
00838 flat_image = NULL;
00839
00840 cpl_mask_delete(bpm_im_bin);
00841 bpm_im_bin = NULL;
00842
00843 if (nod_pos != nodding_p) cpl_free(nod_pos);
00844 nod_pos = NULL;
00845
00846 error_if(is_nodding && j != nnod, CPL_ERROR_INCOMPATIBLE_INPUT,
00847 "With nodding exactly half of the images "
00848 "must be on-object, not %d of %d", j, 2*nnod);
00849
00850 if (do_spc_fix) {
00851 const double ksi = visir_parameterlist_get_double(parlist, recipename,
00852 VISIR_PARAM_SPECSKEW);
00853 const double eps = visir_parameterlist_get_double(parlist, recipename,
00854 VISIR_PARAM_VERTARC);
00855 const double delta = visir_parameterlist_get_double(parlist, recipename,
00856 VISIR_PARAM_HORIARC);
00857 const double phi = visir_parameterlist_get_double(parlist, recipename,
00858 VISIR_PARAM_SLITSKEW);
00859 const int doplot = visir_parameterlist_get_int(parlist, recipename,
00860 VISIR_PARAM_PLOT);
00861
00862
00863 skip_if (0);
00864
00865 images = cpl_malloc(nnod * sizeof(cpl_image*));
00866
00867 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00868
00869 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00870 phi, ksi, eps, delta, doplot));
00871 }
00872
00873 end_skip;
00874
00875 cpl_msg_set_time_off();
00876
00877 cpl_free(images);
00878 cpl_imagelist_delete(in);
00879
00880 if (nod_pos != nodding_p) cpl_free(nod_pos);
00881 cpl_vector_delete(nods_vec);
00882 cpl_image_delete(bpm_im_int);
00883 cpl_mask_delete(bpm_im_bin);
00884 cpl_image_delete(collapsed);
00885 cpl_image_delete(prev);
00886 if (cpl_error_get_code() && nodded != NULL) {
00887 cpl_imagelist_delete(nodded);
00888 nodded = NULL;
00889 }
00890
00891 return nodded;
00892 }
00893
00894
00941
00942 cpl_image ** visir_img_recombine(const char * recipename,
00943 const cpl_parameterlist * parlist,
00944 const irplib_framelist * rawframes,
00945 const char * badpix,
00946 const char * flat,
00947 cpl_geom_combine combine_mode,
00948 cpl_boolean * pdid_resize,
00949 cpl_boolean do_spc_fix,
00950 double wlen,
00951 visir_spc_resol resol)
00952 {
00953 int nfiles;
00954 int * nod_pos = NULL;
00955 cpl_imagelist * nodded = NULL;
00956 int nnod;
00957 cpl_bivector * offsets_est = NULL;
00958 cpl_bivector * objs = NULL;
00959 cpl_image ** combined = NULL;
00960 const cpl_vector * sigmas = NULL;
00961 double xoff, yoff;
00962 cpl_propertylist * qclist = cpl_propertylist_new();
00963 int i;
00964
00965
00966 bug_if (0);
00967
00968 bug_if (recipename == NULL);
00969 bug_if (parlist == NULL);
00970 bug_if (rawframes == NULL);
00971 bug_if (pdid_resize == NULL);
00972
00973
00974 nfiles = irplib_framelist_get_size(rawframes);
00975
00976
00977 if (nfiles % 2) {
00978 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00979 "ignoring the last of %d file(s)", nfiles);
00980 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00981 "At least two files are required");
00982 nfiles--;
00983 }
00984
00985 skip_if ( nfiles <= 0);
00986
00987
00988 nod_pos = cpl_malloc(nfiles * sizeof(int));
00989
00990
00991 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00992 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00993 nod_pos, do_spc_fix, wlen, resol);
00994
00995 skip_if (nodded == NULL);
00996 nnod = cpl_imagelist_get_size(nodded);
00997
00998
00999 if (nnod == 1) {
01000
01001 combined = cpl_malloc(2*sizeof(cpl_image*));
01002 combined[1] = NULL;
01003
01004 combined[0] = cpl_imagelist_unset(nodded, 0);
01005 bug_if (combined[0] == NULL);
01006
01007 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
01008 cpl_image_get_size_y(combined[0]),
01009 CPL_TYPE_INT);
01010 bug_if (combined[1] == NULL);
01011
01012
01013 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
01014
01015 *pdid_resize = CPL_FALSE;
01016
01017 } else {
01018 const double psigmas[] = {5, 2, 1, 0.5};
01019 const char * sval;
01020 const char * offsets;
01021 const char * objects;
01022 int sx, sy, mx, my;
01023 int rej_low, rej_high;
01024 cpl_boolean refine;
01025
01026
01027 refine = visir_parameterlist_get_bool(parlist, recipename,
01028 VISIR_PARAM_REFINE);
01029 skip_if (0);
01030
01031 offsets = visir_parameterlist_get_string(parlist, recipename,
01032 VISIR_PARAM_OFFSETS);
01033 skip_if (0);
01034
01035 objects = visir_parameterlist_get_string(parlist, recipename,
01036 VISIR_PARAM_OBJECTS);
01037 skip_if (0);
01038
01039 sval = visir_parameterlist_get_string(parlist, recipename,
01040 VISIR_PARAM_XCORR);
01041 skip_if (0);
01042
01043 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
01044
01045 sval = visir_parameterlist_get_string(parlist, recipename,
01046 VISIR_PARAM_REJECT);
01047 skip_if (0);
01048
01049 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
01050
01051
01052 cpl_msg_info(cpl_func, "Get the offsets estimation");
01053 if (offsets != NULL && strlen(offsets)) {
01054
01055 offsets_est = cpl_bivector_read(offsets);
01056 skip_if (offsets_est==NULL);
01057
01058 error_if (cpl_bivector_get_size(offsets_est) != nnod,
01059 CPL_ERROR_BAD_FILE_FORMAT, "The offsets file %s must "
01060 "have %d entries, not %d", offsets, nnod,
01061 cpl_bivector_get_size(offsets_est));
01062 } else {
01063 double * offsets_est_x;
01064 double * offsets_est_y;
01065 double xoff0 = 0.0;
01066 double yoff0 = 0.0;
01067
01068
01069 offsets_est = cpl_bivector_new(nnod);
01070 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01071 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01072
01073 skip_if (0);
01074
01075 offsets_est_x[0] = 0.0;
01076 offsets_est_y[0] = 0.0;
01077
01078 for (i=0; i < nnod ; i++) {
01079 const cpl_propertylist * plist;
01080
01081
01082 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
01083
01084 plist = irplib_framelist_get_propertylist_const(rawframes,
01085 iframe);
01086 skip_if(plist == NULL);
01087
01088 xoff = visir_pfits_get_cumoffsetx(plist);
01089 yoff = visir_pfits_get_cumoffsety(plist);
01090
01091 skip_if (0);
01092
01093 if (i == 0) {
01094 xoff0 = xoff;
01095 yoff0 = yoff;
01096 } else {
01097
01098 offsets_est_x[i] = xoff0 - xoff;
01099 offsets_est_y[i] = yoff0 - yoff;
01100 }
01101 }
01102 }
01103 cpl_free(nod_pos);
01104 nod_pos = NULL;
01105
01106
01107
01108 if (objects != NULL && strlen(objects) > 0) {
01109 objs = cpl_bivector_read(objects);
01110 any_if ("Could not read objects from %s", objects);
01111 }
01112
01113 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
01114 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
01115 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
01116 CPL_GEOM_FIRST, rej_low, rej_high);
01117
01118 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
01119 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
01120 cpl_bivector_dump(offsets_est, stdout);
01121 }
01122
01123 sigmas = cpl_vector_wrap(4, (double*)psigmas);
01124 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
01125 objs, sigmas, NULL, sx, sy,
01126 mx, my, rej_low, rej_high,
01127 combine_mode);
01128 any_if("Could not recombine the images");
01129
01130 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
01131 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
01132 cpl_image_get_size_y(combined[0])
01133 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
01134 }
01135
01136 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
01137 visir_image_plot("", "t 'The combined image'", "", combined[0]);
01138
01139 end_skip;
01140
01141 cpl_propertylist_delete(qclist);
01142 cpl_free(nod_pos);
01143 cpl_imagelist_delete(nodded);
01144 cpl_bivector_delete(offsets_est);
01145 cpl_bivector_delete(objs);
01146 cpl_vector_unwrap((cpl_vector*)sigmas);
01147
01148 return combined;
01149 }
01150
01151
01174
01175 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
01176 {
01177 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
01178 }
01179
01180
01191
01192 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
01193 {
01194
01195 cpl_image * im_bpm = NULL;
01196 cpl_mask * bpm = NULL;
01197 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
01198
01199
01200 skip_if (0);
01201
01202 skip_if (self == NULL);
01203
01204 if (bpmfile == NULL) {
01205 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
01206 skip_if (0);
01207 } else {
01208
01209
01210 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
01211
01212 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
01213 any_if ("Could not load the bad pixel map %s",
01214 bpmfile ? bpmfile : "<NULL>");
01215
01216 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
01217 skip_if (0);
01218 cpl_image_delete(im_bpm);
01219 im_bpm = NULL;
01220
01221 skip_if (cpl_mask_not(bpm));
01222 }
01223
01224 skip_if (cpl_image_reject_from_mask(self, bpm));
01225
01226 end_skip;
01227
01228 cpl_image_delete(im_bpm);
01229 cpl_mask_delete(bpm);
01230
01231 return cpl_error_get_code();
01232
01233 }
01234
01235
01236
01243
01244 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
01245 {
01246 cpl_imagelist * self = NULL;
01247 int naxis3;
01248
01249
01250 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
01251 CPL_TYPE_INT, CPL_TRUE, 0.0));
01252
01253 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
01254 rawframes,
01255 0));
01256
01257
01258 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
01259 0);
01260
01261 skip_if (self == NULL);
01262
01263 end_skip;
01264
01265 return self;
01266
01267 }
01268
01269
01270
01280
01281 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01282 int pos, cpl_boolean is_interm)
01283 {
01284 cpl_imagelist * self = NULL;
01285 cpl_image * image = NULL;
01286 const char * file
01287 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
01288 int naxis3, nchop;
01289 visir_cube_type cube_type;
01290 const cpl_error_code code = visir_get_type(rawframes, pos, &cube_type,
01291 &naxis3, &nchop);
01292 int plane_step;
01293 int nsize;
01294 int iplane;
01295 int i;
01296
01297
01298 skip_if (code);
01299 bug_if (file == NULL);
01300
01301 if (cube_type == VISIR_CUBE1) {
01302
01303 iplane = is_interm ? 0 : nchop;
01304
01305 nsize = is_interm ? nchop : 1;
01306 plane_step = 1;
01307 } else if (naxis3 == 1) {
01308 iplane = 0;
01309 nsize = 1;
01310 plane_step = 1;
01311 } else {
01312
01313 iplane = is_interm ? 1 : 0;
01314 nsize = nchop;
01315 plane_step = 2;
01316 }
01317
01318 self = cpl_imagelist_new();
01319
01320 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01321
01322 image = cpl_image_load(file, CPL_TYPE_FLOAT, iplane, 0);
01323 skip_if (image == NULL);
01324
01325 skip_if (!is_interm && visir_offset_hcycle(image));
01326
01327 skip_if (cpl_imagelist_set(self, image, i));
01328
01329 image = NULL;
01330 }
01331
01332 skip_if (i < nsize);
01333
01334 end_skip;
01335
01336 if (cpl_error_get_code()) {
01337 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01338 "frame(s) from: %s",
01339 is_interm ? "INTERM" : "Half-Cycle",
01340 file);
01341 cpl_image_delete(image);
01342 cpl_imagelist_delete(self);
01343 self = NULL;
01344 }
01345
01346 return self;
01347 }
01348
01349
01352
01376
01377 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01378 int pos)
01379 {
01380 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01381
01382 }
01383
01384
01393
01394 static cpl_image * visir_load_average(const char * file,
01395 const cpl_propertylist * plist)
01396 {
01397 cpl_errorstate cleanstate = cpl_errorstate_get();
01398 cpl_image * self = NULL;
01399 int nchop, naxis3;
01400
01401
01402 skip_if (0);
01403 skip_if (file == NULL);
01404 skip_if (plist == NULL);
01405
01406 naxis3 = visir_pfits_get_naxis3(plist);
01407 nchop = visir_pfits_get_chop_ncycles(plist);
01408
01409 skip_if (0);
01410
01411 if (nchop == 0 && naxis3 == 1) {
01412 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01413 } else {
01414 const char * sval;
01415
01416
01417 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01418
01419
01420 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT, "CHOP NCYCLES in %s "
01421 "is non-positive (and NAXIS3=%d): %d", file, naxis3, nchop);
01422
01423 error_if (plane_offset == 3 && naxis3 != nchop+2,
01424 CPL_ERROR_BAD_FILE_FORMAT, "NAXIS3=%d and CHOP NCYCLES=%d "
01425 "in %s is not a valid VISIR INTERM+Half-Cycle format", naxis3,
01426 nchop, file);
01427
01428 if (plane_offset == 3 && nchop > 1)
01429 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01430 "Cycle frame (old CUBE1-format)", file, nchop);
01431
01432
01433 sval = visir_pfits_get_frame_type(plist);
01434 if (sval == NULL) {
01435
01436 visir_error_reset("Could not get FITS key");
01437
01438 } else if (strlen(sval) == 0) {
01439
01440 } else if (plane_offset == 3) {
01441 if (strcmp(sval, "CUBE2")==0)
01442 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3="
01443 "%d and CHOP NCYCLES=%d imply a CUBE1. Assuming"
01444 " the frame type is really CUBE1", file,
01445 naxis3, nchop);
01446 } else if (nchop > 1) {
01447
01448 if (strcmp(sval, "CUBE1")==0)
01449 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3="
01450 "%d and CHOP NCYCLES=%d imply a CUBE2. Assuming"
01451 "the frame type is really CUBE2", file,
01452 naxis3, nchop);
01453 }
01454
01455
01456 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01457
01458 }
01459
01460 skip_if (0);
01461
01462 end_skip;
01463
01464 if (cpl_error_get_code()) {
01465 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01466 "%s", file ? file : "<NULL>");
01467 cpl_image_delete(self);
01468 self = NULL;
01469 }
01470
01471 return self;
01472 }
01473
01474
01497
01498 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01499 {
01500 cpl_image * iprev;
01501 cpl_image * image;
01502 const int n = cpl_imagelist_get_size(self);
01503 int i;
01504
01505
01506 skip_if (0);
01507
01508 if (n == 1) return CPL_ERROR_NONE;
01509
01510 iprev = cpl_imagelist_get(self, n - 1);
01511
01512 skip_if (0);
01513
01514 skip_if (cpl_image_multiply_scalar(iprev, n));
01515
01516
01517 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01518 image = cpl_imagelist_get(self, i-1);
01519
01520 skip_if (0);
01521
01522 skip_if (cpl_image_multiply_scalar(image, i));
01523
01524 skip_if (cpl_image_subtract(iprev, image));
01525
01526 }
01527
01528 image = cpl_imagelist_get(self, 0);
01529
01530 skip_if (0);
01531
01532 skip_if (cpl_image_subtract(iprev, image));
01533
01534 end_skip;
01535
01536 return cpl_error_get_code();
01537 }
01538
01539
01552
01553 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
01554 {
01555 cpl_image * med_filt = NULL;
01556 cpl_mask * bpm = NULL;
01557 cpl_mask * kernel = cpl_mask_new(3, 3);
01558 double mean, stdev;
01559 double low_thresh, high_thresh;
01560 const int nx = cpl_image_get_size_x(glitchy);
01561 const int ny = cpl_image_get_size_y(glitchy);
01562 int i;
01563
01564
01565 double factor1 = 3.0;
01566 double factor2 = 10.0;
01567 const int niterations = 5;
01568 const double median_corr = 1.5;
01569
01570 bug_if (0);
01571
01572
01573 bug_if(cpl_mask_not(kernel));
01574
01575
01576 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
01577 cpl_image_get_size_y(glitchy),
01578 cpl_image_get_type(glitchy));
01579 bug_if(med_filt == NULL);
01580 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
01581 CPL_BORDER_FILTER));
01582 cpl_mask_delete(kernel);
01583 kernel = NULL;
01584
01585
01586 skip_if (cpl_image_subtract(glitchy, med_filt));
01587
01588
01589 for (i=0 ; i < niterations ; i++) {
01590
01591 mean = cpl_image_get_mean(glitchy);
01592 stdev = cpl_image_get_stdev(glitchy);
01593
01594 skip_if (0);
01595
01596
01597 low_thresh = mean - factor1 * stdev;
01598 high_thresh = mean + factor1 * stdev;
01599
01600
01601 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01602 skip_if (cpl_mask_not(bpm));
01603 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01604 cpl_mask_delete(bpm);
01605 bpm = NULL;
01606
01607
01608 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01609 }
01610
01611
01612
01613 mean = cpl_image_get_mean(glitchy);
01614 stdev = cpl_image_get_stdev(glitchy) * median_corr;
01615
01616 skip_if (0);
01617
01618 low_thresh = mean - factor2 * stdev;
01619 high_thresh = mean + factor2 * stdev;
01620
01621 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01622 skip_if (cpl_mask_not(bpm));
01623 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01624 cpl_mask_delete(bpm);
01625 bpm = NULL;
01626
01627
01628 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01629
01630
01631 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01632 skip_if (cpl_image_accept_all(glitchy));
01633
01634
01635 skip_if (cpl_image_add(glitchy, med_filt));
01636
01637 end_skip;
01638
01639 cpl_image_delete(med_filt);
01640 cpl_mask_delete(bpm);
01641 cpl_mask_delete(kernel);
01642
01643 return cpl_error_get_code();
01644 }
01645
01646
01657
01658 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
01659 {
01660 cpl_vector * medians = NULL;
01661 cpl_vector * stdevs = NULL;
01662 cpl_vector * selection = NULL;
01663 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01664 const double threshold = 3;
01665 const int nima = cpl_imagelist_get_size(in);
01666 int i;
01667
01668
01669
01670 skip_if (0);
01671
01672 if (nima <= 3) return CPL_ERROR_NONE;
01673
01674
01675 medians = cpl_vector_new(nima);
01676 stdevs = cpl_vector_new(nima);
01677
01678
01679 for (i=0 ; i < nima ; i++) {
01680 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01681 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01682
01683 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01684 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
01685 cpl_stats_delete(stats);
01686 }
01687
01688 skip_if( 0);
01689
01690
01691 mean_medians = cpl_vector_get_mean(medians);
01692 stdev_medians = cpl_vector_get_stdev(medians);
01693 mean_stdevs = cpl_vector_get_mean(stdevs);
01694 stdev_stdevs = cpl_vector_get_stdev(stdevs);
01695
01696 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01697 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
01698
01699 stdev_medians *= threshold;
01700 stdev_stdevs *= threshold;
01701
01702
01703 selection = cpl_vector_new(nima);
01704 skip_if( cpl_vector_fill(selection, 0));
01705 for (i=0 ; i < nima ; i++) {
01706 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01707 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
01708
01709 cpl_vector_set(selection, i, -1);
01710 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01711 i+1, nima, stdev_medians, stdev_stdevs);
01712 }
01713
01714
01715 cpl_imagelist_erase(in, selection);
01716
01717 end_skip;
01718
01719 cpl_vector_delete(medians);
01720 cpl_vector_delete(stdevs);
01721
01722 cpl_vector_delete(selection);
01723
01724 return CPL_ERROR_NONE;
01725
01726 }
01727
01728
01737
01738 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
01739 {
01740 double minval;
01741
01742
01743 skip_if (0);
01744
01745 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01746
01747 minval = cpl_image_get_min(hcycle);
01748
01749
01750 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01751
01752 end_skip;
01753
01754 return CPL_ERROR_NONE;
01755 }
01756
01757
01769
01770 static
01771 cpl_image ** visir_img_collapse_beam_four(cpl_propertylist * qclist,
01772 const cpl_image * self,
01773 const cpl_image * inverse,
01774 double eccmax,
01775 double pthrow,
01776 const cpl_propertylist * plist)
01777 {
01778
01779 cpl_image ** combined = NULL;
01780 const int nx = cpl_image_get_size_x(self);
01781 const int ny = cpl_image_get_size_y(self);
01782 const cpl_type type = cpl_image_get_type(self);
01783 cpl_imagelist * list4 = cpl_imagelist_new();
01784 cpl_image * swrap = type == CPL_TYPE_DOUBLE
01785 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)self))
01786 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)self));
01787 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
01788 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
01789 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
01790 cpl_bivector * offs = cpl_bivector_new(4);
01791 double * x4 = cpl_bivector_get_x_data(offs);
01792 double * y4 = cpl_bivector_get_y_data(offs);
01793 double pos_x, pos_y;
01794 int i;
01795
01796 skip_if (0);
01797
01798 skip_if(plist == NULL);
01799
01800 skip_if(visir_img_find_beam_four(qclist, self, inverse, eccmax, pthrow,
01801 x4, y4));
01802
01803
01804 for (i = 1; i < 4; i++) {
01805 x4[i] = x4[0] - x4[i];
01806 y4[i] = y4[0] - y4[i];
01807 }
01808
01809 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
01810 x4[0]));
01811 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
01812 y4[0]));
01813 x4[0] = y4[0] = 0.0;
01814
01815 bug_if(cpl_imagelist_set(list4, (cpl_image*)self, 0));
01816 bug_if(cpl_imagelist_set(list4, swrap, 1));
01817 bug_if(cpl_imagelist_set(list4, (cpl_image*)inverse, 2));
01818 bug_if(cpl_imagelist_set(list4, iwrap, 3));
01819
01820 combined = cpl_geom_img_offset_saa(list4, offs, CPL_KERNEL_DEFAULT, 0, 0,
01821 CPL_GEOM_FIRST, &pos_x, &pos_y);
01822
01823 skip_if(combined == NULL);
01824
01825 end_skip;
01826
01827 cpl_bivector_delete(offs);
01828 for (i = cpl_imagelist_get_size(list4) - 1; i >= 0; i--) {
01829 (void)cpl_imagelist_unset(list4, i);
01830 }
01831 cpl_imagelist_delete(list4);
01832 (void)cpl_image_unwrap(swrap);
01833 (void)cpl_image_unwrap(iwrap);
01834 if (cpl_error_get_code() && combined != NULL) {
01835 cpl_image_delete(combined[0]);
01836 cpl_image_delete(combined[1]);
01837 cpl_free(combined);
01838 }
01839
01840 return combined;
01841 }
01842
01843
01855
01856 static
01857 cpl_error_code visir_img_find_beam_four(cpl_propertylist * qclist,
01858 const cpl_image * self,
01859 const cpl_image * inverse,
01860 double eccmax,
01861 double pthrow,
01862 double x4[],
01863 double y4[])
01864 {
01865
01866 cpl_errorstate cleanstate = cpl_errorstate_get();
01867 cpl_apertures * appos = NULL;
01868 cpl_apertures * apneg = NULL;
01869 const double psigmas[] = {2.0, 1.0, 0.5};
01870 const int nsigmas = sizeof(psigmas)/sizeof(double);
01871 int isigma;
01872 int iappos2[] = {1, 2};
01873 int iapneg2[] = {1, 2};
01874
01875 bug_if(0);
01876 skip_if(self == NULL);
01877 skip_if(qclist == NULL);
01878 skip_if(pthrow <= 0.0);
01879 skip_if(x4 == NULL);
01880 skip_if(y4 == NULL);
01881
01882 cpl_msg_info(cpl_func, "Detecting the 4-beam object with %g pixel throw "
01883 "using %d sigma-levels ranging from %g down to %g", pthrow,
01884 nsigmas, psigmas[0], psigmas[nsigmas-1]);
01885
01886 bug_if(0);
01887 for (isigma = 0; isigma < nsigmas; isigma++) {
01888 int npos = 0;
01889 int nneg = 0;
01890
01891
01892 cpl_apertures_delete(appos);
01893 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
01894
01895 if (appos != NULL) {
01896 npos = cpl_apertures_get_size(appos);
01897 }
01898
01899
01900
01901 cpl_apertures_delete(apneg);
01902 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
01903 if (apneg != NULL) {
01904 nneg = cpl_apertures_get_size(apneg);
01905 }
01906
01907 cpl_msg_info(cpl_func, "Found %d positive (need 2) and %d negative "
01908 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
01909 psigmas[isigma], 1+isigma, nsigmas);
01910
01911 if (eccmax > 0.0) {
01912 int ipos1;
01913 double eccbest = eccmax;
01914 double eccmin = DBL_MAX;
01915 double fluxbest = 0.0;
01916 double fluxecc = DBL_MAX;
01917 cpl_boolean is_first = CPL_TRUE;
01918
01919 #ifdef _OPENMP
01920 #pragma omp parallel for private(ipos1)
01921 #endif
01922 for (ipos1 = 2; ipos1 <= npos; ipos1++) {
01923 int ipos2, ineg1, ineg2;
01924 for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
01925 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
01926 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
01927 cpl_boolean swappos, swapneg;
01928 const double ecc
01929 = visir_img_check_box(appos, ipos1, ipos2,
01930 apneg, ineg1, ineg2,
01931 pthrow, &swappos,
01932 &swapneg);
01933
01934 const double flux
01935 = cpl_apertures_get_flux(appos, ipos1)
01936 + cpl_apertures_get_flux(appos, ipos2)
01937 + cpl_apertures_get_flux(apneg, ineg1)
01938 + cpl_apertures_get_flux(apneg, ineg2);
01939
01940
01941 if (ecc < 0.0 || flux <= 0.0 ||
01942 !cpl_errorstate_is_equal(cleanstate)) {
01943 irplib_error_recover(cleanstate, "Invalid 4-"
01944 "object (%d & %d of %d, "
01945 "%d & %d of %d)",
01946 ipos2, ipos1, npos,
01947 ineg2, ineg1, nneg);
01948 continue;
01949 }
01950
01951 #ifdef _OPENMP
01952 #pragma omp critical(visir_img_find_beam_four_min)
01953 #endif
01954 if (ecc < eccmin)
01955 {
01956 eccmin = ecc;
01957 fluxecc = flux;
01958 }
01959
01960 if (eccmax <= ecc) continue;
01961
01962 #ifdef _OPENMP
01963 #pragma omp critical(visir_img_find_beam_four_ok)
01964 #endif
01965 if (is_first || ecc * fluxbest < eccbest * flux)
01966 {
01967 if (is_first) {
01968 is_first = CPL_FALSE;
01969 cpl_msg_info(cpl_func, "Found 4 object "
01970 "positions with throw-"
01971 "scaled eccentricity %g "
01972 "and flux %g", ecc, flux);
01973 } else {
01974 cpl_msg_info(cpl_func, "Found 4 object "
01975 "positions with throw-"
01976 "scaled eccentricity %g "
01977 "< %g and/or flux %g > %g",
01978 ecc, eccbest, flux, fluxbest);
01979 }
01980 eccbest = ecc;
01981 fluxbest = flux;
01982 iappos2[0] = swappos ? ipos2 : ipos1;
01983 iappos2[1] = swappos ? ipos1 : ipos2;
01984 iapneg2[0] = swapneg ? ineg2 : ineg1;
01985 iapneg2[1] = swapneg ? ineg1 : ineg2;
01986 }
01987 }
01988 }
01989 }
01990 }
01991 if (eccbest < eccmax) {
01992 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
01993 "ECCENTRICITY", eccbest));
01994
01995 break;
01996 }
01997 if (eccmin < DBL_MAX) {
01998 cpl_msg_info(cpl_func, "Found 4 sigma-%g object positions with "
01999 "too large throw-scaled eccentricity %g >= %g and "
02000 "flux %g", psigmas[isigma], eccmin, eccmax,
02001 fluxecc);
02002 }
02003 } else if (npos >= 2 && nneg >= 2) {
02004 cpl_apertures_sort_by_flux(appos);
02005 cpl_apertures_sort_by_flux(apneg);
02006 break;
02007 }
02008
02009 if (isigma + 1 < nsigmas) {
02010 irplib_error_recover(cleanstate, "4-Beam positions not found among "
02011 "%d postive and %d negative object(s) at "
02012 "sigma=%g, (%d of %d)", npos, nneg,
02013 psigmas[isigma], 1+isigma, nsigmas);
02014 }
02015 }
02016
02017 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02018 "4-Beam positions not found w. %d sigma(s) down to %g",
02019 nsigmas, psigmas[nsigmas - 1]);
02020
02021 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02022 cpl_apertures_dump(appos, stdout);
02023 cpl_apertures_dump(apneg, stdout);
02024 }
02025
02026 x4[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
02027 y4[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
02028 x4[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
02029 y4[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
02030
02031 x4[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02032 y4[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02033 x4[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02034 y4[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02035
02036 cpl_msg_info(cpl_func, "Centroid of positive object 1 [pixel]: %g %g",
02037 x4[0], y4[0]);
02038 cpl_msg_info(cpl_func, "Centroid of positive object 2 [pixel]: %g %g",
02039 x4[1], y4[1]);
02040
02041 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02042 x4[2], y4[2]);
02043 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02044 x4[3], y4[3]);
02045
02046 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02047 pthrow);
02048 cpl_msg_info(cpl_func, "Object Pos -> Pos x/y-distance [pixel]: %g %g",
02049 x4[1] - x4[0], y4[1] - y4[0]);
02050 cpl_msg_info(cpl_func, "Object Neg -> Neg x/y-distance [pixel]: %g %g",
02051 x4[3] - x4[2], y4[3] - y4[2]);
02052 cpl_msg_info(cpl_func, "Object Pos -> Pos angle [degrees]: %g",
02053 atan2(y4[1] - y4[0], x4[1] - x4[0]) * CPL_MATH_DEG_RAD);
02054 cpl_msg_info(cpl_func, "Object Neg -> Neg angle [degrees]: %g",
02055 atan2(y4[3] - y4[2], x4[3] - x4[2]) * CPL_MATH_DEG_RAD);
02056
02057 end_skip;
02058
02059 cpl_apertures_delete(appos);
02060 cpl_apertures_delete(apneg);
02061
02062 return cpl_error_get_code();
02063 }
02064
02065
02077
02078 static
02079 cpl_image ** visir_img_collapse_beam_three(cpl_propertylist * qclist,
02080 const cpl_image * self,
02081 const cpl_image * inverse,
02082 double eccmax,
02083 double pthrow,
02084 const cpl_propertylist * plist)
02085 {
02086
02087 cpl_image ** combined = NULL;
02088 const int nx = cpl_image_get_size_x(self);
02089 const int ny = cpl_image_get_size_y(self);
02090 const cpl_type type = cpl_image_get_type(self);
02091 cpl_imagelist * list3 = cpl_imagelist_new();
02092 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02093 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02094 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02095 cpl_bivector * offs = cpl_bivector_new(3);
02096 double * x3 = cpl_bivector_get_x_data(offs);
02097 double * y3 = cpl_bivector_get_y_data(offs);
02098 double pos_x, pos_y;
02099 int i;
02100
02101 skip_if (0);
02102
02103 skip_if(plist == NULL);
02104
02105 skip_if(visir_img_find_beam_three(qclist, self, inverse, eccmax, pthrow,
02106 x3, y3));
02107
02108
02109 for (i = 1; i < 3; i++) {
02110 x3[i] = x3[0] - x3[i];
02111 y3[i] = y3[0] - y3[i];
02112 }
02113 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02114 x3[0]));
02115 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02116 y3[0]));
02117
02118 x3[0] = y3[0] = 0.0;
02119
02120 bug_if(cpl_imagelist_set(list3, (cpl_image*)self, 0));
02121 bug_if(cpl_imagelist_set(list3, (cpl_image*)inverse, 1));
02122 bug_if(cpl_imagelist_set(list3, iwrap, 2));
02123
02124 combined = cpl_geom_img_offset_saa(list3, offs, CPL_KERNEL_DEFAULT, 0, 0,
02125 CPL_GEOM_FIRST, &pos_x, &pos_y);
02126
02127 skip_if(combined == NULL);
02128
02129 end_skip;
02130
02131 cpl_bivector_delete(offs);
02132 for (i = cpl_imagelist_get_size(list3) - 1; i >= 0; i--) {
02133 (void)cpl_imagelist_unset(list3, i);
02134 }
02135 cpl_imagelist_delete(list3);
02136 (void)cpl_image_unwrap(iwrap);
02137 if (cpl_error_get_code() && combined != NULL) {
02138 cpl_image_delete(combined[0]);
02139 cpl_image_delete(combined[1]);
02140 cpl_free(combined);
02141 }
02142
02143 return combined;
02144 }
02145
02146
02147
02160
02161 static
02162 cpl_error_code visir_img_find_beam_three(cpl_propertylist * qclist,
02163 const cpl_image * self,
02164 const cpl_image * inverse,
02165 double eccmax,
02166 double pthrow,
02167 double x3[],
02168 double y3[])
02169 {
02170
02171 cpl_errorstate cleanstate = cpl_errorstate_get();
02172 cpl_apertures * appos = NULL;
02173 cpl_apertures * apneg = NULL;
02174 const double psigmas[] = {2.0, 1.0, 0.5};
02175 const int nsigmas = sizeof(psigmas)/sizeof(double);
02176 int isigma;
02177 int iappos [] = {1};
02178 int iapneg2[] = {1, 2};
02179
02180 bug_if(0);
02181 skip_if(self == NULL);
02182 skip_if(qclist == NULL);
02183 skip_if(pthrow <= 0.0);
02184 skip_if(eccmax < 0.0);
02185 skip_if(x3 == NULL);
02186 skip_if(y3 == NULL);
02187
02188
02189 cpl_msg_info(cpl_func, "Detecting the 3-beam object with %g pixel throw "
02190 "using %d sigma-levels ranging from %g down to %g", pthrow,
02191 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02192
02193 bug_if(0);
02194 for (isigma = 0; isigma < nsigmas; isigma++) {
02195 int npos = 0;
02196 int nneg = 0;
02197
02198
02199 cpl_apertures_delete(appos);
02200 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02201
02202 if (appos != NULL) {
02203 npos = cpl_apertures_get_size(appos);
02204 }
02205
02206
02207
02208 cpl_apertures_delete(apneg);
02209 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02210 if (apneg != NULL) {
02211 nneg = cpl_apertures_get_size(apneg);
02212 }
02213
02214 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
02215 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02216 psigmas[isigma], 1+isigma, nsigmas);
02217
02218 if (eccmax > 0.0) {
02219 int ipos;
02220 double eccbest = eccmax;
02221 double eccmin = DBL_MAX;
02222 double fluxbest = 0.0;
02223 double fluxecc = DBL_MAX;
02224 cpl_boolean is_first = CPL_TRUE;
02225
02226 #ifdef _OPENMP
02227 #pragma omp parallel for private(ipos)
02228 #endif
02229 for (ipos = 1; ipos <= npos; ipos++) {
02230 int ineg1, ineg2;
02231 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
02232 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02233 cpl_boolean swapnegh, swapnegv;
02234 const double ecch
02235 = visir_img_check_align(appos, ipos, apneg, ineg1,
02236 ineg2, pthrow, CPL_TRUE,
02237 &swapnegh);
02238 const double eccv
02239 = visir_img_check_align(appos, ipos, apneg, ineg1,
02240 ineg2, pthrow, CPL_FALSE,
02241 &swapnegv);
02242 const double ecc = ecch < eccv ? ecch : eccv;
02243 const cpl_boolean swapneg = ecch < eccv
02244 ? swapnegh : swapnegv;
02245
02246 const double flux
02247 = cpl_apertures_get_flux(appos, ipos)
02248 + cpl_apertures_get_flux(apneg, ineg1)
02249 + cpl_apertures_get_flux(apneg, ineg2);
02250
02251
02252 if (ecc < 0.0 || flux <= 0.0 ||
02253 !cpl_errorstate_is_equal(cleanstate)) {
02254 irplib_error_recover(cleanstate, "Invalid 3-"
02255 "object (%d of %d, "
02256 "%d & %d of %d)",
02257 ipos, npos,
02258 ineg2, ineg1, nneg);
02259 continue;
02260 }
02261
02262 #ifdef _OPENMP
02263 #pragma omp critical(visir_img_collapse_beam_three_min)
02264 #endif
02265 if (ecc < eccmin)
02266 {
02267 eccmin = ecc;
02268 fluxecc = flux;
02269 }
02270
02271 if (eccmax <= ecc) continue;
02272
02273 #ifdef _OPENMP
02274 #pragma omp critical(visir_img_collapse_beam_three_ok)
02275 #endif
02276 if (is_first || ecc * fluxbest < eccbest * flux)
02277 {
02278 if (is_first) {
02279 is_first = CPL_FALSE;
02280 cpl_msg_info(cpl_func, "Found 3 object posi"
02281 "tions with throw-scaled (ver"
02282 "tical/horizontal) eccentrici"
02283 "ty %g/%g and flux %g", eccv,
02284 ecch, flux);
02285 } else {
02286 cpl_msg_info(cpl_func, "Found 3 object posi"
02287 "tions with throw-scaled (ver"
02288 "tical/horizontal) eccentrici"
02289 "ty %g/%g < %g and/or flux %g "
02290 "> %g", eccv, ecch, eccbest,
02291 flux, fluxbest);
02292 }
02293 eccbest = ecc;
02294 fluxbest = flux;
02295 iappos[0] = ipos;
02296 iapneg2[0] = swapneg ? ineg2 : ineg1;
02297 iapneg2[1] = swapneg ? ineg1 : ineg2;
02298 }
02299 }
02300 }
02301 }
02302 if (eccbest < eccmax) {
02303 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02304 "ECCENTRICITY", eccbest));
02305 break;
02306 }
02307 if (eccmin < DBL_MAX) {
02308 cpl_msg_info(cpl_func, "Found 3 sigma-%g object positions with "
02309 "too large throw-scaled eccentricity %g >= %g and "
02310 "flux %g", psigmas[isigma], eccmin, eccmax,
02311 fluxecc);
02312 }
02313 } else if (npos >= 1 && nneg >= 2) {
02314 cpl_apertures_sort_by_flux(appos);
02315 cpl_apertures_sort_by_flux(apneg);
02316 break;
02317 }
02318
02319 if (isigma + 1 < nsigmas) {
02320 irplib_error_recover(cleanstate, "3-Beam positions not found among "
02321 "%d postive and %d negative object(s) at "
02322 "sigma=%g, (%d of %d)", npos, nneg,
02323 psigmas[isigma], 1+isigma, nsigmas);
02324 }
02325 }
02326
02327 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02328 "3-Beam positions not found w. %d sigma(s) down to %g",
02329 nsigmas, psigmas[nsigmas - 1]);
02330
02331 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02332 cpl_apertures_dump(appos, stdout);
02333 cpl_apertures_dump(apneg, stdout);
02334 }
02335
02336 x3[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
02337 y3[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
02338
02339 x3[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02340 y3[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02341 x3[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02342 y3[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02343
02344 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
02345 x3[0], y3[0]);
02346
02347 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02348 x3[1], y3[1]);
02349 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02350 x3[2], y3[2]);
02351
02352 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02353 pthrow);
02354 cpl_msg_info(cpl_func, "Object Neg1 -> Pos x/y-distance [pixel]: %g %g",
02355 x3[2] - x3[0], y3[2] - y3[0]);
02356 cpl_msg_info(cpl_func, "Object Pos -> Neg2 x/y-distance [pixel]: %g %g",
02357 x3[0] - x3[1], y3[0] - y3[1]);
02358
02359 end_skip;
02360
02361 cpl_apertures_delete(appos);
02362 cpl_apertures_delete(apneg);
02363
02364 return cpl_error_get_code();
02365 }
02366
02367
02368
02369
02388
02389 double visir_img_check_box(const cpl_apertures * appos,
02390 int ipos1, int ipos2,
02391 const cpl_apertures * apneg,
02392 int ineg1, int ineg2, double ssize,
02393 cpl_boolean * pswapp, cpl_boolean * pswapn)
02394 {
02395
02396
02397
02398
02399 const double xp1 = cpl_apertures_get_centroid_x(appos, ipos1);
02400 const double xp2 = cpl_apertures_get_centroid_x(appos, ipos2);
02401 const double yp1 = cpl_apertures_get_centroid_y(appos, ipos1);
02402 const double yp2 = cpl_apertures_get_centroid_y(appos, ipos2);
02403
02404
02405 const double xpl = xp1 < xp2 ? xp1 : xp2;
02406 const double ypl = xp1 < xp2 ? yp1 : yp2;
02407
02408
02409 const double xpr = xp1 < xp2 ? xp2 : xp1;
02410 const double ypr = xp1 < xp2 ? yp2 : yp1;
02411
02412
02413 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
02414 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
02415 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
02416 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
02417
02418
02419 const double xnl = xn1 < xn2 ? xn1 : xn2;
02420 const double ynl = xn1 < xn2 ? yn1 : yn2;
02421
02422
02423 const double xnr = xn1 < xn2 ? xn2 : xn1;
02424 const double ynr = xn1 < xn2 ? yn2 : yn1;
02425
02426 const double lx1 = xnr - xpl;
02427 const double lx2 = xpr - xnl;
02428 const double ly1 = ypl - ynl;
02429 const double ly2 = ynr - ypr;
02430
02431 const double dx1 = lx1 - ssize;
02432 const double dx2 = lx2 - ssize;
02433 const double dy1 = ly1 - ssize;
02434 const double dy2 = ly2 - ssize;
02435
02436 const double ey1 = ynr - ypl;
02437 const double ey2 = ypr - ynl;
02438 const double ex1 = xpl - xnl;
02439 const double ex2 = xpr - xnr;
02440
02441 const double ok = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
02442 ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
02443
02444 double result = -1.0;
02445
02446 skip_if(0);
02447
02448 skip_if(pswapp == NULL);
02449 skip_if(pswapn == NULL);
02450 skip_if(appos == apneg);
02451 skip_if(ipos1 == ipos2);
02452 skip_if(ineg1 == ineg2);
02453
02454 skip_if(ssize <= 0.0);
02455
02456 *pswapp = xp1 < xp2 ? CPL_FALSE : CPL_TRUE;
02457 *pswapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
02458
02459 result = ok/ssize;
02460
02461 end_skip;
02462
02463 return result;
02464
02465 }
02466
02467
02468
02487
02488 double visir_img_check_align(const cpl_apertures * appos, int ipos,
02489 const cpl_apertures * apneg, int ineg1, int ineg2,
02490 double ssize, cpl_boolean is_hor,
02491 cpl_boolean * pswapn)
02492 {
02493
02494
02495
02496
02497 const double xp = cpl_apertures_get_centroid_x(appos, ipos);
02498 const double yp = cpl_apertures_get_centroid_y(appos, ipos);
02499
02500
02501 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
02502 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
02503 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
02504 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
02505
02506 double result = -1.0;
02507
02508 double ok;
02509
02510 cpl_boolean swapn;
02511
02512 if (is_hor) {
02513
02514 const double xnl = xn1 < xn2 ? xn1 : xn2;
02515 const double ynl = xn1 < xn2 ? yn1 : yn2;
02516
02517
02518 const double xnr = xn1 < xn2 ? xn2 : xn1;
02519 const double ynr = xn1 < xn2 ? yn2 : yn1;
02520
02521 const double d1 = xnr - xp - ssize;
02522 const double d2 = xp - xnl - ssize;
02523
02524 const double e1 = ynr - yp;
02525 const double e2 = yp - ynl;
02526
02527 swapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
02528
02529 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
02530
02531 } else {
02532
02533 const double xnl = yn1 < yn2 ? xn1 : xn2;
02534 const double ynl = yn1 < yn2 ? yn1 : yn2;
02535
02536
02537 const double xnr = yn1 < yn2 ? xn2 : xn1;
02538 const double ynr = yn1 < yn2 ? yn2 : yn1;
02539
02540 const double d1 = ynr - yp - ssize;
02541 const double d2 = yp - ynl - ssize;
02542
02543 const double e1 = xnr - xp;
02544 const double e2 = xp - xnl;
02545
02546 swapn = yn1 < yn2 ? CPL_FALSE : CPL_TRUE;
02547
02548 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
02549
02550 }
02551
02552 skip_if(0);
02553
02554 skip_if(pswapn == NULL);
02555 skip_if(appos == apneg);
02556 skip_if(ineg1 == ineg2);
02557
02558 skip_if(ssize <= 0.0);
02559
02560 *pswapn = swapn;
02561
02562 result = ok/ssize;
02563
02564 end_skip;
02565
02566 return result;
02567
02568 }
02569
02570
02571
02582
02583 static cpl_error_code visir_get_type(const irplib_framelist * rawframes,
02584 int pos, visir_cube_type * ptype,
02585 int * pnaxis3, int * pnchop) {
02586
02587
02588
02589 cpl_errorstate cleanstate = cpl_errorstate_get();
02590 const char * file
02591 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
02592 const cpl_propertylist * plist
02593 = irplib_framelist_get_propertylist_const(rawframes, pos);
02594 const int nchop = visir_pfits_get_chop_ncycles(plist);
02595 const int naxis3 = visir_pfits_get_naxis3(plist);
02596 const char * sval = NULL;
02597
02598
02599
02600
02601 skip_if(0);
02602 bug_if(ptype == NULL);
02603 bug_if(pnaxis3 == NULL);
02604
02605 sval = visir_pfits_get_frame_type(plist);
02606 if (sval == NULL) {
02607
02608 visir_error_reset("Could not get FITS key");
02609
02610 } else if (strcmp(sval, "CUBE1")==0) {
02611 *ptype = VISIR_CUBE1;
02612 } else if (strcmp(sval, "CUBE2")==0) {
02613 *ptype = VISIR_CUBE2;
02614 }
02615
02616 if (*ptype == VISIR_CUBE2) {
02617 if (naxis3 == 2 * nchop + 1) {
02618
02619 } else if (naxis3 == nchop + 2) {
02620 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
02621 "and CHOP NCYCLES=%d imply a CUBE1. Assuming "
02622 "the frame type is really CUBE1", file, sval,
02623 naxis3, nchop);
02624 *ptype = VISIR_CUBE1;
02625 } else {
02626 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
02627 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
02628 "Half-Cycle format", file, sval, naxis3, nchop);
02629 skip_if(1);
02630 }
02631 } else if (*ptype == VISIR_CUBE1) {
02632 if (naxis3 == nchop + 2) {
02633
02634 if (nchop > 1)
02635 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
02636 "Cycle frame (old CUBE1-format)", file, nchop);
02637
02638 } else if (naxis3 == 2 * nchop + 1) {
02639 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
02640 "and CHOP NCYCLES=%d imply a CUBE2. Assuming "
02641 "the frame type is really CUBE2", file, sval,
02642 naxis3, nchop);
02643 *ptype = VISIR_CUBE2;
02644 } else {
02645 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
02646 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
02647 "Half-Cycle format", file, sval, naxis3, nchop);
02648 skip_if(1);
02649 }
02650 } else if (naxis3 == 2 * nchop + 1) {
02651 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
02652 "CHOP NCYCLES=%d imply a CUBE2. Assuming the frame "
02653 "type is CUBE2", file, sval ? sval : "<NULL>", naxis3,
02654 nchop);
02655 *ptype = VISIR_CUBE2;
02656 } else if (naxis3 == nchop + 2) {
02657 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
02658 "CHOP NCYCLES=%d imply a CUBE1. Assuming the frame "
02659 "type is CUBE1", file, sval ? sval : "<NULL>", naxis3,
02660 nchop);
02661 *ptype = VISIR_CUBE1;
02662 } else {
02663 return cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
02664 "%s has FRAM TYPE='%s', NAXIS3 = %d and "
02665 "CHOP NCYCLES = %d", file,
02666 sval ? sval : "<NULL>", naxis3, nchop);
02667 }
02668
02669 *pnaxis3 = naxis3;
02670 *pnchop = nchop;
02671
02672 end_skip;
02673
02674 return cpl_error_get_code();
02675 }
02676
02677
02678 #include "visir_destripe.c"