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
00056 #define VISIR_HCYCLE_BPM_THRESHOLD 65000.0
00057
00058 #ifndef VISIR_DESTRIPE_DETECT
00059 #define VISIR_DESTRIPE_DETECT (3.5 * 1.64)
00060 #endif
00061
00062 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00063 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00064 #endif
00065
00066
00067 #define VISIRSZ 256
00068
00069
00070
00071
00072
00073
00074 #include "visir_destripe.h"
00075
00076 static cpl_image * visir_load_average(const char *,
00077 const cpl_propertylist *);
00078 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00079 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00080 static cpl_error_code visir_rem_glitch(cpl_image *);
00081 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00082 static cpl_error_code visir_offset_hcycle(cpl_image *);
00083
00084 static cpl_image ** visir_img_collapse_beam_four(cpl_propertylist *,
00085 const cpl_image *,
00086 const cpl_image *,
00087 double, double,
00088 const cpl_propertylist *);
00089
00090 static cpl_image ** visir_img_collapse_beam_three(cpl_propertylist *,
00091 const cpl_image *,
00092 const cpl_image *,
00093 double, double,
00094 const cpl_propertylist *);
00095
00096
00097 static cpl_error_code visir_img_find_beam_three(cpl_propertylist *,
00098 const cpl_image *,
00099 const cpl_image *,
00100 double, double,
00101 double *,
00102 double *);
00103
00104 static cpl_error_code visir_img_find_beam_four(cpl_propertylist *,
00105 const cpl_image *,
00106 const cpl_image *,
00107 double, double,
00108 double *,
00109 double *);
00110
00111
00115
00116
00119
00141
00142 cpl_image ** visir_img_collapse_beam(cpl_propertylist * qclist,
00143 const cpl_image * self,
00144 const cpl_parameterlist * parlist,
00145 const char * recipename,
00146 visir_chopnod_mode mode,
00147 const cpl_propertylist * plist)
00148 {
00149
00150 cpl_image ** combined = NULL;
00151
00152 cpl_image * inverse = cpl_image_multiply_scalar_create(self, -1.0);
00153
00154 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
00155 VISIR_PARAM_ECCMAX);
00156
00157
00158 const char * sthrow = visir_pfits_get_pixscale(plist);
00159 const double pscale = sthrow ? atof(sthrow) : 0.0;
00160 const double pthrow = pscale > 0.0
00161 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
00162
00163
00164 skip_if(self == NULL);
00165 skip_if(parlist == NULL);
00166 skip_if(qclist == NULL);
00167 skip_if(plist == NULL);
00168
00169 if (mode == VISIR_CHOPNOD_PERPENDICULAR) {
00170
00171 combined = visir_img_collapse_beam_four(qclist, self, inverse, eccmax,
00172 pthrow, plist);
00173 } else if (mode == VISIR_CHOPNOD_PARALLEL) {
00174
00175 combined = visir_img_collapse_beam_three(qclist, self, inverse, eccmax,
00176 pthrow, plist);
00177 } else if (mode == VISIR_CHOPNOD_AUTO) {
00178 cpl_errorstate cleanstate = cpl_errorstate_get();
00179
00180 const char * sdir = visir_pfits_get_chopnod_dir(plist);
00181
00182 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
00183
00184 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00185 eccmax, pthrow, plist);
00186 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
00187
00188 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00189 eccmax, pthrow, plist);
00190 } else {
00191 if (sdir == NULL) {
00192 visir_error_reset("Could not get FITS key");
00193 } else {
00194 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
00195 sdir);
00196 }
00197 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
00198 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
00199 "PERPENDICULAR");
00200 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00201 eccmax, pthrow, plist);
00202 if (combined == NULL) {
00203 visir_error_reset("Proceeding as if FITS card "
00204 VISIR_PFITS_STRING_CHOPNOD_DIR
00205 " had value: %s", "PARALLEL");
00206 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00207 eccmax, pthrow, plist);
00208 }
00209 }
00210 } else {
00211 bug_if(1);
00212 }
00213
00214 skip_if(combined == NULL);
00215
00216 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
00217 pthrow));
00218 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
00219 "The throw in pixels (TEL CHOP THROW "
00220 "divided by INS PFOV)"));
00221
00222 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM XPOS",
00223 "The X pixel position (centroid) "
00224 "of the one-beam object"));
00225
00226 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM YPOS",
00227 "The Y pixel position (centroid) "
00228 "of the one-beam object"));
00229 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM ECCENTRICITY",
00230 "Eccentricity: 0 for perfect, throw-"
00231 "sized square/line"));
00232
00233 end_skip;
00234
00235 cpl_image_delete(inverse);
00236
00237 return combined;
00238 }
00239
00240
00241
00324
00325 cpl_imagelist * visir_inputs_combine(const char * recipename,
00326 const cpl_parameterlist * parlist,
00327 const irplib_framelist * rawframes,
00328 const char * badpix,
00329 const char * flat,
00330 int * nodding_p,
00331 cpl_boolean do_spc_fix,
00332 double wlen,
00333 visir_spc_resol resol)
00334 {
00335 const char * fnodpos;
00336 int nfiles;
00337 cpl_imagelist * in = NULL;
00338 cpl_image * collapsed = NULL;
00339 cpl_image * prev = NULL;
00340 cpl_vector * nods_vec = NULL;
00341 double * nods_data;
00342 int * nod_pos = NULL;
00343 cpl_image ** images = NULL;
00344 cpl_imagelist * nodded = NULL;
00345 int nnod;
00346 cpl_image * flat_image = NULL;
00347 cpl_image * bpm_im_int = NULL;
00348 cpl_mask * bpm_im_bin = NULL;
00349 cpl_imagelist * hcycle = NULL;
00350 cpl_boolean no_rem;
00351 cpl_boolean is_nodding = CPL_FALSE;
00352 int i, j;
00353 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00354 int ndestripe;
00355 cpl_boolean morpho_destripe;
00356 double tstart, tstop;
00357 #ifdef _OPENMP
00358 cpl_errorstate cleanstate = cpl_errorstate_get();
00359 #endif
00360 cpl_error_code didfail = CPL_ERROR_NONE;
00361
00362
00363 skip_if (0);
00364 skip_if(recipename == NULL);
00365 skip_if(parlist == NULL);
00366 skip_if(rawframes == NULL);
00367
00368
00369 nfiles = irplib_framelist_get_size(rawframes);
00370
00371
00372 if (nfiles % 2) {
00373 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00374 "ignoring the last of %d file(s)", nfiles);
00375 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00376 "At least two files are required");
00377 nfiles--;
00378 }
00379
00380 nnod = nfiles/2;
00381
00382 skip_if (nnod <= 0);
00383
00384 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00385 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00386 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00387 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00388 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00389 CPL_TYPE_INT, CPL_FALSE, 0.0));
00390 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00391 CPL_TYPE_INT, CPL_FALSE, 0.0));
00392
00393
00394
00395 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00396 VISIR_PARAM_NODPOS);
00397 skip_if (0);
00398
00399 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00400 VISIR_PARAM_AUTOBPM);
00401 skip_if (0);
00402
00403 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00404 VISIR_PARAM_GLITCH);
00405 skip_if (0);
00406
00407 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00408 VISIR_PARAM_PURGE);
00409 skip_if (0);
00410
00411 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00412 VISIR_PARAM_STRIPITE);
00413 bug_if (0);
00414
00415 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00416 visir_parameterlist_get_bool(parlist, recipename,
00417 VISIR_PARAM_STRIPMOR);
00418 bug_if (0);
00419
00420 no_rem = !rem_glitch && !rem_bad;
00421
00422
00423
00424 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00425 j = 0;
00426 if (fnodpos != NULL && strlen(fnodpos) > 0) {
00427
00428 nods_vec = cpl_vector_read(fnodpos);
00429 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00430 nods_data = cpl_vector_get_data(nods_vec);
00431 skip_if (0);
00432 for (i=0 ; i<nfiles ; i++) {
00433 if ((int)nods_data[i] == 0) {
00434 nod_pos[i] = 1;
00435 j++;
00436 } else if ((int)nods_data[i] == 1) {
00437 nod_pos[i] = -1;
00438 is_nodding = CPL_TRUE;
00439 } else {
00440 error_if(1, CPL_ERROR_BAD_FILE_FORMAT,
00441 "Wrong values in line %d in %s", i+1, fnodpos);
00442 }
00443 }
00444 } else {
00445 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00446 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00447 }
00448
00449 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00450 "frames requested: Using fast I/O method");
00451
00452
00453 if (badpix != NULL) {
00454
00455 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00456
00457 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00458 skip_if (0);
00459
00460
00461 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00462 cpl_image_delete(bpm_im_int);
00463 bpm_im_int = NULL;
00464 skip_if (cpl_mask_not(bpm_im_bin));
00465 } else if (auto_bpm) {
00466
00467
00468
00469 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00470 skip_if(0);
00471
00472 bpm_im_bin =
00473 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00474 VISIR_HCYCLE_BPM_THRESHOLD,
00475 DBL_MAX);
00476 cpl_imagelist_delete(hcycle);
00477 hcycle = NULL;
00478 skip_if(0);
00479 }
00480
00481
00482 if (flat != NULL) {
00483 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00484
00485 flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
00486 any_if ("Cannot load the flat field %s", flat ? flat : "<NULL>");
00487 }
00488
00489
00490 nodded = cpl_imagelist_new();
00491
00492 tstart = cpl_test_get_walltime();
00493
00494
00495
00496 for (i=0; i < nfiles/2 ; i++) {
00497 cpl_image * empty = cpl_image_new(VISIRSZ, VISIRSZ, CPL_TYPE_FLOAT);
00498
00499
00500
00501
00502 bug_if (cpl_imagelist_set(nodded, empty, i));
00503 }
00504
00505 #ifdef _OPENMP
00506 #pragma omp parallel for private(i) firstprivate(prev, collapsed) \
00507 schedule(static, 2)
00508 #endif
00509 for (i = 0; i < nfiles ; i++) {
00510 cpl_error_code errori = cpl_error_get_code();
00511
00512
00513
00514
00515
00516
00517
00518 if (didfail) continue;
00519
00520 do {
00521
00522 const char * file =
00523 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00524 const cpl_propertylist * plist;
00525
00526 double dit;
00527 double factor;
00528
00529
00530 plist = irplib_framelist_get_propertylist_const(rawframes, i);
00531 if (plist == NULL) {
00532 errori = cpl_error_set_where(cpl_func);
00533 break;
00534 }
00535
00536 if (nods_vec == NULL) {
00537 const char * sval = visir_pfits_get_nodpos(plist);
00538 if (sval == NULL) {
00539 errori = cpl_error_set_message(cpl_func,
00540 CPL_ERROR_DATA_NOT_FOUND,
00541 "Cannot get nodding position "
00542 "for file %d/%d", i+1, nfiles);
00543 break;
00544 }
00545 if (!strcmp(sval, "A")) {
00546 nod_pos[i] = 1;
00547 j++;
00548 } else {
00549 nod_pos[i] = -1;
00550 is_nodding = CPL_TRUE;
00551 }
00552 }
00553
00554
00555 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00556 nod_pos[i]==1 ? '+' : '-');
00557
00558
00559 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00560 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00561 "on-object (A) and an off-object (B) image: %s", i-1,
00562 i, nod_pos[i] == 1 ? "A" : "B");
00563 }
00564
00565
00566 dit = visir_pfits_get_dit(plist);
00567 if (cpl_error_get_code()) {
00568 errori = cpl_error_set_where(cpl_func);
00569 break;
00570 }
00571
00572 if (dit <= 0) {
00573 errori = cpl_error_set_message(cpl_func,
00574 CPL_ERROR_ILLEGAL_INPUT,
00575 "DIT in file %d/%d is too small: "
00576 "%g", i+1, nfiles, dit);
00577 break;
00578 }
00579
00580 factor = dit * nod_pos[i] * 2.0;
00581
00582 if (no_rem){
00583 collapsed = visir_load_average(file, plist);
00584 } else {
00585 in = visir_load_intermint(rawframes, i);
00586 if (in == NULL) {
00587 errori = cpl_error_set_message(cpl_func,
00588 CPL_ERROR_ILLEGAL_INPUT,
00589 "Could not load image set %d",
00590 i+1);
00591 break;
00592 }
00593
00594
00595 if (visir_imagelist_unpack_interm(in)) {
00596 errori = cpl_error_set_message(cpl_func,
00597 cpl_error_get_code(),
00598 "Failure for file %d/%d",
00599 i+1, nfiles);
00600 break;
00601 }
00602
00603
00604
00605 if (rem_glitch) {
00606 int jj;
00607 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00608 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00609 errori = cpl_error_set_message(cpl_func,
00610 cpl_error_get_code(),
00611 "Could not remove "
00612 "glitch in image %d in "
00613 "set %d", jj+1, i+1);
00614 break;
00615 }
00616 }
00617 }
00618
00619
00620 if (rem_bad) {
00621 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00622 if (visir_rem_bad_images(in)) {
00623 errori = cpl_error_set_message(cpl_func,
00624 cpl_error_get_code(),
00625 "Could not remove bad "
00626 "images in list %d", i+1);
00627 break;
00628 }
00629 }
00630
00631 collapsed = cpl_imagelist_collapse_create(in);
00632
00633 cpl_imagelist_delete(in);
00634 in = NULL;
00635
00636 }
00637
00638 if (cpl_error_get_code()) {
00639 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00640 "Failure for file %d/%d",
00641 i+1, nfiles);
00642 break;
00643 }
00644
00645
00646 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
00647 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00648 "Failure for file %d/%d",
00649 i+1, nfiles);
00650 break;
00651 }
00652
00653
00654 if (i & 1) {
00655 if (cpl_image_add(prev, collapsed)) {
00656 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00657 "Failure for file %d/%d",
00658 i+1, nfiles);
00659 break;
00660 }
00661 cpl_image_delete(collapsed);
00662 collapsed = NULL;
00663
00664
00665
00666
00667 if (bpm_im_bin != NULL) {
00668
00669 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
00670 errori = cpl_error_set_message(cpl_func,
00671 cpl_error_get_code(),
00672 "Failure for file %d/%d",
00673 i+1, nfiles);
00674 break;
00675 }
00676 if (cpl_detector_interpolate_rejected(prev)) {
00677 errori = cpl_error_set_message(cpl_func,
00678 cpl_error_get_code(),
00679 "Failure for file %d/%d",
00680 i+1, nfiles);
00681 break;
00682 }
00683 }
00684
00685 if (ndestripe > 0)
00686 if(visir_destripe_image(prev, ndestripe,
00687 VISIR_DESTRIPE_DETECT,
00688 VISIR_DESTRIPE_DETECT_THRESHOLD,
00689 morpho_destripe)) {
00690 errori = cpl_error_set_message(cpl_func,
00691 cpl_error_get_code(),
00692 "Failure for file %d/%d",
00693 i+1, nfiles);
00694 break;
00695 }
00696
00697 if (flat_image != NULL) {
00698
00699 if (cpl_image_divide(prev, flat_image)) {
00700 errori = cpl_error_set_message(cpl_func,
00701 cpl_error_get_code(),
00702 "Failure for file %d/%d",
00703 i+1, nfiles);
00704 break;
00705 }
00706 }
00707
00708 if (cpl_imagelist_set(nodded, prev, i/2)) {
00709 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
00710 "Failure for file %d/%d",
00711 i+1, nfiles);
00712 break;
00713 }
00714 prev = NULL;
00715 } else {
00716 prev = collapsed;
00717 collapsed = NULL;
00718 }
00719 } while (0);
00720
00721 if (errori) {
00722 #ifdef _OPENMP
00723
00724
00725 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
00726
00727
00728 cpl_image_delete(prev); prev = NULL;
00729 cpl_image_delete(collapsed); collapsed = NULL;
00730
00731 #pragma omp critical
00732 #endif
00733 didfail = errori;
00734 }
00735 }
00736
00737 error_if(didfail, didfail, "Failed to create %d nodded images from %d "
00738 "files", nnod, nfiles);
00739
00740 tstop = cpl_test_get_walltime();
00741 cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
00742 tstop - tstart);
00743
00744 cpl_vector_delete(nods_vec);
00745 nods_vec = NULL;
00746
00747 cpl_image_delete(flat_image);
00748 flat_image = NULL;
00749
00750 cpl_mask_delete(bpm_im_bin);
00751 bpm_im_bin = NULL;
00752
00753 if (nod_pos != nodding_p) cpl_free(nod_pos);
00754 nod_pos = NULL;
00755
00756 error_if(is_nodding && j != nnod, CPL_ERROR_INCOMPATIBLE_INPUT,
00757 "With nodding exactly half of the images "
00758 "must be on-object, not %d of %d", j, 2*nnod);
00759
00760 if (do_spc_fix) {
00761 const double ksi = visir_parameterlist_get_double(parlist, recipename,
00762 VISIR_PARAM_SPECSKEW);
00763 const double eps = visir_parameterlist_get_double(parlist, recipename,
00764 VISIR_PARAM_VERTARC);
00765 const double delta = visir_parameterlist_get_double(parlist, recipename,
00766 VISIR_PARAM_HORIARC);
00767 const double phi = visir_parameterlist_get_double(parlist, recipename,
00768 VISIR_PARAM_SLITSKEW);
00769 const int doplot = visir_parameterlist_get_int(parlist, recipename,
00770 VISIR_PARAM_PLOT);
00771
00772
00773 skip_if (0);
00774
00775 images = cpl_malloc(nnod * sizeof(cpl_image*));
00776
00777 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
00778
00779 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
00780 phi, ksi, eps, delta, doplot));
00781 }
00782
00783 end_skip;
00784
00785 cpl_msg_set_time_off();
00786
00787 cpl_free(images);
00788 cpl_imagelist_delete(in);
00789
00790 if (nod_pos != nodding_p) cpl_free(nod_pos);
00791 cpl_vector_delete(nods_vec);
00792 cpl_image_delete(bpm_im_int);
00793 cpl_mask_delete(bpm_im_bin);
00794 cpl_image_delete(collapsed);
00795 cpl_image_delete(prev);
00796 if (cpl_error_get_code() && nodded != NULL) {
00797 cpl_imagelist_delete(nodded);
00798 nodded = NULL;
00799 }
00800
00801 return nodded;
00802 }
00803
00804
00851
00852 cpl_image ** visir_img_recombine(const char * recipename,
00853 const cpl_parameterlist * parlist,
00854 const irplib_framelist * rawframes,
00855 const char * badpix,
00856 const char * flat,
00857 cpl_geom_combine combine_mode,
00858 cpl_boolean * pdid_resize,
00859 cpl_boolean do_spc_fix,
00860 double wlen,
00861 visir_spc_resol resol)
00862 {
00863 int nfiles;
00864 int * nod_pos = NULL;
00865 cpl_imagelist * nodded = NULL;
00866 int nnod;
00867 cpl_bivector * offsets_est = NULL;
00868 cpl_bivector * objs = NULL;
00869 cpl_image ** combined = NULL;
00870 const cpl_vector * sigmas = NULL;
00871 double xoff, yoff;
00872 cpl_propertylist * qclist = cpl_propertylist_new();
00873 int i;
00874
00875
00876 bug_if (0);
00877
00878 bug_if (recipename == NULL);
00879 bug_if (parlist == NULL);
00880 bug_if (rawframes == NULL);
00881 bug_if (pdid_resize == NULL);
00882
00883
00884 nfiles = irplib_framelist_get_size(rawframes);
00885
00886
00887 if (nfiles % 2) {
00888 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00889 "ignoring the last of %d file(s)", nfiles);
00890 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00891 "At least two files are required");
00892 nfiles--;
00893 }
00894
00895 skip_if ( nfiles <= 0);
00896
00897
00898 nod_pos = cpl_malloc(nfiles * sizeof(int));
00899
00900
00901 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
00902 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
00903 nod_pos, do_spc_fix, wlen, resol);
00904
00905 skip_if (nodded == NULL);
00906 nnod = cpl_imagelist_get_size(nodded);
00907
00908
00909 if (nnod == 1) {
00910
00911 combined = cpl_malloc(2*sizeof(cpl_image*));
00912 combined[1] = NULL;
00913
00914 combined[0] = cpl_imagelist_unset(nodded, 0);
00915 bug_if (combined[0] == NULL);
00916
00917 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
00918 cpl_image_get_size_y(combined[0]),
00919 CPL_TYPE_INT);
00920 bug_if (combined[1] == NULL);
00921
00922
00923 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
00924
00925 *pdid_resize = CPL_FALSE;
00926
00927 } else {
00928 const double psigmas[] = {5, 2, 1, 0.5};
00929 const char * sval;
00930 const char * offsets;
00931 const char * objects;
00932 int sx, sy, mx, my;
00933 int rej_low, rej_high;
00934 cpl_boolean refine;
00935
00936
00937 refine = visir_parameterlist_get_bool(parlist, recipename,
00938 VISIR_PARAM_REFINE);
00939 skip_if (0);
00940
00941 offsets = visir_parameterlist_get_string(parlist, recipename,
00942 VISIR_PARAM_OFFSETS);
00943 skip_if (0);
00944
00945 objects = visir_parameterlist_get_string(parlist, recipename,
00946 VISIR_PARAM_OBJECTS);
00947 skip_if (0);
00948
00949 sval = visir_parameterlist_get_string(parlist, recipename,
00950 VISIR_PARAM_XCORR);
00951 skip_if (0);
00952
00953 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
00954
00955 sval = visir_parameterlist_get_string(parlist, recipename,
00956 VISIR_PARAM_REJECT);
00957 skip_if (0);
00958
00959 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
00960
00961
00962 cpl_msg_info(cpl_func, "Get the offsets estimation");
00963 if (offsets != NULL && strlen(offsets)) {
00964
00965 offsets_est = cpl_bivector_read(offsets);
00966 skip_if (offsets_est==NULL);
00967
00968 error_if (cpl_bivector_get_size(offsets_est) != nnod,
00969 CPL_ERROR_BAD_FILE_FORMAT, "The offsets file %s must "
00970 "have %d entries, not %d", offsets, nnod,
00971 cpl_bivector_get_size(offsets_est));
00972 } else {
00973 double * offsets_est_x;
00974 double * offsets_est_y;
00975 double xoff0 = 0.0;
00976 double yoff0 = 0.0;
00977
00978
00979 offsets_est = cpl_bivector_new(nnod);
00980 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
00981 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
00982
00983 skip_if (0);
00984
00985 offsets_est_x[0] = 0.0;
00986 offsets_est_y[0] = 0.0;
00987
00988 for (i=0; i < nnod ; i++) {
00989 const cpl_propertylist * plist;
00990
00991
00992 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
00993
00994 plist = irplib_framelist_get_propertylist_const(rawframes,
00995 iframe);
00996 skip_if(plist == NULL);
00997
00998 xoff = visir_pfits_get_cumoffsetx(plist);
00999 yoff = visir_pfits_get_cumoffsety(plist);
01000
01001 skip_if (0);
01002
01003 if (i == 0) {
01004 xoff0 = xoff;
01005 yoff0 = yoff;
01006 } else {
01007
01008 offsets_est_x[i] = xoff0 - xoff;
01009 offsets_est_y[i] = yoff0 - yoff;
01010 }
01011 }
01012 }
01013 cpl_free(nod_pos);
01014 nod_pos = NULL;
01015
01016
01017
01018 if (objects != NULL && strlen(objects) > 0) {
01019 objs = cpl_bivector_read(objects);
01020 any_if ("Could not read objects from %s", objects);
01021 }
01022
01023 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
01024 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
01025 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
01026 CPL_GEOM_FIRST, rej_low, rej_high);
01027
01028 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
01029 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
01030 cpl_bivector_dump(offsets_est, stdout);
01031 }
01032
01033 sigmas = cpl_vector_wrap(4, (double*)psigmas);
01034 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
01035 objs, sigmas, NULL, sx, sy,
01036 mx, my, rej_low, rej_high,
01037 combine_mode);
01038 any_if("Could not recombine the images");
01039
01040 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
01041 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
01042 cpl_image_get_size_y(combined[0])
01043 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
01044 }
01045
01046 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
01047 visir_image_plot("", "t 'The combined image'", "", combined[0]);
01048
01049 end_skip;
01050
01051 cpl_propertylist_delete(qclist);
01052 cpl_free(nod_pos);
01053 cpl_imagelist_delete(nodded);
01054 cpl_bivector_delete(offsets_est);
01055 cpl_bivector_delete(objs);
01056 cpl_vector_unwrap((cpl_vector*)sigmas);
01057
01058 return combined;
01059 }
01060
01061
01084
01085 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
01086 {
01087 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
01088 }
01089
01090
01101
01102 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
01103 {
01104
01105 cpl_image * im_bpm = NULL;
01106 cpl_mask * bpm = NULL;
01107 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
01108
01109
01110 skip_if (0);
01111
01112 skip_if (self == NULL);
01113
01114 if (bpmfile == NULL) {
01115 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
01116 skip_if (0);
01117 } else {
01118
01119
01120 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
01121
01122 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
01123 any_if ("Could not load the bad pixel map %s",
01124 bpmfile ? bpmfile : "<NULL>");
01125
01126 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
01127 skip_if (0);
01128 cpl_image_delete(im_bpm);
01129 im_bpm = NULL;
01130
01131 skip_if (cpl_mask_not(bpm));
01132 }
01133
01134 skip_if (cpl_image_reject_from_mask(self, bpm));
01135
01136 end_skip;
01137
01138 cpl_image_delete(im_bpm);
01139 cpl_mask_delete(bpm);
01140
01141 return cpl_error_get_code();
01142
01143 }
01144
01145
01146
01153
01154 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
01155 {
01156 cpl_imagelist * self = NULL;
01157 int naxis3;
01158
01159
01160 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
01161 CPL_TYPE_INT, CPL_TRUE, 0.0));
01162
01163 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
01164 rawframes,
01165 0));
01166
01167
01168 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
01169 0);
01170
01171 skip_if (self == NULL);
01172
01173 end_skip;
01174
01175 return self;
01176
01177 }
01178
01179
01180
01190
01191 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01192 int pos, cpl_boolean is_interm)
01193 {
01194 cpl_errorstate cleanstate = cpl_errorstate_get();
01195 cpl_imagelist * self = NULL;
01196 cpl_image * image = NULL;
01197 const char * file = NULL;
01198 const cpl_propertylist * plist;
01199 int nchop, naxis3;
01200
01201
01202
01203 skip_if (0);
01204
01205 skip_if (rawframes == NULL);
01206
01207 file = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
01208 skip_if (file == NULL);
01209
01210
01211 plist = irplib_framelist_get_propertylist_const(rawframes, pos);
01212 skip_if (plist == NULL);
01213
01214 naxis3 = visir_pfits_get_naxis3(plist);
01215 nchop = visir_pfits_get_chop_ncycles(plist);
01216
01217 skip_if (0);
01218
01219 if (nchop == 0 && naxis3 == 1 && is_interm) {
01220 self = cpl_imagelist_load(file, CPL_TYPE_FLOAT, 0);
01221 } else {
01222 const char * sval;
01223
01224
01225 const int plane_step = (naxis3 == 2 * nchop + 1) ? 2 : 1;
01226 const cpl_type pixel_type = CPL_TYPE_FLOAT;
01227 int nsize;
01228 int iplane;
01229 int i;
01230
01231
01232 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT,
01233 "CHOP NCYCLES in %s is non-positive (and NAXIS3=%d): %d",
01234 file, naxis3, nchop);
01235
01236 error_if (plane_step == 1 && naxis3 != nchop+2,
01237 CPL_ERROR_BAD_FILE_FORMAT, "NAXIS3=%d and CHOP NCYCLES=%d in "
01238 "%s is not a valid VISIR INTERM+Half-Cycle "
01239 "format", naxis3, nchop, file);
01240
01241 if (plane_step == 1 && nchop > 1)
01242 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01243 "Cycle frame (old CUBE1-format)", file, nchop);
01244
01245
01246 sval = visir_pfits_get_frame_type(plist);
01247 if (sval == NULL) {
01248
01249 visir_error_reset("Could not get FITS key");
01250
01251 } else if (strlen(sval) == 0) {
01252
01253 } else if (plane_step == 1) {
01254 if (strcmp(sval, "CUBE2")==0)
01255 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01256 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01257 " the frame type is really CUBE1", file,
01258 naxis3, nchop);
01259 } else if (nchop > 1) {
01260
01261 if (strcmp(sval, "CUBE1")==0)
01262 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01263 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01264 " the frame type is really CUBE2", file,
01265 naxis3, nchop);
01266 }
01267
01268 self = cpl_imagelist_new();
01269
01270 if (plane_step == 1) {
01271
01272 iplane = is_interm ? 0 : nchop;
01273
01274 nsize = is_interm ? nchop : 1;
01275 } else {
01276
01277 iplane = is_interm ? 1 : 0;
01278 nsize = nchop;
01279 }
01280
01281 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01282
01283 image = cpl_image_load(file, pixel_type, iplane, 0);
01284 skip_if (image == NULL);
01285
01286 skip_if (!is_interm && visir_offset_hcycle(image));
01287
01288 skip_if (cpl_imagelist_set(self, image, i));
01289
01290 image = NULL;
01291 }
01292
01293 skip_if (i < nsize);
01294 }
01295
01296 end_skip;
01297
01298 if (cpl_error_get_code()) {
01299 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01300 "frame(s) from: %s",
01301 is_interm ? "INTERM" : "Half-Cycle",
01302 file);
01303 cpl_image_delete(image);
01304 cpl_imagelist_delete(self);
01305 self = NULL;
01306 }
01307
01308 return self;
01309 }
01310
01311
01314
01338
01339 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01340 int pos)
01341 {
01342 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01343
01344 }
01345
01346
01355
01356 static cpl_image * visir_load_average(const char * file,
01357 const cpl_propertylist * plist)
01358 {
01359 cpl_errorstate cleanstate = cpl_errorstate_get();
01360 cpl_image * self = NULL;
01361 int nchop, naxis3;
01362
01363
01364 skip_if (0);
01365 skip_if (file == NULL);
01366 skip_if (plist == NULL);
01367
01368 naxis3 = visir_pfits_get_naxis3(plist);
01369 nchop = visir_pfits_get_chop_ncycles(plist);
01370
01371 skip_if (0);
01372
01373 if (nchop == 0 && naxis3 == 1) {
01374 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01375 } else {
01376 const char * sval;
01377
01378
01379 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01380
01381
01382 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT, "CHOP NCYCLES in %s "
01383 "is non-positive (and NAXIS3=%d): %d", file, naxis3, nchop);
01384
01385 error_if (plane_offset == 3 && naxis3 != nchop+2,
01386 CPL_ERROR_BAD_FILE_FORMAT, "NAXIS3=%d and CHOP NCYCLES=%d "
01387 "in %s is not a valid VISIR INTERM+Half-Cycle format", naxis3,
01388 nchop, file);
01389
01390 if (plane_offset == 3 && nchop > 1)
01391 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01392 "Cycle frame (old CUBE1-format)", file, nchop);
01393
01394
01395 sval = visir_pfits_get_frame_type(plist);
01396 if (sval == NULL) {
01397
01398 visir_error_reset("Could not get FITS key");
01399
01400 } else if (strlen(sval) == 0) {
01401
01402 } else if (plane_offset == 3) {
01403 if (strcmp(sval, "CUBE2")==0)
01404 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3=%d"
01405 " and CHOP NCYCLES=%d imply a CUBE1. Assuming "
01406 " the frame type is really CUBE1", file,
01407 naxis3, nchop);
01408 } else if (nchop > 1) {
01409
01410 if (strcmp(sval, "CUBE1")==0)
01411 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3=%d"
01412 " and CHOP NCYCLES=%d imply a CUBE2. Assuming "
01413 " the frame type is really CUBE2", file,
01414 naxis3, nchop);
01415 }
01416
01417
01418 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01419
01420 }
01421
01422 skip_if (0);
01423
01424 end_skip;
01425
01426 if (cpl_error_get_code()) {
01427 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01428 "%s", file ? file : "<NULL>");
01429 cpl_image_delete(self);
01430 self = NULL;
01431 }
01432
01433 return self;
01434 }
01435
01436
01459
01460 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01461 {
01462 cpl_image * iprev;
01463 cpl_image * image;
01464 const int n = cpl_imagelist_get_size(self);
01465 int i;
01466
01467
01468 skip_if (0);
01469
01470 if (n == 1) return CPL_ERROR_NONE;
01471
01472 iprev = cpl_imagelist_get(self, n - 1);
01473
01474 skip_if (0);
01475
01476 skip_if (cpl_image_multiply_scalar(iprev, n));
01477
01478
01479 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01480 image = cpl_imagelist_get(self, i-1);
01481
01482 skip_if (0);
01483
01484 skip_if (cpl_image_multiply_scalar(image, i));
01485
01486 skip_if (cpl_image_subtract(iprev, image));
01487
01488 }
01489
01490 image = cpl_imagelist_get(self, 0);
01491
01492 skip_if (0);
01493
01494 skip_if (cpl_image_subtract(iprev, image));
01495
01496 end_skip;
01497
01498 return cpl_error_get_code();
01499 }
01500
01501
01514
01515 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
01516 {
01517 cpl_image * med_filt = NULL;
01518 cpl_mask * bpm = NULL;
01519 cpl_mask * kernel = cpl_mask_new(3, 3);
01520 double mean, stdev;
01521 double low_thresh, high_thresh;
01522 const int nx = cpl_image_get_size_x(glitchy);
01523 const int ny = cpl_image_get_size_y(glitchy);
01524 int i;
01525
01526
01527 double factor1 = 3.0;
01528 double factor2 = 10.0;
01529 const int niterations = 5;
01530 const double median_corr = 1.5;
01531
01532 bug_if (0);
01533
01534
01535 bug_if(cpl_mask_not(kernel));
01536
01537
01538 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
01539 cpl_image_get_size_y(glitchy),
01540 cpl_image_get_type(glitchy));
01541 bug_if(med_filt == NULL);
01542 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
01543 CPL_BORDER_FILTER));
01544 cpl_mask_delete(kernel);
01545 kernel = NULL;
01546
01547
01548 skip_if (cpl_image_subtract(glitchy, med_filt));
01549
01550
01551 for (i=0 ; i < niterations ; i++) {
01552
01553 mean = cpl_image_get_mean(glitchy);
01554 stdev = cpl_image_get_stdev(glitchy);
01555
01556 skip_if (0);
01557
01558
01559 low_thresh = mean - factor1 * stdev;
01560 high_thresh = mean + factor1 * stdev;
01561
01562
01563 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01564 skip_if (cpl_mask_not(bpm));
01565 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01566 cpl_mask_delete(bpm);
01567 bpm = NULL;
01568
01569
01570 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01571 }
01572
01573
01574
01575 mean = cpl_image_get_mean(glitchy);
01576 stdev = cpl_image_get_stdev(glitchy) * median_corr;
01577
01578 skip_if (0);
01579
01580 low_thresh = mean - factor2 * stdev;
01581 high_thresh = mean + factor2 * stdev;
01582
01583 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01584 skip_if (cpl_mask_not(bpm));
01585 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01586 cpl_mask_delete(bpm);
01587 bpm = NULL;
01588
01589
01590 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01591
01592
01593 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01594 skip_if (cpl_image_accept_all(glitchy));
01595
01596
01597 skip_if (cpl_image_add(glitchy, med_filt));
01598
01599 end_skip;
01600
01601 cpl_image_delete(med_filt);
01602 cpl_mask_delete(bpm);
01603 cpl_mask_delete(kernel);
01604
01605 return cpl_error_get_code();
01606 }
01607
01608
01619
01620 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
01621 {
01622 cpl_vector * medians = NULL;
01623 cpl_vector * stdevs = NULL;
01624 cpl_vector * selection = NULL;
01625 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01626 const double threshold = 3;
01627 const int nima = cpl_imagelist_get_size(in);
01628 int i;
01629
01630
01631
01632 skip_if (0);
01633
01634 if (nima <= 3) return CPL_ERROR_NONE;
01635
01636
01637 medians = cpl_vector_new(nima);
01638 stdevs = cpl_vector_new(nima);
01639
01640
01641 for (i=0 ; i < nima ; i++) {
01642 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01643 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01644
01645 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01646 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
01647 cpl_stats_delete(stats);
01648 }
01649
01650 skip_if( 0);
01651
01652
01653 mean_medians = cpl_vector_get_mean(medians);
01654 stdev_medians = cpl_vector_get_stdev(medians);
01655 mean_stdevs = cpl_vector_get_mean(stdevs);
01656 stdev_stdevs = cpl_vector_get_stdev(stdevs);
01657
01658 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01659 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
01660
01661 stdev_medians *= threshold;
01662 stdev_stdevs *= threshold;
01663
01664
01665 selection = cpl_vector_new(nima);
01666 skip_if( cpl_vector_fill(selection, 0));
01667 for (i=0 ; i < nima ; i++) {
01668 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01669 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
01670
01671 cpl_vector_set(selection, i, -1);
01672 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01673 i+1, nima, stdev_medians, stdev_stdevs);
01674 }
01675
01676
01677 cpl_imagelist_erase(in, selection);
01678
01679 end_skip;
01680
01681 cpl_vector_delete(medians);
01682 cpl_vector_delete(stdevs);
01683
01684 cpl_vector_delete(selection);
01685
01686 return CPL_ERROR_NONE;
01687
01688 }
01689
01690
01699
01700 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
01701 {
01702 double minval;
01703
01704
01705 skip_if (0);
01706
01707 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
01708
01709 minval = cpl_image_get_min(hcycle);
01710
01711
01712 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
01713
01714 end_skip;
01715
01716 return CPL_ERROR_NONE;
01717 }
01718
01719
01731
01732 static
01733 cpl_image ** visir_img_collapse_beam_four(cpl_propertylist * qclist,
01734 const cpl_image * self,
01735 const cpl_image * inverse,
01736 double eccmax,
01737 double pthrow,
01738 const cpl_propertylist * plist)
01739 {
01740
01741 cpl_image ** combined = NULL;
01742 const int nx = cpl_image_get_size_x(self);
01743 const int ny = cpl_image_get_size_y(self);
01744 const cpl_type type = cpl_image_get_type(self);
01745 cpl_imagelist * list4 = cpl_imagelist_new();
01746 cpl_image * swrap = type == CPL_TYPE_DOUBLE
01747 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)self))
01748 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)self));
01749 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
01750 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
01751 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
01752 cpl_bivector * offs = cpl_bivector_new(4);
01753 double * x4 = cpl_bivector_get_x_data(offs);
01754 double * y4 = cpl_bivector_get_y_data(offs);
01755 double pos_x, pos_y;
01756 int i;
01757
01758 skip_if (0);
01759
01760 skip_if(plist == NULL);
01761
01762 skip_if(visir_img_find_beam_four(qclist, self, inverse, eccmax, pthrow,
01763 x4, y4));
01764
01765
01766 for (i = 1; i < 4; i++) {
01767 x4[i] = x4[0] - x4[i];
01768 y4[i] = y4[0] - y4[i];
01769 }
01770
01771 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
01772 x4[0]));
01773 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
01774 y4[0]));
01775 x4[0] = y4[0] = 0.0;
01776
01777 bug_if(cpl_imagelist_set(list4, (cpl_image*)self, 0));
01778 bug_if(cpl_imagelist_set(list4, swrap, 1));
01779 bug_if(cpl_imagelist_set(list4, (cpl_image*)inverse, 2));
01780 bug_if(cpl_imagelist_set(list4, iwrap, 3));
01781
01782 combined = cpl_geom_img_offset_saa(list4, offs, CPL_KERNEL_DEFAULT, 0, 0,
01783 CPL_GEOM_FIRST, &pos_x, &pos_y);
01784
01785 skip_if(combined == NULL);
01786
01787 end_skip;
01788
01789 cpl_bivector_delete(offs);
01790 for (i = cpl_imagelist_get_size(list4) - 1; i >= 0; i--) {
01791 (void)cpl_imagelist_unset(list4, i);
01792 }
01793 cpl_imagelist_delete(list4);
01794 (void)cpl_image_unwrap(swrap);
01795 (void)cpl_image_unwrap(iwrap);
01796 if (cpl_error_get_code() && combined != NULL) {
01797 cpl_image_delete(combined[0]);
01798 cpl_image_delete(combined[1]);
01799 cpl_free(combined);
01800 }
01801
01802 return combined;
01803 }
01804
01805
01817
01818 static
01819 cpl_error_code visir_img_find_beam_four(cpl_propertylist * qclist,
01820 const cpl_image * self,
01821 const cpl_image * inverse,
01822 double eccmax,
01823 double pthrow,
01824 double x4[],
01825 double y4[])
01826 {
01827
01828 cpl_errorstate cleanstate = cpl_errorstate_get();
01829 cpl_apertures * appos = NULL;
01830 cpl_apertures * apneg = NULL;
01831 const double psigmas[] = {2.0, 1.0, 0.5};
01832 const int nsigmas = sizeof(psigmas)/sizeof(double);
01833 int isigma;
01834 int iappos2[] = {1, 2};
01835 int iapneg2[] = {1, 2};
01836
01837 bug_if(0);
01838 skip_if(self == NULL);
01839 skip_if(qclist == NULL);
01840 skip_if(pthrow <= 0.0);
01841 skip_if(x4 == NULL);
01842 skip_if(y4 == NULL);
01843
01844 cpl_msg_info(cpl_func, "Detecting the 4-beam object with %g pixel throw "
01845 "using %d sigma-levels ranging from %g down to %g", pthrow,
01846 nsigmas, psigmas[0], psigmas[nsigmas-1]);
01847
01848 bug_if(0);
01849 for (isigma = 0; isigma < nsigmas; isigma++) {
01850 int npos = 0;
01851 int nneg = 0;
01852
01853
01854 cpl_apertures_delete(appos);
01855 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
01856
01857 if (appos != NULL) {
01858 npos = cpl_apertures_get_size(appos);
01859 }
01860
01861
01862
01863 cpl_apertures_delete(apneg);
01864 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
01865 if (apneg != NULL) {
01866 nneg = cpl_apertures_get_size(apneg);
01867 }
01868
01869 cpl_msg_info(cpl_func, "Found %d positive (need 2) and %d negative "
01870 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
01871 psigmas[isigma], 1+isigma, nsigmas);
01872
01873 if (eccmax > 0.0) {
01874 int ipos1;
01875 double eccbest = eccmax;
01876 double eccmin = DBL_MAX;
01877 double fluxbest = 0.0;
01878 double fluxecc = DBL_MAX;
01879 cpl_boolean is_first = CPL_TRUE;
01880
01881 #ifdef _OPENMP
01882 #pragma omp parallel for private(ipos1)
01883 #endif
01884 for (ipos1 = 2; ipos1 <= npos; ipos1++) {
01885 int ipos2, ineg1, ineg2;
01886 for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
01887 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
01888 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
01889 cpl_boolean swappos, swapneg;
01890 const double ecc
01891 = visir_img_check_box(appos, ipos1, ipos2,
01892 apneg, ineg1, ineg2,
01893 pthrow, &swappos,
01894 &swapneg);
01895
01896 const double flux
01897 = cpl_apertures_get_flux(appos, ipos1)
01898 + cpl_apertures_get_flux(appos, ipos2)
01899 + cpl_apertures_get_flux(apneg, ineg1)
01900 + cpl_apertures_get_flux(apneg, ineg2);
01901
01902
01903 if (ecc < 0.0 || flux <= 0.0 ||
01904 !cpl_errorstate_is_equal(cleanstate)) {
01905 irplib_error_recover(cleanstate, "Invalid 4-"
01906 "object (%d & %d of %d, "
01907 "%d & %d of %d)",
01908 ipos2, ipos1, npos,
01909 ineg2, ineg1, nneg);
01910 continue;
01911 }
01912
01913 if (ecc < eccmin)
01914 #ifdef _OPENMP
01915 #pragma omp critical
01916 #endif
01917 {
01918 eccmin = ecc;
01919 fluxecc = flux;
01920 }
01921
01922 if (eccmax <= ecc) continue;
01923
01924 if (is_first || ecc * fluxbest < eccbest * flux)
01925 #ifdef _OPENMP
01926 #pragma omp critical
01927 #endif
01928 {
01929 if (is_first) {
01930 is_first = CPL_FALSE;
01931 cpl_msg_info(cpl_func, "Found 4 object "
01932 "positions with throw-"
01933 "scaled eccentricity %g "
01934 "and flux %g", ecc, flux);
01935 } else {
01936 cpl_msg_info(cpl_func, "Found 4 object "
01937 "positions with throw-"
01938 "scaled eccentricity %g "
01939 "< %g and/or flux %g > %g",
01940 ecc, eccbest, flux, fluxbest);
01941 }
01942 eccbest = ecc;
01943 fluxbest = flux;
01944 iappos2[0] = swappos ? ipos2 : ipos1;
01945 iappos2[1] = swappos ? ipos1 : ipos2;
01946 iapneg2[0] = swapneg ? ineg2 : ineg1;
01947 iapneg2[1] = swapneg ? ineg1 : ineg2;
01948 }
01949 }
01950 }
01951 }
01952 }
01953 if (eccbest < eccmax) {
01954 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
01955 "ECCENTRICITY", eccbest));
01956
01957 break;
01958 }
01959 if (eccmin < DBL_MAX) {
01960 cpl_msg_info(cpl_func, "Found 4 sigma-%g object positions with "
01961 "too large throw-scaled eccentricity %g >= %g and "
01962 "flux %g", psigmas[isigma], eccmin, eccmax,
01963 fluxecc);
01964 }
01965 } else if (npos >= 2 && nneg >= 2) {
01966 cpl_apertures_sort_by_flux(appos);
01967 cpl_apertures_sort_by_flux(apneg);
01968 break;
01969 }
01970
01971 if (isigma + 1 < nsigmas) {
01972 irplib_error_recover(cleanstate, "4-Beam positions not found among "
01973 "%d postive and %d negative object(s) at "
01974 "sigma=%g, (%d of %d)", npos, nneg,
01975 psigmas[isigma], 1+isigma, nsigmas);
01976 }
01977 }
01978
01979 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
01980 "4-Beam positions not found w. %d sigma(s) down to %g",
01981 nsigmas, psigmas[nsigmas - 1]);
01982
01983 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
01984 cpl_apertures_dump(appos, stdout);
01985 cpl_apertures_dump(apneg, stdout);
01986 }
01987
01988 x4[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
01989 y4[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
01990 x4[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
01991 y4[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
01992
01993 x4[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
01994 y4[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
01995 x4[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
01996 y4[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
01997
01998 cpl_msg_info(cpl_func, "Centroid of positive object 1 [pixel]: %g %g",
01999 x4[0], y4[0]);
02000 cpl_msg_info(cpl_func, "Centroid of positive object 2 [pixel]: %g %g",
02001 x4[1], y4[1]);
02002
02003 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02004 x4[2], y4[2]);
02005 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02006 x4[3], y4[3]);
02007
02008 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02009 pthrow);
02010 cpl_msg_info(cpl_func, "Object Pos -> Pos x/y-distance [pixel]: %g %g",
02011 x4[1] - x4[0], y4[1] - y4[0]);
02012 cpl_msg_info(cpl_func, "Object Neg -> Neg x/y-distance [pixel]: %g %g",
02013 x4[3] - x4[2], y4[3] - y4[2]);
02014 cpl_msg_info(cpl_func, "Object Pos -> Pos angle [degrees]: %g",
02015 atan2(y4[1] - y4[0], x4[1] - x4[0]) * CPL_MATH_DEG_RAD);
02016 cpl_msg_info(cpl_func, "Object Neg -> Neg angle [degrees]: %g",
02017 atan2(y4[3] - y4[2], x4[3] - x4[2]) * CPL_MATH_DEG_RAD);
02018
02019 end_skip;
02020
02021 cpl_apertures_delete(appos);
02022 cpl_apertures_delete(apneg);
02023
02024 return cpl_error_get_code();
02025 }
02026
02027
02039
02040 static
02041 cpl_image ** visir_img_collapse_beam_three(cpl_propertylist * qclist,
02042 const cpl_image * self,
02043 const cpl_image * inverse,
02044 double eccmax,
02045 double pthrow,
02046 const cpl_propertylist * plist)
02047 {
02048
02049 cpl_image ** combined = NULL;
02050 const int nx = cpl_image_get_size_x(self);
02051 const int ny = cpl_image_get_size_y(self);
02052 const cpl_type type = cpl_image_get_type(self);
02053 cpl_imagelist * list3 = cpl_imagelist_new();
02054 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02055 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02056 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02057 cpl_bivector * offs = cpl_bivector_new(3);
02058 double * x3 = cpl_bivector_get_x_data(offs);
02059 double * y3 = cpl_bivector_get_y_data(offs);
02060 double pos_x, pos_y;
02061 int i;
02062
02063 skip_if (0);
02064
02065 skip_if(plist == NULL);
02066
02067 skip_if(visir_img_find_beam_three(qclist, self, inverse, eccmax, pthrow,
02068 x3, y3));
02069
02070
02071 for (i = 1; i < 3; i++) {
02072 x3[i] = x3[0] - x3[i];
02073 y3[i] = y3[0] - y3[i];
02074 }
02075 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02076 x3[0]));
02077 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02078 y3[0]));
02079
02080 x3[0] = y3[0] = 0.0;
02081
02082 bug_if(cpl_imagelist_set(list3, (cpl_image*)self, 0));
02083 bug_if(cpl_imagelist_set(list3, (cpl_image*)inverse, 1));
02084 bug_if(cpl_imagelist_set(list3, iwrap, 2));
02085
02086 combined = cpl_geom_img_offset_saa(list3, offs, CPL_KERNEL_DEFAULT, 0, 0,
02087 CPL_GEOM_FIRST, &pos_x, &pos_y);
02088
02089 skip_if(combined == NULL);
02090
02091 end_skip;
02092
02093 cpl_bivector_delete(offs);
02094 for (i = cpl_imagelist_get_size(list3) - 1; i >= 0; i--) {
02095 (void)cpl_imagelist_unset(list3, i);
02096 }
02097 cpl_imagelist_delete(list3);
02098 (void)cpl_image_unwrap(iwrap);
02099 if (cpl_error_get_code() && combined != NULL) {
02100 cpl_image_delete(combined[0]);
02101 cpl_image_delete(combined[1]);
02102 cpl_free(combined);
02103 }
02104
02105 return combined;
02106 }
02107
02108
02109
02122
02123 static
02124 cpl_error_code visir_img_find_beam_three(cpl_propertylist * qclist,
02125 const cpl_image * self,
02126 const cpl_image * inverse,
02127 double eccmax,
02128 double pthrow,
02129 double x3[],
02130 double y3[])
02131 {
02132
02133 cpl_errorstate cleanstate = cpl_errorstate_get();
02134 cpl_apertures * appos = NULL;
02135 cpl_apertures * apneg = NULL;
02136 const double psigmas[] = {2.0, 1.0, 0.5};
02137 const int nsigmas = sizeof(psigmas)/sizeof(double);
02138 int isigma;
02139 int iappos [] = {1};
02140 int iapneg2[] = {1, 2};
02141
02142 bug_if(0);
02143 skip_if(self == NULL);
02144 skip_if(qclist == NULL);
02145 skip_if(pthrow <= 0.0);
02146 skip_if(eccmax < 0.0);
02147 skip_if(x3 == NULL);
02148 skip_if(y3 == NULL);
02149
02150
02151 cpl_msg_info(cpl_func, "Detecting the 3-beam object with %g pixel throw "
02152 "using %d sigma-levels ranging from %g down to %g", pthrow,
02153 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02154
02155 bug_if(0);
02156 for (isigma = 0; isigma < nsigmas; isigma++) {
02157 int npos = 0;
02158 int nneg = 0;
02159
02160
02161 cpl_apertures_delete(appos);
02162 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02163
02164 if (appos != NULL) {
02165 npos = cpl_apertures_get_size(appos);
02166 }
02167
02168
02169
02170 cpl_apertures_delete(apneg);
02171 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02172 if (apneg != NULL) {
02173 nneg = cpl_apertures_get_size(apneg);
02174 }
02175
02176 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
02177 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02178 psigmas[isigma], 1+isigma, nsigmas);
02179
02180 if (eccmax > 0.0) {
02181 int ipos;
02182 double eccbest = eccmax;
02183 double eccmin = DBL_MAX;
02184 double fluxbest = 0.0;
02185 double fluxecc = DBL_MAX;
02186 cpl_boolean is_first = CPL_TRUE;
02187
02188 #ifdef _OPENMP
02189 #pragma omp parallel for private(ipos)
02190 #endif
02191 for (ipos = 1; ipos <= npos; ipos++) {
02192 int ineg1, ineg2;
02193 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
02194 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02195 cpl_boolean swapnegh, swapnegv;
02196 const double ecch
02197 = visir_img_check_align(appos, ipos, apneg, ineg1,
02198 ineg2, pthrow, CPL_TRUE,
02199 &swapnegh);
02200 const double eccv
02201 = visir_img_check_align(appos, ipos, apneg, ineg1,
02202 ineg2, pthrow, CPL_FALSE,
02203 &swapnegv);
02204 const double ecc = ecch < eccv ? ecch : eccv;
02205 const cpl_boolean swapneg = ecch < eccv
02206 ? swapnegh : swapnegv;
02207
02208 const double flux
02209 = cpl_apertures_get_flux(appos, ipos)
02210 + cpl_apertures_get_flux(apneg, ineg1)
02211 + cpl_apertures_get_flux(apneg, ineg2);
02212
02213
02214 if (ecc < 0.0 || flux <= 0.0 ||
02215 !cpl_errorstate_is_equal(cleanstate)) {
02216 irplib_error_recover(cleanstate, "Invalid 3-"
02217 "object (%d of %d, "
02218 "%d & %d of %d)",
02219 ipos, npos,
02220 ineg2, ineg1, nneg);
02221 continue;
02222 }
02223
02224 if (ecc < eccmin)
02225 #ifdef _OPENMP
02226 #pragma omp critical
02227 #endif
02228 {
02229 eccmin = ecc;
02230 fluxecc = flux;
02231 }
02232
02233 if (eccmax <= ecc) continue;
02234
02235 if (is_first || ecc * fluxbest < eccbest * flux)
02236 #ifdef _OPENMP
02237 #pragma omp critical
02238 #endif
02239 {
02240 if (is_first) {
02241 is_first = CPL_FALSE;
02242 cpl_msg_info(cpl_func, "Found 3 object posi"
02243 "tions with throw-scaled (ver"
02244 "tical/horizontal) eccentrici"
02245 "ty %g/%g and flux %g", eccv,
02246 ecch, flux);
02247 } else {
02248 cpl_msg_info(cpl_func, "Found 3 object posi"
02249 "tions with throw-scaled (ver"
02250 "tical/horizontal) eccentrici"
02251 "ty %g/%g < %g and/or flux %g "
02252 "> %g", eccv, ecch, eccbest,
02253 flux, fluxbest);
02254 }
02255 eccbest = ecc;
02256 fluxbest = flux;
02257 iappos[0] = ipos;
02258 iapneg2[0] = swapneg ? ineg2 : ineg1;
02259 iapneg2[1] = swapneg ? ineg1 : ineg2;
02260 }
02261 }
02262 }
02263 }
02264 if (eccbest < eccmax) {
02265 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02266 "ECCENTRICITY", eccbest));
02267 break;
02268 }
02269 if (eccmin < DBL_MAX) {
02270 cpl_msg_info(cpl_func, "Found 3 sigma-%g object positions with "
02271 "too large throw-scaled eccentricity %g >= %g and "
02272 "flux %g", psigmas[isigma], eccmin, eccmax,
02273 fluxecc);
02274 }
02275 } else if (npos >= 1 && nneg >= 2) {
02276 cpl_apertures_sort_by_flux(appos);
02277 cpl_apertures_sort_by_flux(apneg);
02278 break;
02279 }
02280
02281 if (isigma + 1 < nsigmas) {
02282 irplib_error_recover(cleanstate, "3-Beam positions not found among "
02283 "%d postive and %d negative object(s) at "
02284 "sigma=%g, (%d of %d)", npos, nneg,
02285 psigmas[isigma], 1+isigma, nsigmas);
02286 }
02287 }
02288
02289 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02290 "3-Beam positions not found w. %d sigma(s) down to %g",
02291 nsigmas, psigmas[nsigmas - 1]);
02292
02293 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02294 cpl_apertures_dump(appos, stdout);
02295 cpl_apertures_dump(apneg, stdout);
02296 }
02297
02298 x3[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
02299 y3[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
02300
02301 x3[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02302 y3[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02303 x3[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02304 y3[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02305
02306 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
02307 x3[0], y3[0]);
02308
02309 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02310 x3[1], y3[1]);
02311 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02312 x3[2], y3[2]);
02313
02314 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02315 pthrow);
02316 cpl_msg_info(cpl_func, "Object Neg1 -> Pos x/y-distance [pixel]: %g %g",
02317 x3[2] - x3[0], y3[2] - y3[0]);
02318 cpl_msg_info(cpl_func, "Object Pos -> Neg2 x/y-distance [pixel]: %g %g",
02319 x3[0] - x3[1], y3[0] - y3[1]);
02320
02321 end_skip;
02322
02323 cpl_apertures_delete(appos);
02324 cpl_apertures_delete(apneg);
02325
02326 return cpl_error_get_code();
02327 }
02328
02329
02330
02331
02350
02351 double visir_img_check_box(const cpl_apertures * appos,
02352 int ipos1, int ipos2,
02353 const cpl_apertures * apneg,
02354 int ineg1, int ineg2, double ssize,
02355 cpl_boolean * pswapp, cpl_boolean * pswapn)
02356 {
02357
02358
02359
02360
02361 const double xp1 = cpl_apertures_get_centroid_x(appos, ipos1);
02362 const double xp2 = cpl_apertures_get_centroid_x(appos, ipos2);
02363 const double yp1 = cpl_apertures_get_centroid_y(appos, ipos1);
02364 const double yp2 = cpl_apertures_get_centroid_y(appos, ipos2);
02365
02366
02367 const double xpl = xp1 < xp2 ? xp1 : xp2;
02368 const double ypl = xp1 < xp2 ? yp1 : yp2;
02369
02370
02371 const double xpr = xp1 < xp2 ? xp2 : xp1;
02372 const double ypr = xp1 < xp2 ? yp2 : yp1;
02373
02374
02375 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
02376 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
02377 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
02378 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
02379
02380
02381 const double xnl = xn1 < xn2 ? xn1 : xn2;
02382 const double ynl = xn1 < xn2 ? yn1 : yn2;
02383
02384
02385 const double xnr = xn1 < xn2 ? xn2 : xn1;
02386 const double ynr = xn1 < xn2 ? yn2 : yn1;
02387
02388 const double lx1 = xnr - xpl;
02389 const double lx2 = xpr - xnl;
02390 const double ly1 = ypl - ynl;
02391 const double ly2 = ynr - ypr;
02392
02393 const double dx1 = lx1 - ssize;
02394 const double dx2 = lx2 - ssize;
02395 const double dy1 = ly1 - ssize;
02396 const double dy2 = ly2 - ssize;
02397
02398 const double ey1 = ynr - ypl;
02399 const double ey2 = ypr - ynl;
02400 const double ex1 = xpl - xnl;
02401 const double ex2 = xpr - xnr;
02402
02403 const double ok = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
02404 ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
02405
02406 double result = -1.0;
02407
02408 skip_if(0);
02409
02410 skip_if(pswapp == NULL);
02411 skip_if(pswapn == NULL);
02412 skip_if(appos == apneg);
02413 skip_if(ipos1 == ipos2);
02414 skip_if(ineg1 == ineg2);
02415
02416 skip_if(ssize <= 0.0);
02417
02418 *pswapp = xp1 < xp2 ? CPL_FALSE : CPL_TRUE;
02419 *pswapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
02420
02421 result = ok/ssize;
02422
02423 end_skip;
02424
02425 return result;
02426
02427 }
02428
02429
02430
02449
02450 double visir_img_check_align(const cpl_apertures * appos, int ipos,
02451 const cpl_apertures * apneg, int ineg1, int ineg2,
02452 double ssize, cpl_boolean is_hor,
02453 cpl_boolean * pswapn)
02454 {
02455
02456
02457
02458
02459 const double xp = cpl_apertures_get_centroid_x(appos, ipos);
02460 const double yp = cpl_apertures_get_centroid_y(appos, ipos);
02461
02462
02463 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
02464 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
02465 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
02466 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
02467
02468 double result = -1.0;
02469
02470 double ok;
02471
02472 cpl_boolean swapn;
02473
02474 if (is_hor) {
02475
02476 const double xnl = xn1 < xn2 ? xn1 : xn2;
02477 const double ynl = xn1 < xn2 ? yn1 : yn2;
02478
02479
02480 const double xnr = xn1 < xn2 ? xn2 : xn1;
02481 const double ynr = xn1 < xn2 ? yn2 : yn1;
02482
02483 const double d1 = xnr - xp - ssize;
02484 const double d2 = xp - xnl - ssize;
02485
02486 const double e1 = ynr - yp;
02487 const double e2 = yp - ynl;
02488
02489 swapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
02490
02491 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
02492
02493 } else {
02494
02495 const double xnl = yn1 < yn2 ? xn1 : xn2;
02496 const double ynl = yn1 < yn2 ? yn1 : yn2;
02497
02498
02499 const double xnr = yn1 < yn2 ? xn2 : xn1;
02500 const double ynr = yn1 < yn2 ? yn2 : yn1;
02501
02502 const double d1 = ynr - yp - ssize;
02503 const double d2 = yp - ynl - ssize;
02504
02505 const double e1 = xnr - xp;
02506 const double e2 = xp - xnl;
02507
02508 swapn = yn1 < yn2 ? CPL_FALSE : CPL_TRUE;
02509
02510 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
02511
02512 }
02513
02514 skip_if(0);
02515
02516 skip_if(pswapn == NULL);
02517 skip_if(appos == apneg);
02518 skip_if(ineg1 == ineg2);
02519
02520 skip_if(ssize <= 0.0);
02521
02522 *pswapn = swapn;
02523
02524 result = ok/ssize;
02525
02526 end_skip;
02527
02528 return result;
02529
02530 }
02531
02532 #include "visir_destripe.c"