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
00039 #ifndef CPL_SIZE_FORMAT
00040 #define CPL_SIZE_FORMAT "d"
00041 #define cpl_size int
00042 #endif
00043
00044
00045 #include "visir_utils.h"
00046 #include "visir_pfits.h"
00047 #include "visir_parameter.h"
00048 #include "visir_pfits.h"
00049 #include "visir_spc_distortion.h"
00050 #include "visir_inputs.h"
00051 #include "irplib_framelist.h"
00052 #include "irplib_wcs.h"
00053
00054 #include <string.h>
00055 #include <math.h>
00056 #include <float.h>
00057 #include <assert.h>
00058
00059
00060
00061
00062
00063 #ifndef VISIR_DESTRIPE_DETECT
00064 #define VISIR_DESTRIPE_DETECT (3.5 * 1.64)
00065 #endif
00066
00067 #ifndef VISIR_DESTRIPE_DETECT_THRESHOLD
00068 #define VISIR_DESTRIPE_DETECT_THRESHOLD 1.3
00069 #endif
00070
00071 #define VISIR_SECS_PER_DAY (24 * 3600)
00072
00073 typedef enum {
00074 VISIR_CUBE1,
00075 VISIR_CUBE2
00076 } visir_cube_type;
00077
00078
00079
00080
00081
00082
00083 #include "visir_destripe.h"
00084
00085 static cpl_image * visir_load_average(const char *,
00086 const cpl_propertylist *);
00087 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00088 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00089 static cpl_error_code visir_rem_glitch(cpl_image *);
00090 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00091 static cpl_error_code visir_offset_hcycle(cpl_image *);
00092
00093 static cpl_image ** visir_img_collapse_beam_four(cpl_propertylist *,
00094 const cpl_image *,
00095 const cpl_image *,
00096 double, double,
00097 const cpl_propertylist *);
00098
00099 static cpl_image ** visir_img_collapse_beam_three(cpl_propertylist *,
00100 const cpl_image *,
00101 const cpl_image *,
00102 double, double,
00103 const cpl_propertylist *);
00104
00105
00106 static cpl_error_code visir_img_find_beam_three(cpl_propertylist *,
00107 const cpl_image *,
00108 const cpl_image *,
00109 double, double,
00110 double *,
00111 double *);
00112
00113 static cpl_error_code visir_img_find_beam_four(cpl_propertylist *,
00114 const cpl_image *,
00115 const cpl_image *,
00116 double, double,
00117 double *,
00118 double *);
00119
00120 static cpl_error_code visir_get_type(const irplib_framelist *, int,
00121 visir_cube_type *, int *, int *);
00122
00123
00124
00128
00129
00133
00146
00147
00148 static
00149 cpl_error_code visir_load_cube2_split_(cpl_imagelist * alist, cpl_imagelist * blist,
00150 cpl_imagelist * packed, cpl_image * prevd)
00151 {
00152
00153 int naxis3 = cpl_imagelist_get_size(packed);
00154 int prevd_insert_pos = cpl_imagelist_get_size(blist);
00155
00156 bug_if(alist == NULL);
00157 bug_if(blist == NULL);
00158
00159
00160 if (prevd)
00161 cpl_imagelist_set(blist, prevd, prevd_insert_pos);
00162
00163
00164 for (int i = 0; i < naxis3/2; i++) {
00165 cpl_image * aimage = cpl_imagelist_unset(packed, 0);
00166 cpl_image * dimage = cpl_imagelist_unset(packed, 0);
00167
00168 cpl_imagelist_set(alist, aimage, cpl_imagelist_get_size(alist));
00169 cpl_imagelist_set(blist, dimage, cpl_imagelist_get_size(blist));
00170
00171 }
00172
00173 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00174
00175
00176 bug_if(visir_imagelist_unpack_interm(blist));
00177
00178
00179 if (prevd)
00180 cpl_imagelist_unset(blist, prevd_insert_pos);
00181
00182 for (int i = 0; i < naxis3/2; i++) {
00183 const cpl_image * aimage = cpl_imagelist_get_const(alist, i);
00184 const cpl_image * dimage = cpl_imagelist_get_const(blist, i);
00185
00186 cpl_image * bimage = cpl_image_subtract_create(aimage, dimage);
00187
00188
00189 bug_if(cpl_imagelist_set(blist, bimage, i));
00190
00191 }
00192
00193 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00194
00195 end_skip;
00196
00197 return cpl_error_get_code();
00198
00199 }
00200
00201
00202
00214
00215 static cpl_imagelist * load_range(const char * filename,
00216 cpl_type im_type,
00217 int pstart,
00218 int pend)
00219 {
00220 int selfsize = 0;
00221 cpl_imagelist * self = cpl_imagelist_new();
00222
00223 for (int iplane = pstart; iplane < pend; iplane++) {
00224 cpl_image * image = cpl_image_load(filename, im_type, iplane, 0);
00225
00226 if (image == NULL) break;
00227
00228 if (cpl_imagelist_set(self, image, selfsize)) {
00229 cpl_image_delete(image);
00230 break;
00231 }
00232
00233 selfsize++;
00234 }
00235 return self;
00236 }
00237
00238
00239
00262
00263 cpl_error_code visir_load_cube2_split(cpl_imagelist * alist, cpl_imagelist * blist,
00264 const irplib_framelist * rawframes, int pos,
00265 const int planestart, const int planeend)
00266 {
00267
00268 cpl_imagelist * packed = NULL;
00269 const char * file
00270 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
00271 int naxis3, nchop;
00272 visir_cube_type cube_type;
00273 int pend;
00274 cpl_image * prevd = NULL;
00275
00276 skip_if(0);
00277
00278 (void)visir_get_type(rawframes, pos, &cube_type, &naxis3, &nchop);
00279
00280
00281
00282 error_if(planestart % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
00283 "Plane start %d wrong. It must be even.", planestart);
00284 error_if(planeend < naxis3 && planeend % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
00285 "Plane end %d wrong. It must be even if not larger naxis3=%d",
00286 planeend, naxis3);
00287
00288 any_if("Cannot split non-CUBE2 frame %d/%d in %s", 1+pos,
00289 irplib_framelist_get_size(rawframes), file);
00290 bug_if(alist == NULL);
00291 bug_if(blist == NULL);
00292
00293 error_if(cube_type != VISIR_CUBE2, CPL_ERROR_INCOMPATIBLE_INPUT, "Cannot "
00294 "split non-CUBE2 frame %d/%d w. NAXIS3=%d, NCYCLES=%d in %s",
00295 1+pos, irplib_framelist_get_size(rawframes), naxis3, nchop, file);
00296
00297 if (planeend >= naxis3 || planeend < 0)
00298 pend = naxis3 - 1;
00299 else
00300 pend = planeend;
00301
00302 if (planestart != 0) {
00303 packed = load_range(file, CPL_TYPE_UNSPECIFIED, planestart - 1, pend);
00304 prevd = cpl_imagelist_unset(packed, 0);
00305 }
00306 else
00307 packed = load_range(file, CPL_TYPE_UNSPECIFIED, planestart, pend);
00308
00309 skip_if(visir_load_cube2_split_(alist, blist, packed, prevd));
00310
00311 end_skip;
00312
00313 cpl_image_delete(prevd);
00314 cpl_imagelist_delete(packed);
00315
00316 return cpl_error_get_code();
00317 }
00318
00319
00320
00337
00338 static
00339 cpl_error_code visir_load_burst_(cpl_imagelist * alist, cpl_imagelist * blist,
00340 cpl_imagelist * packed,
00341 const int ichopchange, const int ihalfcycle,
00342 const int trimlow, int const trimhigh)
00343 {
00344 cpl_boolean bon = CPL_TRUE;
00345 const int offset = 0;
00346 const int pend = cpl_imagelist_get_size(packed);
00347 int lorej = ihalfcycle - trimlow;
00348 int hirej = trimhigh + 1;
00349
00350
00351
00352 int chpmv = ichopchange - ihalfcycle * 2;
00353
00354 cpl_ensure_code(trimhigh >= -1, CPL_ERROR_ILLEGAL_INPUT);
00355 cpl_ensure_code(trimlow >= 0, CPL_ERROR_ILLEGAL_INPUT);
00356 cpl_ensure_code(ichopchange < ihalfcycle * 2, CPL_ERROR_ILLEGAL_INPUT);
00357 cpl_ensure_code(alist != NULL, CPL_ERROR_NULL_INPUT);
00358 cpl_ensure_code(blist != NULL, CPL_ERROR_NULL_INPUT);
00359
00360 skip_if(0);
00361
00362
00363
00364
00365 for (int i = chpmv; i < pend; i++) {
00366 if ((i + ihalfcycle * 2) % ihalfcycle == ichopchange % ihalfcycle) {
00367 bon = !bon;
00368 hirej = trimhigh + 1;
00369 lorej = ihalfcycle - trimlow;
00370 }
00371 if (hirej <= 0 && lorej > 0 && i >= 0) {
00372 if (bon) {
00373 cpl_image * image= cpl_imagelist_unset(packed, offset);
00374 cpl_imagelist_set(alist, image, cpl_imagelist_get_size(alist));
00375 }
00376 else {
00377 cpl_image * image= cpl_imagelist_unset(packed, offset);
00378 cpl_imagelist_set(blist, image, cpl_imagelist_get_size(blist));
00379 }
00380 }
00381 else if (i >= 0)
00382 cpl_image_delete(cpl_imagelist_unset(packed, offset));
00383
00384 hirej--;
00385 lorej--;
00386 }
00387
00388 cpl_msg_info(cpl_func, "On: %d, Off %d, Skipped %d",
00389 (int)cpl_imagelist_get_size(alist),
00390 (int)cpl_imagelist_get_size(blist),
00391 (int)(pend - cpl_imagelist_get_size(alist)
00392 - cpl_imagelist_get_size(blist)));
00393
00394 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00395
00396 end_skip;
00397
00398 return cpl_error_get_code();
00399 }
00400
00401
00402
00411
00412 static int get_to_off_plane(int chopchange, const int offset,
00413 const int ihalfcycle)
00414 {
00415
00416 if (offset -
00417 (offset / (ihalfcycle * 2)) * ihalfcycle * 2 > chopchange)
00418 chopchange += ihalfcycle * 2 - (offset % (ihalfcycle * 2));
00419 else
00420 chopchange -= (offset % ihalfcycle);
00421 return chopchange;
00422 }
00423
00424
00425
00444
00445 cpl_error_code visir_load_burst(cpl_imagelist * alist, cpl_imagelist * blist,
00446 const cpl_frame * frame, const cpl_propertylist * plist,
00447 const int ichopchange, const int ihalfcycle,
00448 const int planestart, const int planeend,
00449 const int trimlow, const int trimhigh)
00450 {
00451 const char * file = cpl_frame_get_filename(frame);
00452 const int naxis3 = visir_pfits_get_naxis3(plist);
00453 const int pend = planeend <= 0 || planeend > naxis3 ? naxis3 : planeend;
00454 cpl_imagelist * packed;
00455 int to_off = get_to_off_plane(ichopchange, planestart, ihalfcycle);
00456
00457 cpl_msg_info(cpl_func, "Loading planes %d to %d, to off %d",
00458 planestart, pend, planestart + to_off);
00459
00460 packed = load_range(file, CPL_TYPE_UNSPECIFIED, planestart, pend);
00461
00462 skip_if(packed == NULL);
00463
00464 skip_if(visir_load_burst_(alist, blist, packed, to_off, ihalfcycle,
00465 trimlow, trimhigh));
00466
00467 end_skip;
00468
00469 cpl_imagelist_delete(packed);
00470
00471 return cpl_error_get_code();
00472 }
00473
00474
00475
00497
00498 cpl_image ** visir_img_collapse_beam(cpl_propertylist * qclist,
00499 const cpl_image * self,
00500 const cpl_parameterlist * parlist,
00501 const char * recipename,
00502 visir_chopnod_mode mode,
00503 const cpl_propertylist * plist)
00504 {
00505
00506 cpl_image ** combined = NULL;
00507
00508 cpl_image * inverse = cpl_image_multiply_scalar_create(self, -1.0);
00509
00510 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
00511 VISIR_PARAM_ECCMAX);
00512
00513
00514 const char * sscale = visir_pfits_get_pixscale(plist);
00515 const double pscale = sscale ? atof(sscale) : 0.0;
00516 const double pthrow = pscale > 0.0
00517 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
00518
00519
00520 skip_if(self == NULL);
00521 skip_if(parlist == NULL);
00522 skip_if(qclist == NULL);
00523 skip_if(plist == NULL);
00524
00525 if (mode == VISIR_CHOPNOD_PERPENDICULAR) {
00526
00527 combined = visir_img_collapse_beam_four(qclist, self, inverse, eccmax,
00528 pthrow, plist);
00529 } else if (mode == VISIR_CHOPNOD_PARALLEL) {
00530
00531 combined = visir_img_collapse_beam_three(qclist, self, inverse, eccmax,
00532 pthrow, plist);
00533 } else if (mode == VISIR_CHOPNOD_AUTO) {
00534 cpl_errorstate cleanstate = cpl_errorstate_get();
00535
00536 const char * sdir = visir_pfits_get_chopnod_dir(plist);
00537
00538 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
00539
00540 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00541 eccmax, pthrow, plist);
00542 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
00543
00544 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00545 eccmax, pthrow, plist);
00546 } else {
00547 if (sdir == NULL) {
00548 visir_error_reset("Could not get FITS key");
00549 } else {
00550 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
00551 sdir);
00552 }
00553 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
00554 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
00555 "PERPENDICULAR");
00556 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00557 eccmax, pthrow, plist);
00558 if (combined == NULL) {
00559 visir_error_reset("Proceeding as if FITS card "
00560 VISIR_PFITS_STRING_CHOPNOD_DIR
00561 " had value: %s", "PARALLEL");
00562 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00563 eccmax, pthrow, plist);
00564 }
00565 }
00566 } else {
00567 bug_if(1);
00568 }
00569
00570 skip_if(combined == NULL);
00571
00572 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
00573 pthrow));
00574 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
00575 "The throw in pixels (TEL CHOP THROW "
00576 "divided by INS PFOV)"));
00577
00578 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM XPOS",
00579 "The X pixel position (centroid) "
00580 "of the one-beam object"));
00581
00582 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM YPOS",
00583 "The Y pixel position (centroid) "
00584 "of the one-beam object"));
00585 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM ECCENTRICITY",
00586 "Eccentricity: 0 for perfect, throw-"
00587 "sized square/line"));
00588
00589 end_skip;
00590
00591 cpl_image_delete(inverse);
00592
00593 return combined;
00594 }
00595
00596
00597
00680
00681 cpl_imagelist * visir_inputs_combine(const char * recipename,
00682 const cpl_parameterlist * parlist,
00683 const irplib_framelist * rawframes,
00684 const char * badpix,
00685 const char * flat,
00686 int * nodding_p,
00687 cpl_boolean do_spc_fix,
00688 double wlen,
00689 visir_spc_resol resol)
00690 {
00691 const char * fnodpos;
00692 int nfiles;
00693 cpl_imagelist * in = NULL;
00694 cpl_image * collapsed = NULL;
00695 cpl_image * prev = NULL;
00696 cpl_vector * nods_vec = NULL;
00697 double * nods_data;
00698 int * nod_pos = NULL;
00699 cpl_image ** images = NULL;
00700 cpl_imagelist * nodded = NULL;
00701 int nnod;
00702 cpl_image * flat_image = NULL;
00703 cpl_image * bpm_im_int = NULL;
00704 cpl_mask * bpm_im_bin = NULL;
00705 cpl_imagelist * hcycle = NULL;
00706 cpl_boolean no_rem;
00707 cpl_boolean is_nodding = CPL_FALSE;
00708 int i, j;
00709 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00710 int ndestripe;
00711 int naxis1, naxis2;
00712 cpl_boolean morpho_destripe;
00713 double tstart, tstop;
00714 const cpl_propertylist * plist1;
00715 #ifdef _OPENMP
00716 cpl_errorstate cleanstate = cpl_errorstate_get();
00717 #endif
00718 cpl_error_code didfail = CPL_ERROR_NONE;
00719
00720
00721 skip_if (0);
00722 skip_if(recipename == NULL);
00723 skip_if(parlist == NULL);
00724 skip_if(rawframes == NULL);
00725
00726
00727 nfiles = irplib_framelist_get_size(rawframes);
00728
00729
00730 if (nfiles % 2) {
00731 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00732 "ignoring the last of %d file(s)", nfiles);
00733 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00734 "At least two files are required");
00735 nfiles--;
00736 }
00737
00738 nnod = nfiles/2;
00739
00740 skip_if (nnod <= 0);
00741
00742 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00743 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00744 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00745 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00746
00747 skip_if (irplib_framelist_contains(rawframes, "NAXIS1",
00748 CPL_TYPE_INT, CPL_TRUE, 0.0));
00749 skip_if (irplib_framelist_contains(rawframes, "NAXIS2",
00750 CPL_TYPE_INT, CPL_TRUE, 0.0));
00751 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00752 CPL_TYPE_INT, CPL_FALSE, 0.0));
00753 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00754 CPL_TYPE_INT, CPL_FALSE, 0.0));
00755
00756 plist1 = irplib_framelist_get_propertylist_const(rawframes, 0);
00757 naxis1 = irplib_pfits_get_int(plist1, "NAXIS1");
00758 naxis2 = irplib_pfits_get_int(plist1, "NAXIS2");
00759 skip_if(0);
00760
00761
00762 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00763 VISIR_PARAM_NODPOS);
00764 skip_if (0);
00765
00766 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00767 VISIR_PARAM_AUTOBPM);
00768 skip_if (0);
00769
00770 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00771 VISIR_PARAM_GLITCH);
00772 skip_if (0);
00773
00774 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00775 VISIR_PARAM_PURGE);
00776 skip_if (0);
00777
00778 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00779 VISIR_PARAM_STRIPITE);
00780 bug_if (0);
00781
00782 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00783 visir_parameterlist_get_bool(parlist, recipename,
00784 VISIR_PARAM_STRIPMOR);
00785 bug_if (0);
00786
00787 no_rem = !rem_glitch && !rem_bad;
00788
00789
00790
00791 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00792 j = 0;
00793 if (fnodpos != NULL && strlen(fnodpos) > 0 && strcmp(fnodpos, ".") != 0) {
00794
00795 nods_vec = cpl_vector_read(fnodpos);
00796 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00797 nods_data = cpl_vector_get_data(nods_vec);
00798 skip_if (0);
00799 for (i=0 ; i<nfiles ; i++) {
00800 if ((int)nods_data[i] == 0) {
00801 nod_pos[i] = 1;
00802 j++;
00803 } else if ((int)nods_data[i] == 1) {
00804 nod_pos[i] = -1;
00805 is_nodding = CPL_TRUE;
00806 } else {
00807 error_if(1, CPL_ERROR_BAD_FILE_FORMAT,
00808 "Wrong values in line %d in %s", i+1, fnodpos);
00809 }
00810 }
00811 } else {
00812 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00813 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00814 }
00815
00816 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00817 "frames requested: Using fast I/O method");
00818
00819
00820 if (badpix != NULL) {
00821
00822 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00823
00824 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00825 skip_if (0);
00826
00827
00828 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00829 cpl_image_delete(bpm_im_int);
00830 bpm_im_int = NULL;
00831 skip_if (cpl_mask_not(bpm_im_bin));
00832 } else if (auto_bpm) {
00833
00834
00835
00836 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00837 skip_if(0);
00838
00839 bpm_im_bin =
00840 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00841 VISIR_HCYCLE_BPM_THRESHOLD,
00842 DBL_MAX);
00843 cpl_imagelist_delete(hcycle);
00844 hcycle = NULL;
00845 skip_if(0);
00846 }
00847
00848
00849 if (flat != NULL) {
00850 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00851
00852 flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
00853 any_if ("Cannot load the flat field %s", flat ? flat : "<NULL>");
00854 }
00855
00856
00857 nodded = cpl_imagelist_new();
00858
00859 tstart = cpl_test_get_walltime();
00860
00861
00862
00863 for (i=0; i < nfiles/2 ; i++) {
00864 cpl_image * empty = cpl_image_new(naxis1, naxis2, CPL_TYPE_FLOAT);
00865
00866
00867
00868
00869 bug_if (cpl_imagelist_set(nodded, empty, i));
00870 }
00871
00872 #ifdef _OPENMP
00873 #pragma omp parallel for private(i) firstprivate(prev, collapsed) \
00874 schedule(static, 2)
00875 #endif
00876 for (i = 0; i < nfiles ; i++) {
00877 cpl_error_code errori = cpl_error_get_code();
00878
00879
00880
00881
00882
00883
00884
00885 if (didfail) continue;
00886
00887 do {
00888
00889 const char * file =
00890 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
00891 const cpl_propertylist * plist;
00892
00893 double dit;
00894 double factor;
00895
00896
00897 plist = irplib_framelist_get_propertylist_const(rawframes, i);
00898 if (plist == NULL) {
00899 errori = cpl_error_set_where(cpl_func);
00900 break;
00901 }
00902
00903 if (nods_vec == NULL) {
00904 const char * sval = visir_pfits_get_nodpos(plist);
00905 if (sval == NULL) {
00906 errori = cpl_error_set_message(cpl_func,
00907 CPL_ERROR_DATA_NOT_FOUND,
00908 "Cannot get nodding position "
00909 "for file %d/%d", i+1, nfiles);
00910 break;
00911 }
00912 if (!strcmp(sval, "A")) {
00913 nod_pos[i] = 1;
00914 j++;
00915 } else {
00916 nod_pos[i] = -1;
00917 is_nodding = CPL_TRUE;
00918 }
00919 }
00920
00921
00922 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
00923 nod_pos[i]==1 ? '+' : '-');
00924
00925
00926 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
00927 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
00928 "on-object (A) and an off-object (B) image: %s", i-1,
00929 i, nod_pos[i] == 1 ? "A" : "B");
00930 }
00931
00932
00933 dit = visir_pfits_get_dit(plist);
00934 if (cpl_error_get_code()) {
00935 errori = cpl_error_set_where(cpl_func);
00936 break;
00937 }
00938
00939 if (dit <= 0) {
00940 errori = cpl_error_set_message(cpl_func,
00941 CPL_ERROR_ILLEGAL_INPUT,
00942 "DIT in file %d/%d is too small: "
00943 "%g", i+1, nfiles, dit);
00944 break;
00945 }
00946
00947 factor = dit * nod_pos[i] * 2.0;
00948
00949 if (no_rem){
00950 collapsed = visir_load_average(file, plist);
00951 } else {
00952 in = visir_load_intermint(rawframes, i);
00953 if (in == NULL) {
00954 errori = cpl_error_set_message(cpl_func,
00955 CPL_ERROR_ILLEGAL_INPUT,
00956 "Could not load image set %d",
00957 i+1);
00958 break;
00959 }
00960
00961
00962 if (visir_imagelist_unpack_interm(in)) {
00963 errori = cpl_error_set_message(cpl_func,
00964 cpl_error_get_code(),
00965 "Failure for file %d/%d",
00966 i+1, nfiles);
00967 break;
00968 }
00969
00970
00971
00972 if (rem_glitch) {
00973 int jj;
00974 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
00975 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
00976 errori = cpl_error_set_message(cpl_func,
00977 cpl_error_get_code(),
00978 "Could not remove "
00979 "glitch in image %d in "
00980 "set %d", jj+1, i+1);
00981 break;
00982 }
00983 }
00984 }
00985
00986
00987 if (rem_bad) {
00988 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
00989 if (visir_rem_bad_images(in)) {
00990 errori = cpl_error_set_message(cpl_func,
00991 cpl_error_get_code(),
00992 "Could not remove bad "
00993 "images in list %d", i+1);
00994 break;
00995 }
00996 }
00997
00998 collapsed = cpl_imagelist_collapse_create(in);
00999
01000 cpl_imagelist_delete(in);
01001 in = NULL;
01002
01003 }
01004
01005 if (cpl_error_get_code()) {
01006 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01007 "Failure for file %d/%d",
01008 i+1, nfiles);
01009 break;
01010 }
01011
01012
01013 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
01014 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01015 "Failure for file %d/%d",
01016 i+1, nfiles);
01017 break;
01018 }
01019
01020
01021 if (i & 1) {
01022 if (cpl_image_add(prev, collapsed)) {
01023 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01024 "Failure for file %d/%d",
01025 i+1, nfiles);
01026 break;
01027 }
01028 cpl_image_delete(collapsed);
01029 collapsed = NULL;
01030
01031
01032
01033
01034 if (bpm_im_bin != NULL) {
01035
01036 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
01037 errori = cpl_error_set_message(cpl_func,
01038 cpl_error_get_code(),
01039 "Failure for file %d/%d",
01040 i+1, nfiles);
01041 break;
01042 }
01043 if (cpl_detector_interpolate_rejected(prev)) {
01044 errori = cpl_error_set_message(cpl_func,
01045 cpl_error_get_code(),
01046 "Failure for file %d/%d",
01047 i+1, nfiles);
01048 break;
01049 }
01050 }
01051
01052 if (ndestripe > 0)
01053 if(visir_destripe_image(prev, ndestripe,
01054 VISIR_DESTRIPE_DETECT,
01055 VISIR_DESTRIPE_DETECT_THRESHOLD,
01056 morpho_destripe)) {
01057 errori = cpl_error_set_message(cpl_func,
01058 cpl_error_get_code(),
01059 "Failure for file %d/%d",
01060 i+1, nfiles);
01061 break;
01062 }
01063
01064 if (flat_image != NULL) {
01065
01066 if (cpl_image_divide(prev, flat_image)) {
01067 errori = cpl_error_set_message(cpl_func,
01068 cpl_error_get_code(),
01069 "Failure for file %d/%d",
01070 i+1, nfiles);
01071 break;
01072 }
01073 }
01074
01075 if (cpl_imagelist_set(nodded, prev, i/2)) {
01076 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01077 "Failure for file %d/%d",
01078 i+1, nfiles);
01079 break;
01080 }
01081 prev = NULL;
01082 } else {
01083 prev = collapsed;
01084 collapsed = NULL;
01085 }
01086 } while (0);
01087
01088 if (errori) {
01089 #ifdef _OPENMP
01090
01091
01092 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
01093 cpl_errorstate_set(cleanstate);
01094
01095
01096 cpl_image_delete(prev); prev = NULL;
01097 cpl_image_delete(collapsed); collapsed = NULL;
01098
01099 #pragma omp critical(visir_inputs_combine)
01100 #endif
01101 didfail = errori;
01102 }
01103 }
01104
01105 error_if(didfail, didfail, "Failed to create %d nodded images from %d "
01106 "files", nnod, nfiles);
01107
01108 tstop = cpl_test_get_walltime();
01109 cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
01110 tstop - tstart);
01111
01112 cpl_vector_delete(nods_vec);
01113 nods_vec = NULL;
01114
01115 cpl_image_delete(flat_image);
01116 flat_image = NULL;
01117
01118 cpl_mask_delete(bpm_im_bin);
01119 bpm_im_bin = NULL;
01120
01121 if (nod_pos != nodding_p) cpl_free(nod_pos);
01122 nod_pos = NULL;
01123
01124 error_if(is_nodding && j != nnod, CPL_ERROR_INCOMPATIBLE_INPUT,
01125 "With nodding exactly half of the images "
01126 "must be on-object, not %d of %d", j, 2*nnod);
01127
01128 if (do_spc_fix) {
01129 const double ksi = visir_parameterlist_get_double(parlist, recipename,
01130 VISIR_PARAM_SPECSKEW);
01131 const double eps = visir_parameterlist_get_double(parlist, recipename,
01132 VISIR_PARAM_VERTARC);
01133 const double delta = visir_parameterlist_get_double(parlist, recipename,
01134 VISIR_PARAM_HORIARC);
01135 const double phi = visir_parameterlist_get_double(parlist, recipename,
01136 VISIR_PARAM_SLITSKEW);
01137 const int doplot = visir_parameterlist_get_int(parlist, recipename,
01138 VISIR_PARAM_PLOT);
01139
01140
01141 skip_if (0);
01142
01143 images = cpl_malloc(nnod * sizeof(cpl_image*));
01144
01145 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
01146
01147 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
01148 phi, ksi, eps, delta, doplot));
01149 }
01150
01151 end_skip;
01152
01153 cpl_msg_set_time_off();
01154
01155 cpl_free(images);
01156 cpl_imagelist_delete(in);
01157
01158 if (nod_pos != nodding_p) cpl_free(nod_pos);
01159 cpl_vector_delete(nods_vec);
01160 cpl_image_delete(bpm_im_int);
01161 cpl_mask_delete(bpm_im_bin);
01162 cpl_image_delete(collapsed);
01163 cpl_image_delete(prev);
01164 if (cpl_error_get_code() && nodded != NULL) {
01165 cpl_imagelist_delete(nodded);
01166 nodded = NULL;
01167 }
01168
01169 return nodded;
01170 }
01171
01172
01219
01220 cpl_image ** visir_img_recombine(const char * recipename,
01221 const cpl_parameterlist * parlist,
01222 const irplib_framelist * rawframes,
01223 const char * badpix,
01224 const char * flat,
01225 cpl_geom_combine combine_mode,
01226 cpl_boolean * pdid_resize,
01227 cpl_boolean do_spc_fix,
01228 double wlen,
01229 visir_spc_resol resol)
01230 {
01231 int nfiles;
01232 int * nod_pos = NULL;
01233 cpl_imagelist * nodded = NULL;
01234 int nnod;
01235 cpl_bivector * offsets_est = NULL;
01236 cpl_bivector * objs = NULL;
01237 cpl_image ** combined = NULL;
01238 const cpl_vector * sigmas = NULL;
01239 double xoff, yoff;
01240 cpl_propertylist * qclist = cpl_propertylist_new();
01241 int i;
01242
01243
01244 bug_if (0);
01245
01246 bug_if (recipename == NULL);
01247 bug_if (parlist == NULL);
01248 bug_if (rawframes == NULL);
01249 bug_if (pdid_resize == NULL);
01250
01251
01252 nfiles = irplib_framelist_get_size(rawframes);
01253
01254
01255 if (nfiles % 2) {
01256 cpl_msg_warning(cpl_func, "Expecting even number of files, "
01257 "ignoring the last of %d file(s)", nfiles);
01258 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
01259 "At least two files are required");
01260 nfiles--;
01261 }
01262
01263 skip_if ( nfiles <= 0);
01264
01265
01266 nod_pos = cpl_malloc(nfiles * sizeof(int));
01267
01268
01269 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
01270 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
01271 nod_pos, do_spc_fix, wlen, resol);
01272
01273 skip_if (nodded == NULL);
01274 nnod = cpl_imagelist_get_size(nodded);
01275
01276
01277 if (nnod == 1) {
01278
01279 combined = cpl_malloc(2*sizeof(cpl_image*));
01280 combined[1] = NULL;
01281
01282 combined[0] = cpl_imagelist_unset(nodded, 0);
01283 bug_if (combined[0] == NULL);
01284
01285 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
01286 cpl_image_get_size_y(combined[0]),
01287 CPL_TYPE_INT);
01288 bug_if (combined[1] == NULL);
01289
01290
01291 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
01292
01293 *pdid_resize = CPL_FALSE;
01294
01295 } else {
01296 const double psigmas[] = {5, 2, 1, 0.5};
01297 const char * sval;
01298 const char * offsets;
01299 const char * objects;
01300 int sx, sy, mx, my;
01301 int rej_low, rej_high;
01302 cpl_boolean refine;
01303
01304
01305 refine = visir_parameterlist_get_bool(parlist, recipename,
01306 VISIR_PARAM_REFINE);
01307 skip_if (0);
01308
01309 offsets = visir_parameterlist_get_string(parlist, recipename,
01310 VISIR_PARAM_OFFSETS);
01311 skip_if (0);
01312
01313 objects = visir_parameterlist_get_string(parlist, recipename,
01314 VISIR_PARAM_OBJECTS);
01315 skip_if (0);
01316
01317 sval = visir_parameterlist_get_string(parlist, recipename,
01318 VISIR_PARAM_XCORR);
01319 skip_if (0);
01320
01321 if (sscanf(sval, "%d-%d-%d-%d", &sx, &sy, &mx, &my) != 4)
01322 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
01323
01324
01325 sval = visir_parameterlist_get_string(parlist, recipename,
01326 VISIR_PARAM_REJECT);
01327 skip_if (0);
01328
01329 if (sscanf(sval, "%d-%d", &rej_low, &rej_high) !=2 )
01330 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
01331
01332
01333 cpl_msg_info(cpl_func, "Get the offsets estimation");
01334 if (offsets != NULL && strlen(offsets) && strcmp(offsets, ".") != 0) {
01335
01336 offsets_est = cpl_bivector_read(offsets);
01337 skip_if (offsets_est==NULL);
01338
01339 error_if (cpl_bivector_get_size(offsets_est) != nnod,
01340 CPL_ERROR_BAD_FILE_FORMAT, "The offsets file %s must "
01341 "have %d entries, not %d", offsets, nnod,
01342 (int)cpl_bivector_get_size(offsets_est));
01343 } else {
01344 double * offsets_est_x;
01345 double * offsets_est_y;
01346 double xoff0 = 0.0;
01347 double yoff0 = 0.0;
01348
01349
01350 offsets_est = cpl_bivector_new(nnod);
01351 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01352 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01353
01354 skip_if (0);
01355
01356 offsets_est_x[0] = 0.0;
01357 offsets_est_y[0] = 0.0;
01358
01359 for (i=0; i < nnod ; i++) {
01360 const cpl_propertylist * plist;
01361
01362
01363 const int iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
01364
01365 plist = irplib_framelist_get_propertylist_const(rawframes,
01366 iframe);
01367 skip_if(plist == NULL);
01368
01369 xoff = visir_pfits_get_cumoffsetx(plist);
01370 yoff = visir_pfits_get_cumoffsety(plist);
01371
01372 skip_if (0);
01373
01374 if (i == 0) {
01375 xoff0 = xoff;
01376 yoff0 = yoff;
01377 } else {
01378
01379 offsets_est_x[i] = xoff0 - xoff;
01380 offsets_est_y[i] = yoff0 - yoff;
01381 }
01382 }
01383 }
01384 cpl_free(nod_pos);
01385 nod_pos = NULL;
01386
01387
01388
01389 if (objects != NULL && strlen(objects) > 0 && strcmp(offsets, ".") != 0) {
01390 objs = cpl_bivector_read(objects);
01391 any_if ("Could not read objects from %s", objects);
01392 }
01393
01394 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
01395 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
01396 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
01397 CPL_GEOM_FIRST, rej_low, rej_high);
01398
01399 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
01400 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
01401 cpl_bivector_dump(offsets_est, stdout);
01402 }
01403
01404 sigmas = cpl_vector_wrap(4, (double*)psigmas);
01405 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
01406 objs, sigmas, NULL, sx, sy,
01407 mx, my, rej_low, rej_high,
01408 combine_mode);
01409 any_if("Could not recombine the images");
01410
01411 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
01412 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
01413 cpl_image_get_size_y(combined[0])
01414 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
01415 }
01416
01417 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
01418 visir_image_plot("", "t 'The combined image'", "", combined[0]);
01419
01420 end_skip;
01421
01422 cpl_propertylist_delete(qclist);
01423 cpl_free(nod_pos);
01424 cpl_imagelist_delete(nodded);
01425 cpl_bivector_delete(offsets_est);
01426 cpl_bivector_delete(objs);
01427 cpl_vector_unwrap((cpl_vector*)sigmas);
01428
01429 return combined;
01430 }
01431
01432
01455
01456 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
01457 {
01458 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
01459 }
01460
01461
01472
01473 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
01474 {
01475
01476 cpl_image * im_bpm = NULL;
01477 cpl_mask * bpm = NULL;
01478 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
01479
01480
01481 skip_if (0);
01482
01483 skip_if (self == NULL);
01484
01485 if (bpmfile == NULL) {
01486 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
01487 skip_if (0);
01488 } else {
01489
01490
01491 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
01492
01493 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
01494 any_if ("Could not load the bad pixel map %s",
01495 bpmfile ? bpmfile : "<NULL>");
01496
01497 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
01498 skip_if (0);
01499 cpl_image_delete(im_bpm);
01500 im_bpm = NULL;
01501
01502 skip_if (cpl_mask_not(bpm));
01503 }
01504
01505 skip_if (cpl_image_reject_from_mask(self, bpm));
01506
01507 end_skip;
01508
01509 cpl_image_delete(im_bpm);
01510 cpl_mask_delete(bpm);
01511
01512 return cpl_error_get_code();
01513
01514 }
01515
01516
01517
01524
01525 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
01526 {
01527 cpl_imagelist * self = NULL;
01528 int naxis3;
01529
01530
01531 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
01532 CPL_TYPE_INT, CPL_TRUE, 0.0));
01533
01534 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
01535 rawframes,
01536 0));
01537
01538
01539 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
01540 0);
01541
01542 skip_if (self == NULL);
01543
01544 end_skip;
01545
01546 return self;
01547
01548 }
01549
01550
01551
01561
01562 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01563 int pos, cpl_boolean is_interm)
01564 {
01565 cpl_imagelist * self = NULL;
01566 cpl_image * image = NULL;
01567 const char * file
01568 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
01569 int naxis3, nchop;
01570 visir_cube_type cube_type;
01571 const cpl_error_code code = visir_get_type(rawframes, pos, &cube_type,
01572 &naxis3, &nchop);
01573 int plane_step;
01574 int nsize;
01575 int iplane;
01576 int i;
01577
01578
01579 skip_if (code);
01580 bug_if (file == NULL);
01581
01582 if (cube_type == VISIR_CUBE1) {
01583
01584 iplane = is_interm ? 0 : nchop;
01585
01586 nsize = is_interm ? nchop : 1;
01587 plane_step = 1;
01588 } else if (naxis3 == 1) {
01589 iplane = 0;
01590 nsize = 1;
01591 plane_step = 1;
01592 } else {
01593
01594 iplane = is_interm ? 1 : 0;
01595 nsize = nchop;
01596 plane_step = 2;
01597 }
01598
01599 self = cpl_imagelist_new();
01600
01601 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01602
01603 image = cpl_image_load(file, CPL_TYPE_FLOAT, iplane, 0);
01604 skip_if (image == NULL);
01605
01606 skip_if (!is_interm && visir_offset_hcycle(image));
01607
01608 skip_if (cpl_imagelist_set(self, image, i));
01609
01610 image = NULL;
01611 }
01612
01613 skip_if (i < nsize);
01614
01615 end_skip;
01616
01617 if (cpl_error_get_code()) {
01618 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01619 "frame(s) from: %s",
01620 is_interm ? "INTERM" : "Half-Cycle",
01621 file);
01622 cpl_image_delete(image);
01623 cpl_imagelist_delete(self);
01624 self = NULL;
01625 }
01626
01627 return self;
01628 }
01629
01630
01633
01657
01658 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01659 int pos)
01660 {
01661 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01662
01663 }
01664
01665
01674
01675 static cpl_image * visir_load_average(const char * file,
01676 const cpl_propertylist * plist)
01677 {
01678 cpl_errorstate cleanstate = cpl_errorstate_get();
01679 cpl_image * self = NULL;
01680 int nchop, naxis3;
01681
01682
01683 skip_if (0);
01684 skip_if (file == NULL);
01685 skip_if (plist == NULL);
01686
01687 naxis3 = visir_pfits_get_naxis3(plist);
01688 nchop = visir_pfits_get_chop_ncycles(plist);
01689
01690 skip_if (0);
01691
01692 if (nchop == 0 && naxis3 == 1) {
01693 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01694 } else {
01695 const char * sval;
01696
01697
01698 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01699
01700
01701 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT, "CHOP NCYCLES in %s "
01702 "is non-positive (and NAXIS3=%d): %d", file, naxis3, nchop);
01703
01704 error_if (plane_offset == 3 && naxis3 != nchop+2,
01705 CPL_ERROR_BAD_FILE_FORMAT, "NAXIS3=%d and CHOP NCYCLES=%d "
01706 "in %s is not a valid VISIR INTERM+Half-Cycle format", naxis3,
01707 nchop, file);
01708
01709 if (plane_offset == 3 && nchop > 1)
01710 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01711 "Cycle frame (old CUBE1-format)", file, nchop);
01712
01713
01714 sval = visir_pfits_get_frame_type(plist);
01715 if (sval == NULL) {
01716
01717 visir_error_reset("Could not get FITS key");
01718
01719 } else if (strlen(sval) == 0) {
01720
01721 } else if (plane_offset == 3) {
01722 if (strcmp(sval, "CUBE2")==0)
01723 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3="
01724 "%d and CHOP NCYCLES=%d imply a CUBE1. Assuming"
01725 " the frame type is really CUBE1", file,
01726 naxis3, nchop);
01727 } else if (nchop > 1) {
01728
01729 if (strcmp(sval, "CUBE1")==0)
01730 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3="
01731 "%d and CHOP NCYCLES=%d imply a CUBE2. Assuming"
01732 "the frame type is really CUBE2", file,
01733 naxis3, nchop);
01734 }
01735
01736
01737 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01738
01739 }
01740
01741 skip_if (0);
01742
01743 end_skip;
01744
01745 if (cpl_error_get_code()) {
01746 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01747 "%s", file ? file : "<NULL>");
01748 cpl_image_delete(self);
01749 self = NULL;
01750 }
01751
01752 return self;
01753 }
01754
01755
01778
01779 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01780 {
01781 cpl_image * iprev;
01782 cpl_image * image;
01783 const int n = cpl_imagelist_get_size(self);
01784 int i;
01785
01786
01787 skip_if (0);
01788
01789 if (n == 1) return CPL_ERROR_NONE;
01790
01791 iprev = cpl_imagelist_get(self, n - 1);
01792
01793 skip_if (0);
01794
01795 skip_if (cpl_image_multiply_scalar(iprev, n));
01796
01797
01798 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01799 image = cpl_imagelist_get(self, i-1);
01800
01801 skip_if (0);
01802
01803 skip_if (cpl_image_multiply_scalar(image, i));
01804
01805 skip_if (cpl_image_subtract(iprev, image));
01806
01807 }
01808
01809 image = cpl_imagelist_get(self, 0);
01810
01811 skip_if (0);
01812
01813 skip_if (cpl_image_subtract(iprev, image));
01814
01815 end_skip;
01816
01817 return cpl_error_get_code();
01818 }
01819
01820
01833
01834 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
01835 {
01836 cpl_image * med_filt = NULL;
01837 cpl_mask * bpm = NULL;
01838 cpl_mask * kernel = cpl_mask_new(3, 3);
01839 double mean, stdev;
01840 double low_thresh, high_thresh;
01841 const int nx = cpl_image_get_size_x(glitchy);
01842 const int ny = cpl_image_get_size_y(glitchy);
01843 int i;
01844
01845
01846 double factor1 = 3.0;
01847 double factor2 = 10.0;
01848 const int niterations = 5;
01849 const double median_corr = 1.5;
01850
01851 bug_if (0);
01852
01853
01854 bug_if(cpl_mask_not(kernel));
01855
01856
01857 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
01858 cpl_image_get_size_y(glitchy),
01859 cpl_image_get_type(glitchy));
01860 bug_if(med_filt == NULL);
01861 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
01862 CPL_BORDER_FILTER));
01863 cpl_mask_delete(kernel);
01864 kernel = NULL;
01865
01866
01867 skip_if (cpl_image_subtract(glitchy, med_filt));
01868
01869
01870 for (i=0 ; i < niterations ; i++) {
01871
01872 mean = cpl_image_get_mean(glitchy);
01873 stdev = cpl_image_get_stdev(glitchy);
01874
01875 skip_if (0);
01876
01877
01878 low_thresh = mean - factor1 * stdev;
01879 high_thresh = mean + factor1 * stdev;
01880
01881
01882 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
01883 skip_if (cpl_mask_not(bpm));
01884 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01885 cpl_mask_delete(bpm);
01886 bpm = NULL;
01887
01888
01889 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01890 }
01891
01892
01893
01894 mean = cpl_image_get_mean(glitchy);
01895 stdev = cpl_image_get_stdev(glitchy) * median_corr;
01896
01897 skip_if (0);
01898
01899 low_thresh = mean - factor2 * stdev;
01900 high_thresh = mean + factor2 * stdev;
01901
01902 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
01903 skip_if (cpl_mask_not(bpm));
01904 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
01905 cpl_mask_delete(bpm);
01906 bpm = NULL;
01907
01908
01909 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
01910
01911
01912 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
01913 skip_if (cpl_image_accept_all(glitchy));
01914
01915
01916 skip_if (cpl_image_add(glitchy, med_filt));
01917
01918 end_skip;
01919
01920 cpl_image_delete(med_filt);
01921 cpl_mask_delete(bpm);
01922 cpl_mask_delete(kernel);
01923
01924 return cpl_error_get_code();
01925 }
01926
01927
01938
01939 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
01940 {
01941 cpl_vector * medians = NULL;
01942 cpl_vector * stdevs = NULL;
01943 cpl_vector * selection = NULL;
01944 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
01945 const double threshold = 3;
01946 const int nima = cpl_imagelist_get_size(in);
01947 int i;
01948
01949
01950
01951 skip_if (0);
01952
01953 if (nima <= 3) return CPL_ERROR_NONE;
01954
01955
01956 medians = cpl_vector_new(nima);
01957 stdevs = cpl_vector_new(nima);
01958
01959
01960 for (i=0 ; i < nima ; i++) {
01961 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
01962 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
01963
01964 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
01965 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
01966 cpl_stats_delete(stats);
01967 }
01968
01969 skip_if( 0);
01970
01971
01972 mean_medians = cpl_vector_get_mean(medians);
01973 stdev_medians = cpl_vector_get_stdev(medians);
01974 mean_stdevs = cpl_vector_get_mean(stdevs);
01975 stdev_stdevs = cpl_vector_get_stdev(stdevs);
01976
01977 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
01978 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
01979
01980 stdev_medians *= threshold;
01981 stdev_stdevs *= threshold;
01982
01983
01984 selection = cpl_vector_new(nima);
01985 skip_if( cpl_vector_fill(selection, 0));
01986 for (i=0 ; i < nima ; i++) {
01987 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
01988 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
01989
01990 cpl_vector_set(selection, i, -1);
01991 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
01992 i+1, nima, stdev_medians, stdev_stdevs);
01993 }
01994
01995
01996 cpl_imagelist_erase(in, selection);
01997
01998 end_skip;
01999
02000 cpl_vector_delete(medians);
02001 cpl_vector_delete(stdevs);
02002
02003 cpl_vector_delete(selection);
02004
02005 return CPL_ERROR_NONE;
02006
02007 }
02008
02009
02018
02019 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
02020 {
02021 double minval;
02022
02023
02024 skip_if (0);
02025
02026 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
02027
02028 minval = cpl_image_get_min(hcycle);
02029
02030
02031 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
02032
02033 end_skip;
02034
02035 return CPL_ERROR_NONE;
02036 }
02037
02038
02050
02051 static
02052 cpl_image ** visir_img_collapse_beam_four(cpl_propertylist * qclist,
02053 const cpl_image * self,
02054 const cpl_image * inverse,
02055 double eccmax,
02056 double pthrow,
02057 const cpl_propertylist * plist)
02058 {
02059
02060 cpl_image ** combined = NULL;
02061 const int nx = cpl_image_get_size_x(self);
02062 const int ny = cpl_image_get_size_y(self);
02063 const cpl_type type = cpl_image_get_type(self);
02064 cpl_imagelist * list4 = cpl_imagelist_new();
02065 cpl_image * swrap = type == CPL_TYPE_DOUBLE
02066 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)self))
02067 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)self));
02068 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02069 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02070 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02071 cpl_bivector * offs = cpl_bivector_new(4);
02072 double * x4 = cpl_bivector_get_x_data(offs);
02073 double * y4 = cpl_bivector_get_y_data(offs);
02074 double pos_x, pos_y;
02075 int i;
02076
02077 skip_if (0);
02078
02079 skip_if(plist == NULL);
02080
02081 skip_if(visir_img_find_beam_four(qclist, self, inverse, eccmax, pthrow,
02082 x4, y4));
02083
02084
02085 for (i = 1; i < 4; i++) {
02086 x4[i] = x4[0] - x4[i];
02087 y4[i] = y4[0] - y4[i];
02088 }
02089
02090 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02091 x4[0]));
02092 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02093 y4[0]));
02094 x4[0] = y4[0] = 0.0;
02095
02096 bug_if(cpl_imagelist_set(list4, (cpl_image*)self, 0));
02097 bug_if(cpl_imagelist_set(list4, swrap, 1));
02098 bug_if(cpl_imagelist_set(list4, (cpl_image*)inverse, 2));
02099 bug_if(cpl_imagelist_set(list4, iwrap, 3));
02100
02101 combined = cpl_geom_img_offset_saa(list4, offs, CPL_KERNEL_DEFAULT, 0, 0,
02102 CPL_GEOM_FIRST, &pos_x, &pos_y);
02103
02104 skip_if(combined == NULL);
02105
02106 end_skip;
02107
02108 cpl_bivector_delete(offs);
02109 for (i = cpl_imagelist_get_size(list4) - 1; i >= 0; i--) {
02110 (void)cpl_imagelist_unset(list4, i);
02111 }
02112 cpl_imagelist_delete(list4);
02113 (void)cpl_image_unwrap(swrap);
02114 (void)cpl_image_unwrap(iwrap);
02115 if (cpl_error_get_code() && combined != NULL) {
02116 cpl_image_delete(combined[0]);
02117 cpl_image_delete(combined[1]);
02118 cpl_free(combined);
02119 }
02120
02121 return combined;
02122 }
02123
02124
02138
02139 visir_chopnod_mode visir_img_find_beam(cpl_propertylist * qclist,
02140 const cpl_image * self,
02141 const cpl_image * inverse,
02142 const cpl_propertylist * plist,
02143 const cpl_parameterlist * parlist,
02144 const char * recipename,
02145 double x4[],
02146 double y4[])
02147 {
02148
02149 cpl_errorstate cleanstate = cpl_errorstate_get();
02150 visir_chopnod_mode mode = VISIR_CHOPNOD_AUTO;
02151
02152 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
02153 VISIR_PARAM_ECCMAX);
02154
02155 const char * sdir;
02156
02157
02158 const char * sscale = visir_pfits_get_pixscale(plist);
02159 const double pscale = sscale ? atof(sscale) : 0.0;
02160 const double pthrow = pscale > 0.0
02161 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
02162
02163
02164 skip_if(x4 == NULL);
02165 skip_if(y4 == NULL);
02166 skip_if(sscale == NULL);
02167 skip_if(self == NULL);
02168 skip_if(inverse == NULL);
02169 skip_if(parlist == NULL);
02170 skip_if(recipename == NULL);
02171 skip_if(qclist == NULL);
02172
02173 sdir = visir_pfits_get_chopnod_dir(plist);
02174
02175 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
02176
02177 skip_if (visir_img_find_beam_four(qclist, self, inverse, eccmax,
02178 pthrow, x4, y4));
02179
02180
02181 mode = VISIR_CHOPNOD_PERPENDICULAR;
02182
02183 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
02184
02185 skip_if (visir_img_find_beam_three(qclist, self, inverse, eccmax,
02186 pthrow, x4, y4));
02187
02188
02189 mode = VISIR_CHOPNOD_PARALLEL;
02190
02191 } else {
02192 if (sdir == NULL) {
02193 visir_error_reset("Could not get FITS key");
02194 } else {
02195 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
02196 sdir);
02197 }
02198 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
02199 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
02200 "PERPENDICULAR");
02201
02202 if (visir_img_find_beam_four(qclist, self, inverse, eccmax,
02203 pthrow, x4, y4)) {
02204
02205 visir_error_reset("Proceeding as if FITS card "
02206 VISIR_PFITS_STRING_CHOPNOD_DIR
02207 " had value: %s", "PARALLEL");
02208
02209 skip_if (visir_img_find_beam_three(qclist, self, inverse,
02210 eccmax, pthrow, x4, y4));
02211
02212
02213 mode = VISIR_CHOPNOD_PARALLEL;
02214
02215 } else {
02216
02217 mode = VISIR_CHOPNOD_PERPENDICULAR;
02218 }
02219 }
02220
02221 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
02222 pthrow));
02223 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
02224 "The throw in pixels (TEL CHOP THROW "
02225 "divided by INS PFOV)"));
02226 end_skip;
02227
02228 return mode;
02229 }
02230
02231
02232
02244
02245 static
02246 cpl_error_code visir_img_find_beam_four(cpl_propertylist * qclist,
02247 const cpl_image * self,
02248 const cpl_image * inverse,
02249 double eccmax,
02250 double pthrow,
02251 double x4[],
02252 double y4[])
02253 {
02254
02255 cpl_errorstate cleanstate = cpl_errorstate_get();
02256 cpl_apertures * appos = NULL;
02257 cpl_apertures * apneg = NULL;
02258 const double psigmas[] = {2.0, 1.0, 0.5};
02259 const int nsigmas = sizeof(psigmas)/sizeof(double);
02260 int isigma;
02261 int iappos2[] = {1, 2};
02262 int iapneg2[] = {1, 2};
02263
02264 bug_if(0);
02265 skip_if(self == NULL);
02266 skip_if(qclist == NULL);
02267 skip_if(pthrow <= 0.0);
02268 skip_if(x4 == NULL);
02269 skip_if(y4 == NULL);
02270
02271 cpl_msg_info(cpl_func, "Detecting the 4-beam object with %g pixel throw "
02272 "using %d sigma-levels ranging from %g down to %g", pthrow,
02273 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02274
02275 bug_if(0);
02276 for (isigma = 0; isigma < nsigmas; isigma++) {
02277 int npos = 0;
02278 int nneg = 0;
02279
02280
02281 cpl_apertures_delete(appos);
02282 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02283
02284 if (appos != NULL) {
02285 npos = cpl_apertures_get_size(appos);
02286 }
02287
02288
02289
02290 cpl_apertures_delete(apneg);
02291 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02292 if (apneg != NULL) {
02293 nneg = cpl_apertures_get_size(apneg);
02294 }
02295
02296 cpl_msg_info(cpl_func, "Found %d positive (need 2) and %d negative "
02297 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02298 psigmas[isigma], 1+isigma, nsigmas);
02299
02300 if (eccmax > 0.0) {
02301 int ipos1;
02302 double eccbest = eccmax;
02303 double eccmin = DBL_MAX;
02304 double fluxbest = 0.0;
02305 double fluxecc = DBL_MAX;
02306 cpl_boolean is_first = CPL_TRUE;
02307
02308 #ifdef _OPENMP
02309 #pragma omp parallel for private(ipos1)
02310 #endif
02311 for (ipos1 = 2; ipos1 <= npos; ipos1++) {
02312 int ipos2, ineg1, ineg2;
02313 for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
02314 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
02315 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02316 cpl_boolean swappos, swapneg;
02317 const double ecc
02318 = visir_img_check_box(appos, ipos1, ipos2,
02319 apneg, ineg1, ineg2,
02320 pthrow, &swappos,
02321 &swapneg);
02322
02323 const double flux
02324 = cpl_apertures_get_flux(appos, ipos1)
02325 + cpl_apertures_get_flux(appos, ipos2)
02326 + cpl_apertures_get_flux(apneg, ineg1)
02327 + cpl_apertures_get_flux(apneg, ineg2);
02328
02329
02330 if (ecc < 0.0 || flux <= 0.0 ||
02331 !cpl_errorstate_is_equal(cleanstate)) {
02332 irplib_error_recover(cleanstate, "Invalid 4-"
02333 "object (%d & %d of %d, "
02334 "%d & %d of %d)",
02335 ipos2, ipos1, npos,
02336 ineg2, ineg1, nneg);
02337 continue;
02338 }
02339
02340 #ifdef _OPENMP
02341 #pragma omp critical(visir_img_find_beam_four_min)
02342 #endif
02343 if (ecc < eccmin)
02344 {
02345 eccmin = ecc;
02346 fluxecc = flux;
02347 }
02348
02349 if (eccmax <= ecc) continue;
02350
02351 #ifdef _OPENMP
02352 #pragma omp critical(visir_img_find_beam_four_ok)
02353 #endif
02354 if (is_first || ecc * fluxbest < eccbest * flux)
02355 {
02356 if (is_first) {
02357 is_first = CPL_FALSE;
02358 cpl_msg_info(cpl_func, "Found 4 object "
02359 "positions with throw-"
02360 "scaled eccentricity %g "
02361 "and flux %g", ecc, flux);
02362 } else {
02363 cpl_msg_info(cpl_func, "Found 4 object "
02364 "positions with throw-"
02365 "scaled eccentricity %g "
02366 "< %g and/or flux %g > %g",
02367 ecc, eccbest, flux, fluxbest);
02368 }
02369 eccbest = ecc;
02370 fluxbest = flux;
02371 iappos2[0] = swappos ? ipos2 : ipos1;
02372 iappos2[1] = swappos ? ipos1 : ipos2;
02373 iapneg2[0] = swapneg ? ineg2 : ineg1;
02374 iapneg2[1] = swapneg ? ineg1 : ineg2;
02375 }
02376 }
02377 }
02378 }
02379 }
02380 if (eccbest < eccmax) {
02381 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02382 "ECCENTRICITY", eccbest));
02383
02384 break;
02385 }
02386 if (eccmin < DBL_MAX) {
02387 cpl_msg_info(cpl_func, "Found 4 sigma-%g object positions with "
02388 "too large throw-scaled eccentricity %g >= %g and "
02389 "flux %g", psigmas[isigma], eccmin, eccmax,
02390 fluxecc);
02391 }
02392 } else if (npos >= 2 && nneg >= 2) {
02393 cpl_apertures_sort_by_flux(appos);
02394 cpl_apertures_sort_by_flux(apneg);
02395 break;
02396 }
02397
02398 if (isigma + 1 < nsigmas) {
02399 irplib_error_recover(cleanstate, "4-Beam positions not found among "
02400 "%d postive and %d negative object(s) at "
02401 "sigma=%g, (%d of %d)", npos, nneg,
02402 psigmas[isigma], 1+isigma, nsigmas);
02403 }
02404 }
02405
02406 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02407 "4-Beam positions not found w. %d sigma(s) down to %g",
02408 nsigmas, psigmas[nsigmas - 1]);
02409
02410 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02411 cpl_apertures_dump(appos, stdout);
02412 cpl_apertures_dump(apneg, stdout);
02413 }
02414
02415 x4[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
02416 y4[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
02417 x4[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
02418 y4[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
02419
02420 x4[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02421 y4[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02422 x4[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02423 y4[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02424
02425 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
02426 cpl_apertures_get_flux(appos,
02427 iappos2[0])));
02428
02429 cpl_msg_info(cpl_func, "Centroid of positive object 1 [pixel]: %g %g",
02430 x4[0], y4[0]);
02431 cpl_msg_info(cpl_func, "Centroid of positive object 2 [pixel]: %g %g",
02432 x4[1], y4[1]);
02433
02434 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02435 x4[2], y4[2]);
02436 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02437 x4[3], y4[3]);
02438
02439 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02440 pthrow);
02441 cpl_msg_info(cpl_func, "Object Pos -> Pos x/y-distance [pixel]: %g %g",
02442 x4[1] - x4[0], y4[1] - y4[0]);
02443 cpl_msg_info(cpl_func, "Object Neg -> Neg x/y-distance [pixel]: %g %g",
02444 x4[3] - x4[2], y4[3] - y4[2]);
02445 cpl_msg_info(cpl_func, "Object Pos -> Pos angle [degrees]: %g",
02446 atan2(y4[1] - y4[0], x4[1] - x4[0]) * CPL_MATH_DEG_RAD);
02447 cpl_msg_info(cpl_func, "Object Neg -> Neg angle [degrees]: %g",
02448 atan2(y4[3] - y4[2], x4[3] - x4[2]) * CPL_MATH_DEG_RAD);
02449
02450 end_skip;
02451
02452 cpl_apertures_delete(appos);
02453 cpl_apertures_delete(apneg);
02454
02455 return cpl_error_get_code();
02456 }
02457
02458
02470
02471 static
02472 cpl_image ** visir_img_collapse_beam_three(cpl_propertylist * qclist,
02473 const cpl_image * self,
02474 const cpl_image * inverse,
02475 double eccmax,
02476 double pthrow,
02477 const cpl_propertylist * plist)
02478 {
02479
02480 cpl_image ** combined = NULL;
02481 const int nx = cpl_image_get_size_x(self);
02482 const int ny = cpl_image_get_size_y(self);
02483 const cpl_type type = cpl_image_get_type(self);
02484 cpl_imagelist * list3 = cpl_imagelist_new();
02485 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02486 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02487 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02488 cpl_bivector * offs = cpl_bivector_new(3);
02489 double * x3 = cpl_bivector_get_x_data(offs);
02490 double * y3 = cpl_bivector_get_y_data(offs);
02491 double pos_x, pos_y;
02492 int i;
02493
02494 skip_if (0);
02495
02496 skip_if(plist == NULL);
02497
02498 skip_if(visir_img_find_beam_three(qclist, self, inverse, eccmax, pthrow,
02499 x3, y3));
02500
02501
02502 for (i = 1; i < 3; i++) {
02503 x3[i] = x3[0] - x3[i];
02504 y3[i] = y3[0] - y3[i];
02505 }
02506 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02507 x3[0]));
02508 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02509 y3[0]));
02510
02511 x3[0] = y3[0] = 0.0;
02512
02513 bug_if(cpl_imagelist_set(list3, (cpl_image*)self, 0));
02514 bug_if(cpl_imagelist_set(list3, (cpl_image*)inverse, 1));
02515 bug_if(cpl_imagelist_set(list3, iwrap, 2));
02516
02517 combined = cpl_geom_img_offset_saa(list3, offs, CPL_KERNEL_DEFAULT, 0, 0,
02518 CPL_GEOM_FIRST, &pos_x, &pos_y);
02519
02520 skip_if(combined == NULL);
02521
02522 end_skip;
02523
02524 cpl_bivector_delete(offs);
02525 for (i = cpl_imagelist_get_size(list3) - 1; i >= 0; i--) {
02526 (void)cpl_imagelist_unset(list3, i);
02527 }
02528 cpl_imagelist_delete(list3);
02529 (void)cpl_image_unwrap(iwrap);
02530 if (cpl_error_get_code() && combined != NULL) {
02531 cpl_image_delete(combined[0]);
02532 cpl_image_delete(combined[1]);
02533 cpl_free(combined);
02534 }
02535
02536 return combined;
02537 }
02538
02539
02540
02553
02554 static
02555 cpl_error_code visir_img_find_beam_three(cpl_propertylist * qclist,
02556 const cpl_image * self,
02557 const cpl_image * inverse,
02558 double eccmax,
02559 double pthrow,
02560 double x3[],
02561 double y3[])
02562 {
02563
02564 cpl_errorstate cleanstate = cpl_errorstate_get();
02565 cpl_apertures * appos = NULL;
02566 cpl_apertures * apneg = NULL;
02567 const double psigmas[] = {2.0, 1.0, 0.5};
02568 const int nsigmas = sizeof(psigmas)/sizeof(double);
02569 int isigma;
02570 int iappos [] = {1};
02571 int iapneg2[] = {1, 2};
02572
02573 bug_if(0);
02574 skip_if(self == NULL);
02575 skip_if(qclist == NULL);
02576 skip_if(pthrow <= 0.0);
02577 skip_if(eccmax < 0.0);
02578 skip_if(x3 == NULL);
02579 skip_if(y3 == NULL);
02580
02581
02582 cpl_msg_info(cpl_func, "Detecting the 3-beam object with %g pixel throw "
02583 "using %d sigma-levels ranging from %g down to %g", pthrow,
02584 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02585
02586 bug_if(0);
02587 for (isigma = 0; isigma < nsigmas; isigma++) {
02588 int npos = 0;
02589 int nneg = 0;
02590
02591
02592 cpl_apertures_delete(appos);
02593 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02594
02595 if (appos != NULL) {
02596 npos = cpl_apertures_get_size(appos);
02597 }
02598
02599
02600
02601 cpl_apertures_delete(apneg);
02602 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02603 if (apneg != NULL) {
02604 nneg = cpl_apertures_get_size(apneg);
02605 }
02606
02607 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
02608 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02609 psigmas[isigma], 1+isigma, nsigmas);
02610
02611 if (eccmax > 0.0) {
02612 int ipos;
02613 double eccbest = eccmax;
02614 double eccmin = DBL_MAX;
02615 double fluxbest = 0.0;
02616 double fluxecc = DBL_MAX;
02617 cpl_boolean is_first = CPL_TRUE;
02618
02619 #ifdef _OPENMP
02620 #pragma omp parallel for private(ipos)
02621 #endif
02622 for (ipos = 1; ipos <= npos; ipos++) {
02623 int ineg1, ineg2;
02624 for (ineg1 = 2; ineg1 <= nneg; ineg1++) {
02625 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02626 cpl_boolean swapnegh, swapnegv;
02627
02628 const double ecch
02629 = visir_img_check_align(appos, ipos, apneg, ineg1,
02630 ineg2, pthrow, CPL_TRUE,
02631 &swapnegh);
02632 const double eccv
02633 = visir_img_check_align(appos, ipos, apneg, ineg1,
02634 ineg2, pthrow, CPL_FALSE,
02635 &swapnegv);
02636 const double ecc = ecch < eccv ? ecch : eccv;
02637 const cpl_boolean swapneg = ecch < eccv
02638 ? swapnegh : swapnegv;
02639
02640 const double flux
02641 = cpl_apertures_get_flux(appos, ipos)
02642 + cpl_apertures_get_flux(apneg, ineg1)
02643 + cpl_apertures_get_flux(apneg, ineg2);
02644
02645
02646 if (ecc < 0.0 || flux <= 0.0 ||
02647 !cpl_errorstate_is_equal(cleanstate)) {
02648 irplib_error_recover(cleanstate, "Invalid 3-"
02649 "object (%d of %d, "
02650 "%d & %d of %d)",
02651 ipos, npos,
02652 ineg2, ineg1, nneg);
02653 continue;
02654 }
02655
02656 #ifdef _OPENMP
02657 #pragma omp critical(visir_img_collapse_beam_three_min)
02658 #endif
02659 if (ecc < eccmin)
02660 {
02661 eccmin = ecc;
02662 fluxecc = flux;
02663 }
02664
02665 if (eccmax <= ecc) continue;
02666
02667 #ifdef _OPENMP
02668 #pragma omp critical(visir_img_collapse_beam_three_ok)
02669 #endif
02670 if (is_first || ecc * fluxbest < eccbest * flux)
02671 {
02672 if (is_first) {
02673 is_first = CPL_FALSE;
02674 cpl_msg_info(cpl_func, "Found 3 object posi"
02675 "tions with throw-scaled (ver"
02676 "tical/horizontal) eccentrici"
02677 "ty %g/%g and flux %g", eccv,
02678 ecch, flux);
02679 } else {
02680 cpl_msg_info(cpl_func, "Found 3 object posi"
02681 "tions with throw-scaled (ver"
02682 "tical/horizontal) eccentrici"
02683 "ty %g/%g < %g and/or flux %g "
02684 "> %g", eccv, ecch, eccbest,
02685 flux, fluxbest);
02686 }
02687 eccbest = ecc;
02688 fluxbest = flux;
02689 iappos[0] = ipos;
02690 iapneg2[0] = swapneg ? ineg2 : ineg1;
02691 iapneg2[1] = swapneg ? ineg1 : ineg2;
02692 }
02693 }
02694 }
02695 }
02696 if (eccbest < eccmax) {
02697 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02698 "ECCENTRICITY", eccbest));
02699 break;
02700 }
02701 if (eccmin < DBL_MAX) {
02702 cpl_msg_info(cpl_func, "Found 3 sigma-%g object positions with "
02703 "too large throw-scaled eccentricity %g >= %g and "
02704 "flux %g", psigmas[isigma], eccmin, eccmax,
02705 fluxecc);
02706 }
02707 } else if (npos >= 1 && nneg >= 2) {
02708 cpl_apertures_sort_by_flux(appos);
02709 cpl_apertures_sort_by_flux(apneg);
02710 break;
02711 }
02712
02713 if (isigma + 1 < nsigmas) {
02714 irplib_error_recover(cleanstate, "3-Beam positions not found among "
02715 "%d postive and %d negative object(s) at "
02716 "sigma=%g, (%d of %d)", npos, nneg,
02717 psigmas[isigma], 1+isigma, nsigmas);
02718 }
02719 }
02720
02721 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02722 "3-Beam positions not found w. %d sigma(s) down to %g",
02723 nsigmas, psigmas[nsigmas - 1]);
02724
02725 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02726 cpl_apertures_dump(appos, stdout);
02727 cpl_apertures_dump(apneg, stdout);
02728 }
02729
02730 x3[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
02731 y3[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
02732
02733 x3[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02734 y3[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02735 x3[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02736 y3[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02737
02738 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
02739 cpl_apertures_get_flux(appos,
02740 iappos[0])));
02741
02742 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
02743 x3[0], y3[0]);
02744
02745 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02746 x3[1], y3[1]);
02747 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02748 x3[2], y3[2]);
02749
02750 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02751 pthrow);
02752 cpl_msg_info(cpl_func, "Object Neg1 -> Pos x/y-distance [pixel]: %g %g",
02753 x3[2] - x3[0], y3[2] - y3[0]);
02754 cpl_msg_info(cpl_func, "Object Pos -> Neg2 x/y-distance [pixel]: %g %g",
02755 x3[0] - x3[1], y3[0] - y3[1]);
02756
02757 end_skip;
02758
02759 cpl_apertures_delete(appos);
02760 cpl_apertures_delete(apneg);
02761
02762 return cpl_error_get_code();
02763 }
02764
02765
02766
02780
02781 cpl_error_code visir_img_find_beam_two(cpl_propertylist * qclist,
02782 const cpl_image * self,
02783 const cpl_image * inverse,
02784 double eccmax,
02785 double pthrow,
02786 double x2[],
02787 double y2[])
02788 {
02789
02790 cpl_errorstate cleanstate = cpl_errorstate_get();
02791 cpl_apertures * appos = NULL;
02792 cpl_apertures * apneg = NULL;
02793 const double psigmas[] = {2.0, 1.0, 0.5};
02794 const int nsigmas = sizeof(psigmas)/sizeof(double);
02795 int isigma;
02796 int iappos[] = {1};
02797 int iapneg[] = {1};
02798
02799 bug_if(0);
02800 skip_if(self == NULL);
02801 skip_if(qclist == NULL);
02802 skip_if(eccmax < 0.0);
02803 skip_if(x2 == NULL);
02804 skip_if(y2 == NULL);
02805
02806 if (pthrow > 0.0) {
02807 cpl_msg_info(cpl_func, "Detecting the 2-beam object (Pos -> Neg) with "
02808 "%g pixel throw using %d sigma-levels ranging from %g down"
02809 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
02810 } else if (pthrow < 0.0) {
02811 cpl_msg_info(cpl_func, "Detecting the 2-beam object (Neg -> Pos) with "
02812 "%g pixel throw using %d sigma-levels ranging from %g down"
02813 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
02814 } else {
02815 skip_if(1);
02816 }
02817
02818 bug_if(0);
02819 for (isigma = 0; isigma < nsigmas; isigma++) {
02820 int npos = 0;
02821 int nneg = 0;
02822
02823
02824 cpl_apertures_delete(appos);
02825 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02826
02827 if (appos != NULL) {
02828 npos = cpl_apertures_get_size(appos);
02829 }
02830
02831
02832
02833 cpl_apertures_delete(apneg);
02834 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02835 if (apneg != NULL) {
02836 nneg = cpl_apertures_get_size(apneg);
02837 }
02838
02839 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
02840 "(need 1) object(s) at sigma=%g (%d of %d)", npos, nneg,
02841 psigmas[isigma], 1+isigma, nsigmas);
02842
02843 if (eccmax > 0.0) {
02844 int ipos;
02845 double eccbest = eccmax;
02846 double eccmin = DBL_MAX;
02847 double fluxbest = 0.0;
02848 double fluxecc = DBL_MAX;
02849 cpl_boolean is_first = CPL_TRUE;
02850
02851 #ifdef _OPENMP
02852 #pragma omp parallel for private(ipos)
02853 #endif
02854 for (ipos = 1; ipos <= npos; ipos++) {
02855 int ineg;
02856 for (ineg = 1; ineg <= nneg; ineg++) {
02857 const double ecc = pthrow > 0.0
02858 ? visir_img_check_line(appos, ipos, apneg, ineg,
02859 pthrow, CPL_FALSE)
02860 : visir_img_check_line(apneg, ineg, appos, ipos,
02861 -pthrow, CPL_FALSE);
02862
02863 const double flux
02864 = cpl_apertures_get_flux(appos, ipos)
02865 + cpl_apertures_get_flux(apneg, ineg);
02866
02867
02868 if (ecc < 0.0 || flux <= 0.0 ||
02869 !cpl_errorstate_is_equal(cleanstate)) {
02870 irplib_error_recover(cleanstate, "Invalid 2-"
02871 "object (%d of %d, "
02872 "%d of %d)",
02873 ipos, npos,
02874 ineg, nneg);
02875 continue;
02876 }
02877
02878 #ifdef _OPENMP
02879 #pragma omp critical(visir_img_collapse_beam_two_min)
02880 #endif
02881 if (ecc < eccmin)
02882 {
02883 eccmin = ecc;
02884 fluxecc = flux;
02885 }
02886
02887 if (eccmax <= ecc) continue;
02888
02889 #ifdef _OPENMP
02890 #pragma omp critical(visir_img_collapse_beam_two_ok)
02891 #endif
02892 if (is_first || ecc * fluxbest < eccbest * flux)
02893 {
02894 if (is_first) {
02895 is_first = CPL_FALSE;
02896 cpl_msg_info(cpl_func, "Found 2 object posi"
02897 "tions with throw-scaled eccen"
02898 "tricity %g and flux %g", ecc,
02899 flux);
02900 } else {
02901 cpl_msg_info(cpl_func, "Found 2 object posi"
02902 "tions with throw-scaled eccen"
02903 "tricity %g < %g and/or flux %g "
02904 "> %g", ecc, eccbest, flux,
02905 fluxbest);
02906 }
02907 eccbest = ecc;
02908 fluxbest = flux;
02909 iappos[0] = ipos;
02910 iapneg[0] = ineg;
02911 }
02912 }
02913 }
02914 if (eccbest < eccmax) {
02915 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02916 "ECCENTRICITY", eccbest));
02917 break;
02918 }
02919 if (eccmin < DBL_MAX) {
02920 cpl_msg_info(cpl_func, "Found 2 sigma-%g object positions with "
02921 "too large throw-scaled eccentricity %g >= %g and "
02922 "flux %g", psigmas[isigma], eccmin, eccmax,
02923 fluxecc);
02924 }
02925 } else if (npos >= 1 && nneg >= 2) {
02926 cpl_apertures_sort_by_flux(appos);
02927 cpl_apertures_sort_by_flux(apneg);
02928 break;
02929 }
02930
02931 if (isigma + 1 < nsigmas) {
02932 irplib_error_recover(cleanstate, "2-Beam positions not found among "
02933 "%d postive and %d negative object(s) at "
02934 "sigma=%g, (%d of %d)", npos, nneg,
02935 psigmas[isigma], 1+isigma, nsigmas);
02936 }
02937 }
02938
02939 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02940 "2-Beam positions not found w. %d sigma(s) down to %g",
02941 nsigmas, psigmas[nsigmas - 1]);
02942
02943 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02944 cpl_apertures_dump(appos, stdout);
02945 cpl_apertures_dump(apneg, stdout);
02946 }
02947
02948 x2[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
02949 y2[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
02950
02951 x2[1] = cpl_apertures_get_centroid_x(apneg, iapneg[0]);
02952 y2[1] = cpl_apertures_get_centroid_y(apneg, iapneg[0]);
02953
02954 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
02955 cpl_apertures_get_flux(appos,
02956 iappos[0])));
02957
02958 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
02959 x2[0], y2[0]);
02960
02961 cpl_msg_info(cpl_func, "Centroid of negative object [pixel]: %g %g",
02962 x2[1], y2[1]);
02963
02964 if (pthrow > 0.0) {
02965 cpl_msg_info(cpl_func, "Expected object distance (chop throw) "
02966 "[pixel]: %g", pthrow);
02967
02968 cpl_msg_info(cpl_func, "Object Pos -> Neg x/y-distance [pixel]: %g %g",
02969 x2[1] - x2[0], y2[1] - y2[0]);
02970 } else {
02971 cpl_msg_info(cpl_func, "Expected object distance (chop throw) "
02972 "[pixel]: %g", -pthrow);
02973
02974 cpl_msg_info(cpl_func, "Object Neg -> x/y-distance [pixel]: %g %g",
02975 x2[0] - x2[1], y2[0] - y2[1]);
02976 }
02977
02978 end_skip;
02979
02980 cpl_apertures_delete(appos);
02981 cpl_apertures_delete(apneg);
02982
02983 return cpl_error_get_code();
02984 }
02985
02986
02987
02988
03007
03008 double visir_img_check_box(const cpl_apertures * appos,
03009 int ipos1, int ipos2,
03010 const cpl_apertures * apneg,
03011 int ineg1, int ineg2, double ssize,
03012 cpl_boolean * pswapp, cpl_boolean * pswapn)
03013 {
03014
03015
03016
03017
03018 const double xp1 = cpl_apertures_get_centroid_x(appos, ipos1);
03019 const double xp2 = cpl_apertures_get_centroid_x(appos, ipos2);
03020 const double yp1 = cpl_apertures_get_centroid_y(appos, ipos1);
03021 const double yp2 = cpl_apertures_get_centroid_y(appos, ipos2);
03022
03023
03024 const double xpl = xp1 < xp2 ? xp1 : xp2;
03025 const double ypl = xp1 < xp2 ? yp1 : yp2;
03026
03027
03028 const double xpr = xp1 < xp2 ? xp2 : xp1;
03029 const double ypr = xp1 < xp2 ? yp2 : yp1;
03030
03031
03032 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
03033 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
03034 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
03035 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
03036
03037
03038 const double xnl = xn1 < xn2 ? xn1 : xn2;
03039 const double ynl = xn1 < xn2 ? yn1 : yn2;
03040
03041
03042 const double xnr = xn1 < xn2 ? xn2 : xn1;
03043 const double ynr = xn1 < xn2 ? yn2 : yn1;
03044
03045 const double lx1 = xnr - xpl;
03046 const double lx2 = xpr - xnl;
03047 const double ly1 = ypl - ynl;
03048 const double ly2 = ynr - ypr;
03049
03050 const double dx1 = lx1 - ssize;
03051 const double dx2 = lx2 - ssize;
03052 const double dy1 = ly1 - ssize;
03053 const double dy2 = ly2 - ssize;
03054
03055 const double ey1 = ynr - ypl;
03056 const double ey2 = ypr - ynl;
03057 const double ex1 = xpl - xnl;
03058 const double ex2 = xpr - xnr;
03059
03060 const double ok = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
03061 ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
03062
03063 double result = -1.0;
03064
03065 skip_if(0);
03066
03067 skip_if(pswapp == NULL);
03068 skip_if(pswapn == NULL);
03069 skip_if(appos == apneg);
03070 skip_if(ipos1 == ipos2);
03071 skip_if(ineg1 == ineg2);
03072
03073 skip_if(ssize <= 0.0);
03074
03075 *pswapp = xp1 < xp2 ? CPL_FALSE : CPL_TRUE;
03076 *pswapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
03077
03078 result = ok/ssize;
03079
03080 end_skip;
03081
03082 return result;
03083
03084 }
03085
03086
03087
03106
03107 double visir_img_check_align(const cpl_apertures * appos, int ipos,
03108 const cpl_apertures * apneg, int ineg1, int ineg2,
03109 double ssize, cpl_boolean is_hor,
03110 cpl_boolean * pswapn)
03111 {
03112
03113
03114
03115
03116 const double xp = cpl_apertures_get_centroid_x(appos, ipos);
03117 const double yp = cpl_apertures_get_centroid_y(appos, ipos);
03118
03119
03120 const double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1);
03121 const double yn1 = cpl_apertures_get_centroid_y(apneg, ineg1);
03122 const double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2);
03123 const double yn2 = cpl_apertures_get_centroid_y(apneg, ineg2);
03124
03125 double result = -1.0;
03126
03127 double ok;
03128
03129 cpl_boolean swapn;
03130
03131 if (is_hor) {
03132
03133 const double xnl = xn1 < xn2 ? xn1 : xn2;
03134 const double ynl = xn1 < xn2 ? yn1 : yn2;
03135
03136
03137 const double xnr = xn1 < xn2 ? xn2 : xn1;
03138 const double ynr = xn1 < xn2 ? yn2 : yn1;
03139
03140 const double d1 = xnr - xp - ssize;
03141 const double d2 = xp - xnl - ssize;
03142
03143 const double e1 = ynr - yp;
03144 const double e2 = yp - ynl;
03145
03146 swapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
03147
03148 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
03149
03150 } else {
03151
03152 const double xnl = yn1 < yn2 ? xn1 : xn2;
03153 const double ynl = yn1 < yn2 ? yn1 : yn2;
03154
03155
03156 const double xnr = yn1 < yn2 ? xn2 : xn1;
03157 const double ynr = yn1 < yn2 ? yn2 : yn1;
03158
03159 const double d1 = ynr - yp - ssize;
03160 const double d2 = yp - ynl - ssize;
03161
03162 const double e1 = xnr - xp;
03163 const double e2 = xp - xnl;
03164
03165 swapn = yn1 < yn2 ? CPL_FALSE : CPL_TRUE;
03166
03167 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
03168
03169 }
03170
03171 skip_if(0);
03172
03173 skip_if(pswapn == NULL);
03174 skip_if(appos == apneg);
03175 skip_if(ineg1 == ineg2);
03176
03177 skip_if(ssize <= 0.0);
03178
03179 *pswapn = swapn;
03180
03181 result = ok/ssize;
03182
03183 end_skip;
03184
03185 return result;
03186
03187 }
03188
03189
03190
03207
03208 double visir_img_check_line(const cpl_apertures * apnear, int inear,
03209 const cpl_apertures * apfar, int ifar,
03210 double ssize, cpl_boolean is_hor)
03211 {
03212
03213
03214
03215
03216 const double xn = cpl_apertures_get_centroid_x(apnear, inear);
03217 const double yn = cpl_apertures_get_centroid_y(apnear, inear);
03218
03219
03220 const double xf = cpl_apertures_get_centroid_x(apfar, ifar);
03221 const double yf = cpl_apertures_get_centroid_y(apfar, ifar);
03222
03223 double result = -1.0;
03224
03225 double ok;
03226
03227 if (is_hor) {
03228
03229 const double d = xf - xn - ssize;
03230
03231 const double e = yf - yn;
03232
03233 ok = sqrt(d * d + e * e);
03234
03235 } else {
03236
03237 const double d = yf - yn - ssize;
03238
03239 const double e = xf - xn;
03240
03241 ok = sqrt(d * d + e * e);
03242
03243 }
03244
03245 skip_if(0);
03246
03247 skip_if(apnear == apfar);
03248
03249 skip_if(ssize <= 0.0);
03250
03251 result = ok/ssize;
03252
03253 end_skip;
03254
03255 return result;
03256
03257 }
03258
03259
03260
03271
03272 static cpl_error_code visir_get_type(const irplib_framelist * rawframes,
03273 int pos, visir_cube_type * ptype,
03274 int * pnaxis3, int * pnchop) {
03275
03276
03277
03278 cpl_errorstate cleanstate = cpl_errorstate_get();
03279 const char * file
03280 = cpl_frame_get_filename(irplib_framelist_get_const(rawframes, pos));
03281 const cpl_propertylist * plist
03282 = irplib_framelist_get_propertylist_const(rawframes, pos);
03283 const int nchop = visir_pfits_get_chop_ncycles(plist);
03284 const int naxis3 = visir_pfits_get_naxis3(plist);
03285 const char * sval = NULL;
03286
03287
03288
03289
03290 skip_if(0);
03291 bug_if(ptype == NULL);
03292 bug_if(pnaxis3 == NULL);
03293
03294 sval = visir_pfits_get_frame_type(plist);
03295 if (sval == NULL) {
03296
03297 visir_error_reset("Could not get FITS key");
03298
03299 } else if (strcmp(sval, "CUBE1")==0) {
03300 *ptype = VISIR_CUBE1;
03301 } else if (strcmp(sval, "CUBE2")==0) {
03302 *ptype = VISIR_CUBE2;
03303 }
03304
03305 if (*ptype == VISIR_CUBE2) {
03306 if (naxis3 == 2 * nchop + 1) {
03307
03308 } else if (naxis3 == nchop + 2) {
03309 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03310 "and CHOP NCYCLES=%d imply a CUBE1. Assuming "
03311 "the frame type is really CUBE1", file, sval,
03312 naxis3, nchop);
03313 *ptype = VISIR_CUBE1;
03314 } else {
03315 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03316 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
03317 "Half-Cycle format", file, sval, naxis3, nchop);
03318 skip_if(1);
03319 }
03320 } else if (*ptype == VISIR_CUBE1) {
03321 if (naxis3 == nchop + 2) {
03322
03323 if (nchop > 1)
03324 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
03325 "Cycle frame (old CUBE1-format)", file, nchop);
03326
03327 } else if (naxis3 == 2 * nchop + 1) {
03328 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03329 "and CHOP NCYCLES=%d imply a CUBE2. Assuming "
03330 "the frame type is really CUBE2", file, sval,
03331 naxis3, nchop);
03332 *ptype = VISIR_CUBE2;
03333 } else {
03334 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03335 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
03336 "Half-Cycle format", file, sval, naxis3, nchop);
03337 skip_if(1);
03338 }
03339 } else if (naxis3 == 2 * nchop + 1) {
03340 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
03341 "CHOP NCYCLES=%d imply a CUBE2. Assuming the frame "
03342 "type is CUBE2", file, sval ? sval : "<NULL>", naxis3,
03343 nchop);
03344 *ptype = VISIR_CUBE2;
03345 } else if (naxis3 == nchop + 2) {
03346 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
03347 "CHOP NCYCLES=%d imply a CUBE1. Assuming the frame "
03348 "type is CUBE1", file, sval ? sval : "<NULL>", naxis3,
03349 nchop);
03350 *ptype = VISIR_CUBE1;
03351 } else {
03352 return cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
03353 "%s has FRAM TYPE='%s', NAXIS3 = %d and "
03354 "CHOP NCYCLES = %d", file,
03355 sval ? sval : "<NULL>", naxis3, nchop);
03356 }
03357
03358 *pnaxis3 = naxis3;
03359 *pnchop = nchop;
03360
03361 end_skip;
03362
03363 return cpl_error_get_code();
03364 }
03365
03366
03367
03375
03376 cpl_error_code visir_img_burst_find_delta_chop(const cpl_propertylist * self,
03377 int * ichopchange, int * ihalfcycle)
03378 {
03379
03380 const char * sdateobs =
03381 cpl_propertylist_get_string(self, VISIR_PFITS_STRING_OBS_START);
03382 const char * schopstart =
03383 cpl_propertylist_get_string(self, VISIR_PFITS_STRING_CHOP_START);
03384 const double chop_freq =
03385 cpl_propertylist_get_double(self, VISIR_PFITS_DOUBLE_CHOP_FREQ);
03386 const int nditskip =
03387 cpl_propertylist_get_int(self, VISIR_PFITS_INT_NDITSKIP);
03388 const double dit = visir_pfits_get_dit(self);
03389 double ddateobs, dchopstart;
03390 double period;
03391
03392 skip_if(0);
03393
03394 bug_if(irplib_wcs_mjd_from_string(&ddateobs, sdateobs));
03395 bug_if(irplib_wcs_mjd_from_string(&dchopstart, schopstart));
03396
03397 skip_if(chop_freq <= 0.0);
03398 skip_if(dit <= 0.0);
03399
03400
03401 ddateobs += dit * nditskip / (double)VISIR_SECS_PER_DAY;
03402
03403 period = 1.0/(chop_freq * dit);
03404
03405
03406 bug_if((int)(period + 0.5) % 2 != 0);
03407
03408 *ihalfcycle = (int)(period + 0.5)/2;
03409
03410 cpl_msg_info(cpl_func, "Number of A+B frames in one full chopping cycle: %g",
03411 period);
03412
03413 if (dchopstart < ddateobs) {
03414 double tchop = (ddateobs - dchopstart) * (double)VISIR_SECS_PER_DAY;
03415
03416 double dprecycle = tchop * chop_freq;
03417
03418
03419 const double phase = ceil(dprecycle) - dprecycle;
03420
03421
03422 *ichopchange = (int)ceil(phase * period) - 1;
03423
03424 cpl_msg_info(cpl_func, "Chopping started %gs (%f cycles) before OBS start: "
03425 "%f < %f", tchop, dprecycle, dchopstart, ddateobs);
03426
03427 } else if (ddateobs < dchopstart) {
03428
03429
03430 double tchop = (dchopstart - ddateobs) * (double)VISIR_SECS_PER_DAY;
03431 *ichopchange = (int)ceil(tchop / dit) - 1;
03432 cpl_msg_info(cpl_func, "Chopping started %gs (wasted %g cycles) after OBS "
03433 "start: %f > %f", tchop, tchop * chop_freq, dchopstart,
03434 ddateobs);
03435 } else {
03436
03437
03438
03439 *ichopchange = 0;
03440 cpl_msg_info(cpl_func, "Chopping started with OBS start: %f == %f",
03441 dchopstart, ddateobs);
03442 }
03443
03444
03445 *ichopchange = *ichopchange % (*ihalfcycle * 2);
03446
03447 cpl_msg_info(cpl_func, "Frame of chop change: %d", *ichopchange);
03448
03449 end_skip;
03450
03451 return cpl_error_get_code();
03452 }
03453
03454 #include "visir_destripe.c"