30 #include "visir_utils.h"
31 #include "visir_pfits.h"
32 #include "visir_parameter.h"
33 #include "visir_pfits.h"
34 #include "visir_spc_distortion.h"
35 #include "visir_inputs.h"
36 #include "irplib_framelist.h"
37 #include "irplib_wcs.h"
49 #define VISIR_SECS_PER_DAY (24 * 3600)
51 #define FIND_BEAM_MAX_APERTURES_SQR (40 * 40)
58 #include "visir_destripe.h"
60 static cpl_image * visir_load_average(
const char *,
61 const cpl_propertylist *);
62 static cpl_imagelist * visir_load_intermint(
const irplib_framelist *,
int);
63 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
64 static cpl_error_code visir_rem_glitch(cpl_image *);
65 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
66 static cpl_error_code visir_offset_hcycle(cpl_image *);
68 static cpl_image ** visir_img_collapse_beam_four(cpl_propertylist *,
71 double,
double,
double,
72 const cpl_propertylist *);
74 static cpl_image ** visir_img_collapse_beam_three(cpl_propertylist *,
78 const cpl_propertylist *);
81 static cpl_error_code visir_img_find_beam_three(cpl_propertylist *,
84 double,
double,
double,
88 static cpl_error_code visir_img_find_beam_four(cpl_propertylist *,
91 double,
double,
double,
121 cpl_error_code visir_load_cube2_split_(cpl_imagelist * alist, cpl_imagelist * blist,
122 cpl_imagelist * packed, cpl_image * prevd)
125 int naxis3 = cpl_imagelist_get_size(packed);
126 int prevd_insert_pos = cpl_imagelist_get_size(blist);
128 bug_if(alist == NULL);
129 bug_if(blist == NULL);
133 cpl_imagelist_set(blist, prevd, prevd_insert_pos);
136 for (
int i = 0; i < naxis3/2; i++) {
137 cpl_image * aimage = cpl_imagelist_unset(packed, 0);
138 cpl_image * dimage = cpl_imagelist_unset(packed, 0);
140 cpl_imagelist_set(alist, aimage, cpl_imagelist_get_size(alist));
141 cpl_imagelist_set(blist, dimage, cpl_imagelist_get_size(blist));
145 skip_if_lt(0, cpl_imagelist_get_size(packed),
"Too many packed frames");
148 bug_if(visir_imagelist_unpack_interm(blist));
152 cpl_imagelist_unset(blist, prevd_insert_pos);
154 for (
int i = 0; i < naxis3/2; i++) {
155 cpl_image * aimage = cpl_imagelist_get(alist, i);
156 cpl_image * dimage = cpl_imagelist_get(blist, i);
158 cpl_image * bimage = cpl_image_subtract_create(aimage, dimage);
160 visir_offset_hcycle(aimage);
161 visir_offset_hcycle(bimage);
163 bug_if(cpl_imagelist_set(blist, bimage, i));
167 skip_if_lt(0, cpl_imagelist_get_size(packed),
"Too many packed frames");
171 return cpl_error_get_code();
189 static cpl_imagelist * load_range(
const char * filename,
196 cpl_imagelist *
self = cpl_imagelist_new();
198 for (
int iplane = pstart; iplane < pend; iplane++) {
199 cpl_image * image = cpl_image_load(filename, im_type, iplane, iext);
201 if (image == NULL)
break;
203 if (cpl_imagelist_set(
self, image, selfsize)) {
204 cpl_image_delete(image);
239 const irplib_framelist * rawframes,
int pos,
240 const int planestart,
const int planeend)
243 cpl_imagelist * packed = NULL;
245 const char * file = cpl_frame_get_filename(frame);
247 visir_data_type data_type;
249 cpl_image * prevd = NULL;
250 const cpl_propertylist * plist =
252 const int iext = cpl_propertylist_has(plist,
"ZNAXIS3") ? 1 : 0;
257 skip_if(visir_get_data_type(frame, plist, &data_type, NULL));
259 cpl_ensure_code(data_type == VISIR_DATA_CUBE2, CPL_ERROR_ILLEGAL_INPUT);
265 error_if(planestart % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
266 "Plane start %d wrong. It must be even.", planestart);
267 error_if(planeend < naxis3 && planeend % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
268 "Plane end %d wrong. It must be even if not larger naxis3=%d",
271 any_if(
"Cannot split non-CUBE2 frame %d/%d in %s", 1+pos,
273 bug_if(alist == NULL);
274 bug_if(blist == NULL);
276 error_if(data_type != VISIR_DATA_CUBE2, CPL_ERROR_INCOMPATIBLE_INPUT,
277 "Cannot split non-CUBE2 frame %d/%d w. NAXIS3=%d, "
278 "NCYCLES=%d in %s", 1+pos,
281 if (planeend >= naxis3 || planeend < 0)
286 if (planestart != 0) {
287 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
288 iext, planestart - 1, pend);
289 prevd = cpl_imagelist_unset(packed, 0);
292 packed = load_range(file, CPL_TYPE_UNSPECIFIED, iext, planestart, pend);
294 skip_if(visir_load_cube2_split_(alist, blist, packed, prevd));
298 cpl_image_delete(prevd);
299 cpl_imagelist_delete(packed);
301 return cpl_error_get_code();
324 cpl_error_code visir_load_burst_(cpl_imagelist * alist, cpl_imagelist * blist,
325 cpl_imagelist * packed,
326 const int ichopchange,
const int ihalfcycle,
327 const int trimlow,
int const trimhigh)
329 cpl_boolean bon = CPL_TRUE;
330 const int offset = 0;
331 const int pend = cpl_imagelist_get_size(packed);
332 int lorej = ihalfcycle - trimlow;
333 int hirej = trimhigh + 1;
337 int chpmv = ichopchange - ihalfcycle * 2;
339 cpl_ensure_code(trimhigh >= -1, CPL_ERROR_ILLEGAL_INPUT);
340 cpl_ensure_code(trimlow >= 0, CPL_ERROR_ILLEGAL_INPUT);
341 cpl_ensure_code(ichopchange < ihalfcycle * 2, CPL_ERROR_ILLEGAL_INPUT);
342 cpl_ensure_code(alist != NULL, CPL_ERROR_NULL_INPUT);
343 cpl_ensure_code(blist != NULL, CPL_ERROR_NULL_INPUT);
350 for (
int i = chpmv; i < pend; i++) {
351 if ((i + ihalfcycle * 2) % ihalfcycle == ichopchange % ihalfcycle) {
353 hirej = trimhigh + 1;
354 lorej = ihalfcycle - trimlow;
356 if (hirej <= 0 && lorej > 0 && i >= 0) {
358 cpl_image * image= cpl_imagelist_unset(packed, offset);
359 cpl_imagelist_set(alist, image, cpl_imagelist_get_size(alist));
362 cpl_image * image= cpl_imagelist_unset(packed, offset);
363 cpl_imagelist_set(blist, image, cpl_imagelist_get_size(blist));
367 cpl_image_delete(cpl_imagelist_unset(packed, offset));
373 cpl_msg_info(cpl_func,
"On: %d, Off %d, Skipped %d",
374 (
int)cpl_imagelist_get_size(alist),
375 (
int)cpl_imagelist_get_size(blist),
376 (
int)(pend - cpl_imagelist_get_size(alist)
377 - cpl_imagelist_get_size(blist)));
379 skip_if_lt(0, cpl_imagelist_get_size(packed),
"Too many packed frames");
383 return cpl_error_get_code();
397 static int get_to_off_plane(
int chopchange,
const int offset,
398 const int ihalfcycle)
400 const int ifullcycle = ihalfcycle * 2;
403 (offset / ifullcycle) * ifullcycle > chopchange)
404 chopchange += ifullcycle - (offset % ifullcycle);
406 chopchange -= (offset % ifullcycle);
433 cpl_error_code visir_load_burst(cpl_imagelist * alist, cpl_imagelist * blist,
434 const cpl_frame * frame,
const cpl_propertylist * plist,
435 const int ichopchange,
const int ihalfcycle,
436 const int planestart,
const int planeend,
437 const int trimlow,
const int trimhigh)
439 const char * file = cpl_frame_get_filename(frame);
441 const int pend = planeend <= 0 || planeend > naxis3 ? naxis3 : planeend;
442 cpl_imagelist * packed;
443 int to_off = get_to_off_plane(ichopchange, planestart, ihalfcycle);
445 cpl_msg_info(cpl_func,
"Loading planes %d to %d, to off %d",
446 planestart, pend, planestart + to_off);
448 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
449 cpl_propertylist_has(plist,
"ZNAXIS3") ? 1 : 0,
452 skip_if(packed == NULL);
454 if (cpl_imagelist_get_size(packed) > 0) {
455 cpl_image * timg = cpl_imagelist_get(packed, 0);
456 size_t nbytes = visir_get_nbytes(timg);
457 visir_drop_cache(file, 0, nbytes * pend);
460 skip_if(visir_load_burst_(alist, blist, packed, to_off, ihalfcycle,
465 cpl_imagelist_delete(packed);
467 return cpl_error_get_code();
472 visir_load_burst_aqu(cpl_imagelist * alist, cpl_imagelist * blist,
473 const cpl_frame * frame,
const cpl_propertylist * plist,
474 const int ihalfcycle,
475 const int planestart,
const int planeend)
477 const char * file = cpl_frame_get_filename(frame);
479 const int pend = planeend <= 0 || planeend > naxis3 ? naxis3 : planeend;
480 cpl_imagelist * packed;
482 cpl_msg_info(cpl_func,
"Loading planes %d to %d",
485 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
486 cpl_propertylist_has(plist,
"ZNAXIS3") ? 1 : 0,
489 skip_if(packed == NULL);
491 if (cpl_imagelist_get_size(packed) > 0) {
492 cpl_image * timg = cpl_imagelist_get(packed, 0);
493 size_t nbytes = visir_get_nbytes(timg);
494 visir_drop_cache(file, 0, nbytes * pend);
497 cpl_boolean bon = CPL_FALSE;
499 for (
size_t i = planestart; i < pend; i++) {
501 cpl_image * image = cpl_imagelist_unset(packed, 0);
502 cpl_imagelist_set(alist, image, cpl_imagelist_get_size(alist));
505 cpl_image * image = cpl_imagelist_unset(packed, 0);
506 cpl_imagelist_set(blist, image, cpl_imagelist_get_size(blist));
509 if (it == ihalfcycle){
517 cpl_imagelist_delete(packed);
519 return cpl_error_get_code();
547 const cpl_image *
self,
548 const cpl_parameterlist * parlist,
549 const char * recipename,
550 visir_chopnod_mode mode,
551 const cpl_propertylist * plist)
554 cpl_image ** combined = NULL;
556 cpl_image * inverse = cpl_image_multiply_scalar_create(
self, -1.0);
563 const double pthrow = pscale > 0.0
567 skip_if(
self == NULL);
568 skip_if(parlist == NULL);
569 skip_if(qclist == NULL);
570 skip_if(plist == NULL);
572 if (mode == VISIR_CHOPNOD_PERPENDICULAR) {
574 combined = visir_img_collapse_beam_four(qclist,
self, inverse, eccmax,
575 pthrow, angle, plist);
576 }
else if (mode == VISIR_CHOPNOD_PARALLEL) {
578 combined = visir_img_collapse_beam_three(qclist,
self, inverse, eccmax,
580 }
else if (mode == VISIR_CHOPNOD_AUTO) {
581 cpl_errorstate cleanstate = cpl_errorstate_get();
585 if (sdir != NULL && !strcmp(sdir,
"PERPENDICULAR")) {
587 combined = visir_img_collapse_beam_four(qclist,
self, inverse,
588 eccmax, pthrow, angle, plist);
589 }
else if (sdir != NULL && !strcmp(sdir,
"PARALLEL")) {
591 combined = visir_img_collapse_beam_three(qclist,
self, inverse,
592 eccmax, pthrow, plist);
595 visir_error_reset(
"Could not get FITS key");
597 cpl_msg_warning(cpl_func,
"Unknown chopping direction: %s",
600 cpl_msg_warning(cpl_func,
"Proceeding as if FITS card "
601 VISIR_PFITS_STRING_CHOPNOD_DIR
" had value: %s",
603 combined = visir_img_collapse_beam_four(qclist,
self, inverse,
604 eccmax, pthrow, angle, plist);
605 if (combined == NULL) {
606 visir_error_reset(
"Proceeding as if FITS card "
607 VISIR_PFITS_STRING_CHOPNOD_DIR
608 " had value: %s",
"PARALLEL");
609 combined = visir_img_collapse_beam_three(qclist,
self, inverse,
610 eccmax, pthrow, plist);
617 skip_if(combined == NULL);
619 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM THROW",
621 bug_if (cpl_propertylist_set_comment(qclist,
"ESO QC ONEBEAM THROW",
622 "The throw in pixels (TEL CHOP THROW "
623 "divided by INS PFOV)"));
625 bug_if (cpl_propertylist_set_comment(qclist,
"ESO QC ONEBEAM XPOS",
626 "The X pixel position (centroid) "
627 "of the one-beam object"));
629 bug_if (cpl_propertylist_set_comment(qclist,
"ESO QC ONEBEAM YPOS",
630 "The Y pixel position (centroid) "
631 "of the one-beam object"));
632 bug_if (cpl_propertylist_set_comment(qclist,
"ESO QC ONEBEAM ECCENTRICITY",
633 "Eccentricity: 0 for perfect, throw-"
634 "sized square/line"));
638 cpl_image_delete(inverse);
729 const cpl_parameterlist * parlist,
730 const irplib_framelist * rawframes,
734 cpl_boolean do_spc_fix,
736 visir_spc_resol resol)
738 const char * fnodpos;
740 cpl_imagelist * in = NULL;
741 cpl_image * collapsed = NULL;
742 cpl_image * prev = NULL;
743 cpl_vector * nods_vec = NULL;
745 int * nod_pos = NULL;
746 cpl_image ** images = NULL;
747 cpl_imagelist * nodded = NULL;
749 cpl_image * flat_image = NULL;
750 cpl_image * bpm_im_int = NULL;
751 cpl_mask * bpm_im_bin = NULL;
752 cpl_imagelist * hcycle = NULL;
754 cpl_boolean is_nodding = CPL_FALSE;
756 cpl_boolean auto_bpm, rem_glitch, rem_bad;
759 cpl_boolean morpho_destripe;
760 double tstart, tstop;
761 const cpl_propertylist * plist1;
763 cpl_errorstate cleanstate = cpl_errorstate_get();
765 cpl_error_code didfail = CPL_ERROR_NONE;
769 skip_if(recipename == NULL);
770 skip_if(parlist == NULL);
771 skip_if(rawframes == NULL);
778 cpl_msg_warning(cpl_func,
"Expecting even number of files, "
779 "ignoring the last of %d file(s)", nfiles);
780 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
781 "At least two files are required");
790 CPL_TYPE_STRING, CPL_FALSE, 0.0));
792 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
795 CPL_TYPE_INT, CPL_TRUE, 0.0));
797 CPL_TYPE_INT, CPL_TRUE, 0.0));
799 CPL_TYPE_INT, CPL_FALSE, 0.0));
801 CPL_TYPE_INT, CPL_FALSE, 0.0));
804 naxis1 = irplib_pfits_get_int(plist1,
"NAXIS1");
805 naxis2 = irplib_pfits_get_int(plist1,
"NAXIS2");
814 VISIR_PARAM_AUTOBPM);
826 VISIR_PARAM_STRIPITE);
829 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
831 VISIR_PARAM_STRIPMOR);
834 no_rem = !rem_glitch && !rem_bad;
838 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles *
sizeof(
int));
840 if (!visir_str_par_is_empty(fnodpos)) {
842 nods_vec = cpl_vector_read(fnodpos);
843 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
844 nods_data = cpl_vector_get_data(nods_vec);
846 for (i=0 ; i<nfiles ; i++) {
847 if ((
int)nods_data[i] == 0) {
850 }
else if ((
int)nods_data[i] == 1) {
852 is_nodding = CPL_TRUE;
854 error_if(1, CPL_ERROR_BAD_FILE_FORMAT,
855 "Wrong values in line %d in %s", i+1, fnodpos);
860 CPL_TYPE_STRING, CPL_FALSE, 0.0));
863 if (no_rem) cpl_msg_info(cpl_func,
"No glitch removal and no purge of bad "
864 "frames requested: Using fast I/O method");
867 if (badpix != NULL) {
869 cpl_msg_info(cpl_func,
"Loading bad pixel map from %s", badpix);
871 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
875 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
876 cpl_image_delete(bpm_im_int);
878 skip_if (cpl_mask_not(bpm_im_bin));
879 }
else if (auto_bpm) {
887 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
888 VISIR_HCYCLE_BPM_THRESHOLD,
890 cpl_imagelist_delete(hcycle);
897 cpl_msg_info(cpl_func,
"Divide the nodded images by the flatfield");
899 flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
900 any_if (
"Cannot load the flat field %s", flat ? flat :
"<NULL>");
904 nodded = cpl_imagelist_new();
906 tstart = cpl_test_get_walltime();
910 for (i=0; i < nfiles/2 ; i++) {
911 cpl_image * empty = cpl_image_new(naxis1, naxis2, CPL_TYPE_FLOAT);
916 bug_if (cpl_imagelist_set(nodded, empty, i));
920 #pragma omp parallel for private(i) firstprivate(prev, collapsed) \
923 for (i = 0; i < nfiles ; i++) {
924 cpl_error_code errori = cpl_error_get_code();
932 if (didfail)
continue;
938 const cpl_propertylist * plist;
946 errori = cpl_error_set_where(cpl_func);
950 if (nods_vec == NULL) {
953 errori = cpl_error_set_message(cpl_func,
954 CPL_ERROR_DATA_NOT_FOUND,
955 "Cannot get nodding position "
956 "for file %d/%d", i+1, nfiles);
959 if (!strcmp(sval,
"A")) {
967 is_nodding = CPL_TRUE;
972 cpl_msg_info(cpl_func,
"File %02d: %s (%c)", i+1, file,
973 nod_pos[i]==1 ?
'+' :
'-');
976 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
977 cpl_msg_error(cpl_func,
"Nodding pair (%d,%d) does not comprise an "
978 "on-object (A) and an off-object (B) image: %s", i-1,
979 i, nod_pos[i] == 1 ?
"A" :
"B");
984 if (cpl_error_get_code()) {
985 errori = cpl_error_set_where(cpl_func);
990 errori = cpl_error_set_message(cpl_func,
991 CPL_ERROR_ILLEGAL_INPUT,
992 "DIT in file %d/%d is too small: "
993 "%g", i+1, nfiles, dit);
997 factor = dit * nod_pos[i] * 2.0;
1000 collapsed = visir_load_average(file, plist);
1002 in = visir_load_intermint(rawframes, i);
1004 errori = cpl_error_set_message(cpl_func,
1005 CPL_ERROR_ILLEGAL_INPUT,
1006 "Could not load image set %d",
1012 if (visir_imagelist_unpack_interm(in)) {
1013 errori = cpl_error_set_message(cpl_func,
1014 cpl_error_get_code(),
1015 "Failure for file %d/%d",
1024 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
1025 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
1026 errori = cpl_error_set_message(cpl_func,
1027 cpl_error_get_code(),
1029 "glitch in image %d in "
1030 "set %d", jj+1, i+1);
1038 cpl_msg_info(cpl_func,
"Remove the bad A-B input images");
1039 if (visir_rem_bad_images(in)) {
1040 errori = cpl_error_set_message(cpl_func,
1041 cpl_error_get_code(),
1042 "Could not remove bad "
1043 "images in list %d", i+1);
1048 collapsed = cpl_imagelist_collapse_create(in);
1050 cpl_imagelist_delete(in);
1055 if (cpl_error_get_code()) {
1056 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
1057 "Failure for file %d/%d",
1063 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
1064 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
1065 "Failure for file %d/%d",
1072 if (cpl_image_add(prev, collapsed)) {
1073 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
1074 "Failure for file %d/%d",
1078 cpl_image_delete(collapsed);
1084 if (bpm_im_bin != NULL) {
1086 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
1087 errori = cpl_error_set_message(cpl_func,
1088 cpl_error_get_code(),
1089 "Failure for file %d/%d",
1093 if (cpl_detector_interpolate_rejected(prev)) {
1094 errori = cpl_error_set_message(cpl_func,
1095 cpl_error_get_code(),
1096 "Failure for file %d/%d",
1104 VISIR_DESTRIPE_DETECT,
1105 VISIR_DESTRIPE_DETECT_THRESHOLD,
1107 errori = cpl_error_set_message(cpl_func,
1108 cpl_error_get_code(),
1109 "Failure for file %d/%d",
1114 if (flat_image != NULL) {
1116 if (cpl_image_divide(prev, flat_image)) {
1117 errori = cpl_error_set_message(cpl_func,
1118 cpl_error_get_code(),
1119 "Failure for file %d/%d",
1125 if (cpl_imagelist_set(nodded, prev, i/2)) {
1126 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
1127 "Failure for file %d/%d",
1142 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
1143 cpl_errorstate_set(cleanstate);
1146 cpl_image_delete(prev); prev = NULL;
1147 cpl_image_delete(collapsed); collapsed = NULL;
1149 #pragma omp critical(visir_inputs_combine)
1155 error_if(didfail, didfail,
"Failed to create %d nodded images from %d "
1156 "files", nnod, nfiles);
1158 tstop = cpl_test_get_walltime();
1159 cpl_msg_info(cpl_func,
"Time to create %d nodded images [s]: %g", nnod,
1162 cpl_vector_delete(nods_vec);
1165 cpl_image_delete(flat_image);
1168 cpl_mask_delete(bpm_im_bin);
1171 if (nod_pos != nodding_p) cpl_free(nod_pos);
1174 error_if(is_nodding && j != nnod, CPL_ERROR_INCOMPATIBLE_INPUT,
1175 "With nodding exactly half of the images "
1176 "must be on-object, not %d of %d", j, 2*nnod);
1180 VISIR_PARAM_SPECSKEW);
1182 VISIR_PARAM_VERTARC);
1184 VISIR_PARAM_HORIARC);
1186 VISIR_PARAM_SLITSKEW);
1193 images = cpl_malloc(nnod *
sizeof(cpl_image*));
1195 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
1197 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
1198 phi, ksi, eps, delta, doplot));
1203 cpl_msg_set_time_off();
1206 cpl_imagelist_delete(in);
1208 if (nod_pos != nodding_p) cpl_free(nod_pos);
1209 cpl_vector_delete(nods_vec);
1210 cpl_image_delete(bpm_im_int);
1211 cpl_mask_delete(bpm_im_bin);
1212 cpl_image_delete(collapsed);
1213 cpl_image_delete(prev);
1214 if (cpl_error_get_code() && nodded != NULL) {
1215 cpl_imagelist_delete(nodded);
1233 get_cumoffsets(
const cpl_propertylist * plist,
double * x,
double * y)
1235 cpl_errorstate cleanstate = cpl_errorstate_get();
1237 *x = irplib_pfits_get_double(plist,
"ESO DRS CUMOFFSETX");
1238 *y = irplib_pfits_get_double(plist,
"ESO DRS CUMOFFSETY");
1240 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1241 cpl_errorstate_set(cleanstate);
1242 cpl_msg_info(cpl_func,
"DRS CUMOFFSET[XY] not found, falling back"
1243 " to SEQ CUMOFFSET[XY]");
1247 return cpl_error_get_code();
1267 const cpl_parameterlist * parlist,
1268 cpl_imagelist * nodded,
1269 const cpl_propertylist ** plists,
1270 cpl_geom_combine combine_mode,
1271 cpl_boolean * pdid_resize)
1274 cpl_bivector * offsets_est = NULL;
1275 cpl_bivector * objs = NULL;
1276 cpl_image ** combined = NULL;
1277 cpl_vector * sigmas = NULL;
1278 cpl_propertylist * qclist = cpl_propertylist_new();
1283 bug_if (recipename == NULL);
1284 bug_if (parlist == NULL);
1285 bug_if (pdid_resize == NULL);
1286 bug_if (nodded == NULL);
1288 nnod = cpl_imagelist_get_size(nodded);
1293 combined = cpl_malloc(2*
sizeof(cpl_image*));
1296 combined[0] = cpl_imagelist_unset(nodded, 0);
1297 bug_if (combined[0] == NULL);
1299 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
1300 cpl_image_get_size_y(combined[0]),
1302 bug_if (combined[1] == NULL);
1305 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
1307 *pdid_resize = CPL_FALSE;
1310 const double psigmas[] = {5, 2, 1, 0.5};
1312 const char * offsets;
1313 const char * objects;
1315 int rej_low, rej_high;
1320 VISIR_PARAM_REFINE);
1324 VISIR_PARAM_OFFSETS);
1328 VISIR_PARAM_OBJECTS);
1335 if (sscanf(sval,
"%d-%d-%d-%d", &sx, &sy, &mx, &my) != 4)
1336 skip_if (sscanf(sval,
"%d %d %d %d", &sx, &sy, &mx, &my) != 4);
1340 VISIR_PARAM_REJECT);
1343 if (sscanf(sval,
"%d-%d", &rej_low, &rej_high) !=2 )
1344 skip_if (sscanf(sval,
"%d %d", &rej_low, &rej_high) !=2 );
1347 cpl_msg_info(cpl_func,
"Get the offsets estimation");
1348 if (!visir_str_par_is_empty(offsets)) {
1350 offsets_est = cpl_bivector_read(offsets);
1351 skip_if (offsets_est==NULL);
1353 error_if (cpl_bivector_get_size(offsets_est) != nnod,
1354 CPL_ERROR_BAD_FILE_FORMAT,
"The offsets file %s must "
1355 "have %d entries, not %d", offsets, (
int)nnod,
1356 (
int)cpl_bivector_get_size(offsets_est));
1358 double * offsets_est_x;
1359 double * offsets_est_y;
1360 double xoff0, yoff0;
1363 offsets_est = cpl_bivector_new(nnod);
1364 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
1365 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
1369 offsets_est_x[0] = 0.0;
1370 offsets_est_y[0] = 0.0;
1371 get_cumoffsets(plists[0], &xoff0, &yoff0);
1373 for (cpl_size i = 1; i < nnod ; i++) {
1376 skip_if(get_cumoffsets(plists[i], &xoff, &yoff));
1379 offsets_est_x[i] = xoff0 - xoff;
1380 offsets_est_y[i] = yoff0 - yoff;
1386 if (!visir_str_par_is_empty(objects)) {
1387 objs = cpl_bivector_read(objects);
1388 any_if (
"Could not read objects from %s", objects);
1391 cpl_msg_info(cpl_func,
"Recombining the list of nodded images using "
1392 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
1393 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
1394 CPL_GEOM_FIRST, rej_low, rej_high);
1396 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
1397 cpl_msg_debug(cpl_func,
"The offsets for the recombination:");
1398 cpl_bivector_dump(offsets_est, stdout);
1401 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
1402 sigmas = cpl_vector_wrap(4, (
double*)psigmas);
1403 IRPLIB_DIAG_PRAGMA_POP;
1404 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
1405 objs, sigmas, NULL, sx, sy,
1406 mx, my, rej_low, rej_high,
1408 any_if(
"Could not recombine the images");
1410 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
1411 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
1412 cpl_image_get_size_y(combined[0])
1413 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
1417 visir_image_plot(
"",
"t 'The combined image'",
"", combined[0]);
1421 cpl_propertylist_delete(qclist);
1422 cpl_bivector_delete(offsets_est);
1423 cpl_bivector_delete(objs);
1424 cpl_vector_unwrap(sigmas);
1478 const cpl_parameterlist * parlist,
1479 const irplib_framelist * rawframes,
1480 const char * badpix,
1482 cpl_geom_combine combine_mode,
1483 cpl_boolean * pdid_resize,
1484 cpl_boolean do_spc_fix,
1486 visir_spc_resol resol)
1489 int * nod_pos = NULL;
1490 cpl_imagelist * nodded = NULL;
1492 cpl_bivector * objs = NULL;
1493 cpl_propertylist * qclist = cpl_propertylist_new();
1494 const cpl_propertylist ** plists = NULL;
1495 cpl_image ** rec = NULL;
1500 bug_if (recipename == NULL);
1501 bug_if (parlist == NULL);
1502 bug_if (rawframes == NULL);
1503 bug_if (pdid_resize == NULL);
1510 cpl_msg_warning(cpl_func,
"Expecting even number of files, "
1511 "ignoring the last of %d file(s)", nfiles);
1512 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
1513 "At least two files are required");
1517 skip_if ( nfiles <= 0);
1520 nod_pos = cpl_malloc(nfiles *
sizeof(
int));
1523 cpl_msg_info(cpl_func,
"Combining the input frames into the nodded images");
1525 nod_pos, do_spc_fix, wlen, resol);
1526 skip_if(nodded == NULL);
1528 nnod = cpl_imagelist_get_size(nodded);
1529 plists = cpl_malloc(nnod *
sizeof(cpl_propertylist *));
1530 for (cpl_size i=0; i < nnod ; i++) {
1531 const cpl_size iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
1538 plists, combine_mode, pdid_resize);
1542 cpl_propertylist_delete(qclist);
1545 cpl_imagelist_delete(nodded);
1546 cpl_bivector_delete(objs);
1595 cpl_image * im_bpm = NULL;
1596 cpl_mask * bpm = NULL;
1597 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
1602 skip_if (
self == NULL);
1604 if (bpmfile == NULL) {
1605 bpm = cpl_mask_threshold_image_create(
self, upper, DBL_MAX);
1610 cpl_msg_info(cpl_func,
"Clean user specified bad pixels");
1612 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
1613 any_if (
"Could not load the bad pixel map %s",
1614 bpmfile ? bpmfile :
"<NULL>");
1616 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
1618 cpl_image_delete(im_bpm);
1621 skip_if (cpl_mask_not(bpm));
1624 skip_if (cpl_image_reject_from_mask(
self, bpm));
1628 cpl_image_delete(im_bpm);
1629 cpl_mask_delete(bpm);
1631 return cpl_error_get_code();
1646 cpl_imagelist *
self = NULL;
1651 CPL_TYPE_INT, CPL_TRUE, 0.0));
1661 skip_if (
self == NULL);
1682 int pos, cpl_boolean is_interm)
1684 cpl_imagelist *
self = NULL;
1685 cpl_image * image = NULL;
1687 const cpl_propertylist * plist =
1689 const char * file = cpl_frame_get_filename(frame);
1692 visir_data_type data_type;
1698 skip_if (plist == NULL);
1700 skip_if(visir_get_data_type(frame, plist, &data_type, NULL));
1702 switch (data_type) {
1703 case VISIR_DATA_AQU_HCYCLE:
1704 case VISIR_DATA_AQU_BURST:
1705 case VISIR_DATA_AQU_BURST_EXT:
1706 error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
1707 "Aquarius data not supported");
1713 bug_if (file == NULL);
1715 if (data_type == VISIR_DATA_CUBE1) {
1717 iplane = is_interm ? 0 : nchop;
1719 nsize = is_interm ? nchop : 1;
1721 }
else if (naxis3 == 1) {
1727 iplane = is_interm ? 1 : 0;
1732 self = cpl_imagelist_new();
1734 for (i=0 ; i < nsize; i++, iplane += plane_step) {
1736 image = cpl_image_load(file, CPL_TYPE_FLOAT, iplane, 0);
1737 skip_if (image == NULL);
1739 skip_if (!is_interm && visir_offset_hcycle(image));
1741 skip_if (cpl_imagelist_set(
self, image, i));
1746 skip_if (i < nsize);
1750 if (cpl_error_get_code()) {
1751 if (file != NULL) cpl_msg_warning(cpl_func,
"Could not load the %s "
1752 "frame(s) from: %s",
1753 is_interm ?
"INTERM" :
"Half-Cycle",
1755 cpl_image_delete(image);
1756 cpl_imagelist_delete(
self);
1791 static cpl_imagelist * visir_load_intermint(
const irplib_framelist * rawframes,
1808 static cpl_image * visir_load_average(
const char * file,
1809 const cpl_propertylist * plist)
1811 cpl_errorstate cleanstate = cpl_errorstate_get();
1812 cpl_image *
self = NULL;
1817 skip_if (file == NULL);
1818 skip_if (plist == NULL);
1825 if (nchop == 0 && naxis3 == 1) {
1826 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
1831 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
1834 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT,
"CHOP NCYCLES in %s "
1835 "is non-positive (and NAXIS3=%d): %d", file, naxis3, nchop);
1837 error_if (plane_offset == 3 && naxis3 != nchop+2,
1838 CPL_ERROR_BAD_FILE_FORMAT,
"NAXIS3=%d and CHOP NCYCLES=%d "
1839 "in %s is not a valid VISIR INTERM+Half-Cycle format", naxis3,
1842 if (plane_offset == 3 && nchop > 1)
1843 cpl_msg_debug(cpl_func,
"%s has %d INTERM-frames and one Half-"
1844 "Cycle frame (old CUBE1-format)", file, nchop);
1850 visir_error_reset(
"Could not get FITS key");
1852 }
else if (strlen(sval) == 0) {
1854 }
else if (plane_offset == 3) {
1855 if (strcmp(sval,
"CUBE2")==0)
1856 cpl_msg_error(cpl_func,
"%s has FRAM TYPE = CUBE2, but NAXIS3="
1857 "%d and CHOP NCYCLES=%d imply a CUBE1. Assuming"
1858 " the frame type is really CUBE1", file,
1860 }
else if (nchop > 1) {
1862 if (strcmp(sval,
"CUBE1")==0)
1863 cpl_msg_error(cpl_func,
"%s has FRAM TYPE = CUBE1, but NAXIS3="
1864 "%d and CHOP NCYCLES=%d imply a CUBE2. Assuming"
1865 "the frame type is really CUBE2", file,
1870 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
1878 if (cpl_error_get_code()) {
1879 cpl_msg_warning(cpl_func,
"Could not load the last INTERM frame from: "
1880 "%s", file ? file :
"<NULL>");
1881 cpl_image_delete(
self);
1912 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *
self)
1916 const int n = cpl_imagelist_get_size(
self);
1922 if (n == 1)
return CPL_ERROR_NONE;
1924 iprev = cpl_imagelist_get(
self, n - 1);
1928 skip_if (cpl_image_multiply_scalar(iprev, n));
1931 for (i = n-1 ; i > 1 ; i--, iprev = image) {
1932 image = cpl_imagelist_get(
self, i-1);
1936 skip_if (cpl_image_multiply_scalar(image, i));
1938 skip_if (cpl_image_subtract(iprev, image));
1942 image = cpl_imagelist_get(
self, 0);
1946 skip_if (cpl_image_subtract(iprev, image));
1950 return cpl_error_get_code();
1967 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
1969 cpl_image * med_filt = NULL;
1970 cpl_mask * bpm = NULL;
1971 cpl_mask * kernel = cpl_mask_new(3, 3);
1973 double low_thresh, high_thresh;
1974 const int nx = cpl_image_get_size_x(glitchy);
1975 const int ny = cpl_image_get_size_y(glitchy);
1979 double factor1 = 3.0;
1980 double factor2 = 10.0;
1981 const int niterations = 5;
1982 const double median_corr = 1.5;
1987 bug_if(cpl_mask_not(kernel));
1990 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
1991 cpl_image_get_size_y(glitchy),
1992 cpl_image_get_type(glitchy));
1993 bug_if(med_filt == NULL);
1994 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
1995 CPL_BORDER_FILTER));
1996 cpl_mask_delete(kernel);
2000 skip_if (cpl_image_subtract(glitchy, med_filt));
2003 for (i=0 ; i < niterations ; i++) {
2005 mean = cpl_image_get_mean(glitchy);
2006 stdev = cpl_image_get_stdev(glitchy);
2011 low_thresh = mean - factor1 * stdev;
2012 high_thresh = mean + factor1 * stdev;
2015 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
2016 skip_if (cpl_mask_not(bpm));
2017 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
2018 cpl_mask_delete(bpm);
2022 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
2027 mean = cpl_image_get_mean(glitchy);
2028 stdev = cpl_image_get_stdev(glitchy) * median_corr;
2032 low_thresh = mean - factor2 * stdev;
2033 high_thresh = mean + factor2 * stdev;
2035 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
2036 skip_if (cpl_mask_not(bpm));
2037 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
2038 cpl_mask_delete(bpm);
2042 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
2045 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
2046 skip_if (cpl_image_accept_all(glitchy));
2049 skip_if (cpl_image_add(glitchy, med_filt));
2053 cpl_image_delete(med_filt);
2054 cpl_mask_delete(bpm);
2055 cpl_mask_delete(kernel);
2057 return cpl_error_get_code();
2072 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
2074 cpl_vector * medians = NULL;
2075 cpl_vector * stdevs = NULL;
2076 cpl_vector * selection = NULL;
2077 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
2078 const double threshold = 3;
2079 const int nima = cpl_imagelist_get_size(in);
2086 if (nima <= 3)
return CPL_ERROR_NONE;
2089 medians = cpl_vector_new(nima);
2090 stdevs = cpl_vector_new(nima);
2093 for (i=0 ; i < nima ; i++) {
2094 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
2095 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
2097 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
2098 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
2099 cpl_stats_delete(stats);
2105 mean_medians = cpl_vector_get_mean(medians);
2106 stdev_medians = cpl_vector_get_stdev(medians);
2107 mean_stdevs = cpl_vector_get_mean(stdevs);
2108 stdev_stdevs = cpl_vector_get_stdev(stdevs);
2110 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
2111 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
2113 stdev_medians *= threshold;
2114 stdev_stdevs *= threshold;
2117 selection = cpl_vector_new(nima);
2118 skip_if( cpl_vector_fill(selection, 0));
2119 for (i=0 ; i < nima ; i++) {
2120 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
2121 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs)
continue;
2123 cpl_vector_set(selection, i, -1);
2124 cpl_msg_info(cpl_func,
"Image %d of %d rejected: median=%g, stdev=%g",
2125 i+1, nima, stdev_medians, stdev_stdevs);
2129 cpl_imagelist_erase(in, selection);
2133 cpl_vector_delete(medians);
2134 cpl_vector_delete(stdevs);
2136 cpl_vector_delete(selection);
2138 return CPL_ERROR_NONE;
2152 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
2159 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
2161 minval = cpl_image_get_min(hcycle);
2164 if (minval < 1) cpl_msg_warning(cpl_func,
"HCycle pixel minval: %g", minval);
2168 return CPL_ERROR_NONE;
2185 cpl_image ** visir_img_collapse_beam_four(cpl_propertylist * qclist,
2186 const cpl_image *
self,
2187 const cpl_image * inverse,
2191 const cpl_propertylist * plist)
2194 cpl_image ** combined = NULL;
2195 const int nx = cpl_image_get_size_x(
self);
2196 const int ny = cpl_image_get_size_y(
self);
2197 const cpl_type type = cpl_image_get_type(
self);
2198 cpl_imagelist * list4 = cpl_imagelist_new();
2199 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2200 cpl_image * swrap = type == CPL_TYPE_DOUBLE
2201 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)
self))
2202 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)self));
2203 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
2204 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
2205 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
2206 IRPLIB_DIAG_PRAGMA_POP;
2207 cpl_bivector * offs = cpl_bivector_new(4);
2208 double * x4 = cpl_bivector_get_x_data(offs);
2209 double * y4 = cpl_bivector_get_y_data(offs);
2210 double pos_x, pos_y;
2214 skip_if(plist == NULL);
2216 skip_if(visir_img_find_beam_four(qclist,
self, inverse, eccmax, pthrow,
2220 for (
int i = 1; i < 4; i++) {
2221 x4[i] = x4[0] - x4[i];
2222 y4[i] = y4[0] - y4[i];
2225 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM XPOS",
2227 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM YPOS",
2229 x4[0] = y4[0] = 0.0;
2231 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2232 bug_if(cpl_imagelist_set(list4, (cpl_image*)
self, 0));
2233 bug_if(cpl_imagelist_set(list4, swrap, 1));
2234 bug_if(cpl_imagelist_set(list4, (cpl_image*)inverse, 2));
2235 bug_if(cpl_imagelist_set(list4, iwrap, 3));
2236 IRPLIB_DIAG_PRAGMA_POP;
2238 combined = cpl_geom_img_offset_saa(list4, offs, CPL_KERNEL_DEFAULT, 0, 0,
2239 CPL_GEOM_FIRST, &pos_x, &pos_y);
2241 skip_if(combined == NULL);
2245 cpl_bivector_delete(offs);
2246 visir_imagelist_unwrap(list4);
2247 (void)cpl_image_unwrap(swrap);
2248 (void)cpl_image_unwrap(iwrap);
2249 if (cpl_error_get_code() && combined != NULL) {
2250 cpl_image_delete(combined[0]);
2251 cpl_image_delete(combined[1]);
2273 visir_chopnod_mode visir_img_find_beam(cpl_propertylist * qclist,
2274 const cpl_image *
self,
2275 const cpl_image * inverse,
2276 const cpl_propertylist * plist,
2277 const cpl_parameterlist * parlist,
2278 const char * recipename,
2283 cpl_errorstate cleanstate = cpl_errorstate_get();
2284 visir_chopnod_mode mode = VISIR_CHOPNOD_AUTO;
2287 VISIR_PARAM_ECCMAX);
2293 const double pthrow = pscale > 0.0
2297 skip_if(x4 == NULL);
2298 skip_if(y4 == NULL);
2299 skip_if(
self == NULL);
2300 skip_if(inverse == NULL);
2301 skip_if(parlist == NULL);
2302 skip_if(recipename == NULL);
2303 skip_if(qclist == NULL);
2307 if (sdir != NULL && !strcmp(sdir,
"PERPENDICULAR")) {
2310 mode = VISIR_CHOPNOD_PERPENDICULAR;
2312 skip_if (visir_img_find_beam_four(qclist,
self, inverse, eccmax,
2313 pthrow, angle, x4, y4));
2315 }
else if (sdir != NULL && !strcmp(sdir,
"PARALLEL")) {
2318 mode = VISIR_CHOPNOD_PARALLEL;
2320 skip_if (visir_img_find_beam_three(qclist,
self, inverse, eccmax,
2321 pthrow, angle, x4, y4));
2325 visir_error_reset(
"Could not get FITS key");
2327 cpl_msg_warning(cpl_func,
"Unknown chopping direction: %s",
2330 cpl_msg_warning(cpl_func,
"Proceeding as if FITS card "
2331 VISIR_PFITS_STRING_CHOPNOD_DIR
" had value: %s",
2334 if (visir_img_find_beam_four(qclist,
self, inverse, eccmax,
2335 pthrow, angle, x4, y4)) {
2337 visir_error_reset(
"Proceeding as if FITS card "
2338 VISIR_PFITS_STRING_CHOPNOD_DIR
2339 " had value: %s",
"PARALLEL");
2341 skip_if (visir_img_find_beam_three(qclist,
self, inverse,
2342 eccmax, pthrow, angle,
2346 mode = VISIR_CHOPNOD_PARALLEL;
2350 mode = VISIR_CHOPNOD_PERPENDICULAR;
2354 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM THROW",
2356 bug_if (cpl_propertylist_set_comment(qclist,
"ESO QC ONEBEAM THROW",
2357 "The throw in pixels (TEL CHOP THROW "
2358 "divided by INS PFOV)"));
2380 cpl_error_code visir_img_find_beam_four(cpl_propertylist * qclist,
2381 const cpl_image *
self,
2382 const cpl_image * inverse,
2390 cpl_errorstate cleanstate = cpl_errorstate_get();
2391 cpl_apertures * appos = NULL;
2392 cpl_apertures * apneg = NULL;
2393 const double psigmas[] = {2.0, 1.0, 0.5};
2394 const int nsigmas =
sizeof(psigmas)/
sizeof(
double);
2396 int iappos2[] = {1, 2};
2397 int iapneg2[] = {1, 2};
2400 skip_if(
self == NULL);
2401 skip_if(qclist == NULL);
2402 skip_if(pthrow <= 0.0);
2403 skip_if(x4 == NULL);
2404 skip_if(y4 == NULL);
2406 cpl_msg_info(cpl_func,
"Detecting the 4-beam object with %g pixel throw "
2407 "using %d sigma-levels ranging from %g down to %g", pthrow,
2408 nsigmas, psigmas[0], psigmas[nsigmas-1]);
2411 for (isigma = 0; isigma < nsigmas; isigma++) {
2416 cpl_apertures_delete(appos);
2417 appos = cpl_apertures_extract_sigma(
self, psigmas[isigma]);
2419 if (appos != NULL) {
2420 npos = cpl_apertures_get_size(appos);
2425 cpl_apertures_delete(apneg);
2426 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
2427 if (apneg != NULL) {
2428 nneg = cpl_apertures_get_size(apneg);
2431 cpl_msg_info(cpl_func,
"Found %d positive (need 2) and %d negative "
2432 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
2433 psigmas[isigma], 1+isigma, nsigmas);
2436 error_if(npos * nneg > FIND_BEAM_MAX_APERTURES_SQR,
2437 CPL_ERROR_DATA_NOT_FOUND,
"Too many objects found, aborting");
2441 double eccbest = eccmax;
2442 double eccmin = DBL_MAX;
2443 double fluxbest = 0.0;
2444 double fluxecc = DBL_MAX;
2445 cpl_boolean is_first = CPL_TRUE;
2448 #pragma omp parallel for private(ipos1)
2450 for (ipos1 = 2; ipos1 < 1 + npos; ipos1++) {
2451 int ipos2, ineg1, ineg2;
2452 for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
2453 for (ineg1 = 2; ineg1 < 1 + nneg; ineg1++) {
2454 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
2455 cpl_boolean swappos, swapneg;
2457 = visir_img_check_box(appos, ipos1, ipos2,
2458 apneg, ineg1, ineg2,
2459 pthrow, angle, &swappos,
2463 = cpl_apertures_get_flux(appos, ipos1)
2464 + cpl_apertures_get_flux(appos, ipos2)
2465 + cpl_apertures_get_flux(apneg, ineg1)
2466 + cpl_apertures_get_flux(apneg, ineg2);
2469 if (ecc < 0.0 || flux <= 0.0 ||
2470 !cpl_errorstate_is_equal(cleanstate)) {
2471 irplib_error_recover(cleanstate,
"Invalid 4-"
2472 "object (%d & %d of %d, "
2475 ineg2, ineg1, nneg);
2480 #pragma omp critical(visir_img_find_beam_four_min)
2488 if (eccmax <= ecc)
continue;
2491 #pragma omp critical(visir_img_find_beam_four_ok)
2493 if (is_first || ecc * fluxbest < eccbest * flux)
2496 is_first = CPL_FALSE;
2497 cpl_msg_info(cpl_func,
"Found 4 object "
2498 "positions with throw-"
2499 "scaled eccentricity %g "
2500 "and flux %g", ecc, flux);
2502 cpl_msg_info(cpl_func,
"Found 4 object "
2503 "positions with throw-"
2504 "scaled eccentricity %g "
2505 "< %g and/or flux %g > %g",
2506 ecc, eccbest, flux, fluxbest);
2510 iappos2[0] = swappos ? ipos2 : ipos1;
2511 iappos2[1] = swappos ? ipos1 : ipos2;
2512 iapneg2[0] = swapneg ? ineg2 : ineg1;
2513 iapneg2[1] = swapneg ? ineg1 : ineg2;
2519 if (eccbest < eccmax) {
2520 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM "
2521 "ECCENTRICITY", eccbest));
2525 if (eccmin < DBL_MAX) {
2526 cpl_msg_info(cpl_func,
"Found 4 sigma-%g object positions with "
2527 "too large throw-scaled eccentricity %g >= %g and "
2528 "flux %g", psigmas[isigma], eccmin, eccmax,
2531 }
else if (npos >= 2 && nneg >= 2) {
2532 cpl_apertures_sort_by_flux(appos);
2533 cpl_apertures_sort_by_flux(apneg);
2537 if (isigma + 1 < nsigmas) {
2538 irplib_error_recover(cleanstate,
"4-Beam positions not found among "
2539 "%d postive and %d negative object(s) at "
2540 "sigma=%g, (%d of %d)", npos, nneg,
2541 psigmas[isigma], 1+isigma, nsigmas);
2545 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
2546 "4-Beam positions not found w. %d sigma(s) down to %g",
2547 nsigmas, psigmas[nsigmas - 1]);
2549 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
2550 cpl_apertures_dump(appos, stdout);
2551 cpl_apertures_dump(apneg, stdout);
2554 x4[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
2555 y4[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
2556 x4[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
2557 y4[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
2559 x4[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
2560 y4[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
2561 x4[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
2562 y4[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
2564 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM FLUX",
2565 cpl_apertures_get_flux(appos,
2568 cpl_msg_info(cpl_func,
"Centroid of positive object 1 [pixel]: %g %g",
2570 cpl_msg_info(cpl_func,
"Centroid of positive object 2 [pixel]: %g %g",
2573 cpl_msg_info(cpl_func,
"Centroid of negative object 1 [pixel]: %g %g",
2575 cpl_msg_info(cpl_func,
"Centroid of negative object 2 [pixel]: %g %g",
2578 cpl_msg_info(cpl_func,
"Expected object distance (chop throw) [pixel]: %g",
2580 cpl_msg_info(cpl_func,
"Object Pos -> Pos x/y-distance [pixel]: %g %g",
2581 x4[1] - x4[0], y4[1] - y4[0]);
2582 cpl_msg_info(cpl_func,
"Object Neg -> Neg x/y-distance [pixel]: %g %g",
2583 x4[3] - x4[2], y4[3] - y4[2]);
2584 cpl_msg_info(cpl_func,
"Object Pos -> Pos angle [degrees]: %g",
2585 atan2(y4[1] - y4[0], x4[1] - x4[0]) * CPL_MATH_DEG_RAD);
2586 cpl_msg_info(cpl_func,
"Object Neg -> Neg angle [degrees]: %g",
2587 atan2(y4[3] - y4[2], x4[3] - x4[2]) * CPL_MATH_DEG_RAD);
2591 cpl_apertures_delete(appos);
2592 cpl_apertures_delete(apneg);
2594 return cpl_error_get_code();
2611 cpl_image ** visir_img_collapse_beam_three(cpl_propertylist * qclist,
2612 const cpl_image *
self,
2613 const cpl_image * inverse,
2616 const cpl_propertylist * plist)
2619 cpl_image ** combined = NULL;
2620 const int nx = cpl_image_get_size_x(
self);
2621 const int ny = cpl_image_get_size_y(
self);
2622 const cpl_type type = cpl_image_get_type(
self);
2623 cpl_imagelist * list3 = cpl_imagelist_new();
2624 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2625 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
2626 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
2627 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
2628 IRPLIB_DIAG_PRAGMA_POP;
2629 cpl_bivector * offs = cpl_bivector_new(3);
2630 double * x3 = cpl_bivector_get_x_data(offs);
2631 double * y3 = cpl_bivector_get_y_data(offs);
2632 double pos_x, pos_y;
2637 skip_if(plist == NULL);
2639 skip_if(visir_img_find_beam_three(qclist,
self, inverse, eccmax, pthrow,
2643 for (
int i = 1; i < 3; i++) {
2644 x3[i] = x3[0] - x3[i];
2645 y3[i] = y3[0] - y3[i];
2647 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM XPOS",
2649 bug_if (cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM YPOS",
2652 x3[0] = y3[0] = 0.0;
2654 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2655 bug_if(cpl_imagelist_set(list3, (cpl_image*)
self, 0));
2656 bug_if(cpl_imagelist_set(list3, (cpl_image*)inverse, 1));
2657 bug_if(cpl_imagelist_set(list3, iwrap, 2));
2658 IRPLIB_DIAG_PRAGMA_POP;
2660 combined = cpl_geom_img_offset_saa(list3, offs, CPL_KERNEL_DEFAULT, 0, 0,
2661 CPL_GEOM_FIRST, &pos_x, &pos_y);
2663 skip_if(combined == NULL);
2667 cpl_bivector_delete(offs);
2668 visir_imagelist_unwrap(list3);
2669 (void)cpl_image_unwrap(iwrap);
2670 if (cpl_error_get_code() && combined != NULL) {
2671 cpl_image_delete(combined[0]);
2672 cpl_image_delete(combined[1]);
2696 cpl_error_code visir_img_find_beam_three(cpl_propertylist * qclist,
2697 const cpl_image *
self,
2698 const cpl_image * inverse,
2706 cpl_errorstate cleanstate = cpl_errorstate_get();
2707 cpl_apertures * appos = NULL;
2708 cpl_apertures * apneg = NULL;
2709 const double psigmas[] = {2.0, 1.0, 0.5};
2710 const int nsigmas =
sizeof(psigmas)/
sizeof(
double);
2712 int iappos [] = {1};
2713 int iapneg2[] = {1, 2};
2716 skip_if(
self == NULL);
2717 skip_if(qclist == NULL);
2718 skip_if(pthrow <= 0.0);
2719 skip_if(eccmax < 0.0);
2720 skip_if(x3 == NULL);
2721 skip_if(y3 == NULL);
2724 cpl_msg_info(cpl_func,
"Detecting the 3-beam object with %g pixel throw "
2725 "using %d sigma-levels ranging from %g down to %g", pthrow,
2726 nsigmas, psigmas[0], psigmas[nsigmas-1]);
2729 for (isigma = 0; isigma < nsigmas; isigma++) {
2734 cpl_apertures_delete(appos);
2735 appos = cpl_apertures_extract_sigma(
self, psigmas[isigma]);
2737 if (appos != NULL) {
2738 npos = cpl_apertures_get_size(appos);
2743 cpl_apertures_delete(apneg);
2744 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
2745 if (apneg != NULL) {
2746 nneg = cpl_apertures_get_size(apneg);
2749 cpl_msg_info(cpl_func,
"Found %d positive (need 1) and %d negative "
2750 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
2751 psigmas[isigma], 1+isigma, nsigmas);
2754 error_if(npos * nneg > FIND_BEAM_MAX_APERTURES_SQR,
2755 CPL_ERROR_DATA_NOT_FOUND,
"Too many objects found, aborting");
2759 double eccbest = eccmax;
2760 double eccmin = DBL_MAX;
2761 double fluxbest = 0.0;
2762 double fluxecc = DBL_MAX;
2763 cpl_boolean is_first = CPL_TRUE;
2766 #pragma omp parallel for private(ipos)
2768 for (ipos = 1; ipos < 1 + npos; ipos++) {
2770 for (ineg1 = 2; ineg1 < 1 + nneg; ineg1++) {
2771 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
2772 cpl_boolean swapneg;
2775 = visir_img_check_align(appos, ipos, apneg, ineg1,
2776 ineg2, pthrow, angle,
2780 = cpl_apertures_get_flux(appos, ipos)
2781 + cpl_apertures_get_flux(apneg, ineg1)
2782 + cpl_apertures_get_flux(apneg, ineg2);
2785 if (ecc < 0.0 || flux <= 0.0 ||
2786 !cpl_errorstate_is_equal(cleanstate)) {
2787 irplib_error_recover(cleanstate,
"Invalid 3-"
2788 "object (%d of %d, "
2791 ineg2, ineg1, nneg);
2796 #pragma omp critical(visir_img_collapse_beam_three_min)
2804 if (eccmax <= ecc)
continue;
2807 #pragma omp critical(visir_img_collapse_beam_three_ok)
2809 if (is_first || ecc * fluxbest < eccbest * flux)
2812 is_first = CPL_FALSE;
2813 cpl_msg_info(cpl_func,
"Found 3 object posi"
2814 "tions with throw-scaled "
2815 "eccentricity %g and flux %g",
2818 cpl_msg_info(cpl_func,
"Found 3 object posi"
2819 "tions with throw-scaled "
2820 "eccentricity %g < %g and/or "
2821 "flux %g > %g", ecc, eccbest,
2827 iapneg2[0] = swapneg ? ineg2 : ineg1;
2828 iapneg2[1] = swapneg ? ineg1 : ineg2;
2833 if (eccbest < eccmax) {
2834 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM "
2835 "ECCENTRICITY", eccbest));
2838 if (eccmin < DBL_MAX) {
2839 cpl_msg_info(cpl_func,
"Found 3 sigma-%g object positions with "
2840 "too large throw-scaled eccentricity %g >= %g and "
2841 "flux %g", psigmas[isigma], eccmin, eccmax,
2844 }
else if (npos >= 1 && nneg >= 2) {
2845 cpl_apertures_sort_by_flux(appos);
2846 cpl_apertures_sort_by_flux(apneg);
2850 if (isigma + 1 < nsigmas) {
2851 irplib_error_recover(cleanstate,
"3-Beam positions not found among "
2852 "%d postive and %d negative object(s) at "
2853 "sigma=%g, (%d of %d)", npos, nneg,
2854 psigmas[isigma], 1+isigma, nsigmas);
2858 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
2859 "3-Beam positions not found w. %d sigma(s) down to %g",
2860 nsigmas, psigmas[nsigmas - 1]);
2862 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
2863 cpl_apertures_dump(appos, stdout);
2864 cpl_apertures_dump(apneg, stdout);
2867 x3[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
2868 y3[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
2870 x3[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
2871 y3[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
2872 x3[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
2873 y3[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
2875 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM FLUX",
2876 cpl_apertures_get_flux(appos,
2879 cpl_msg_info(cpl_func,
"Centroid of positive object [pixel]: %g %g",
2882 cpl_msg_info(cpl_func,
"Centroid of negative object 1 [pixel]: %g %g",
2884 cpl_msg_info(cpl_func,
"Centroid of negative object 2 [pixel]: %g %g",
2887 cpl_msg_info(cpl_func,
"Expected object distance (chop throw) [pixel]: %g",
2889 cpl_msg_info(cpl_func,
"Object Neg1 -> Pos x/y-distance [pixel]: %g %g",
2890 x3[2] - x3[0], y3[2] - y3[0]);
2891 cpl_msg_info(cpl_func,
"Object Pos -> Neg2 x/y-distance [pixel]: %g %g",
2892 x3[0] - x3[1], y3[0] - y3[1]);
2896 cpl_apertures_delete(appos);
2897 cpl_apertures_delete(apneg);
2899 return cpl_error_get_code();
2920 cpl_error_code visir_img_find_beam_two(cpl_propertylist * qclist,
2921 const cpl_image *
self,
2922 const cpl_image * inverse,
2931 cpl_errorstate cleanstate = cpl_errorstate_get();
2932 cpl_apertures * appos = NULL;
2933 cpl_apertures * apneg = NULL;
2934 const double psigmas[] = {2.0, 1.0, 0.5};
2935 const int nsigmas =
sizeof(psigmas)/
sizeof(
double);
2941 skip_if(
self == NULL);
2942 skip_if(qclist == NULL);
2943 skip_if(eccmax < 0.0);
2944 skip_if(x2 == NULL);
2945 skip_if(y2 == NULL);
2948 cpl_msg_info(cpl_func,
"Detecting the 2-beam object (Pos -> Neg) with "
2949 "%g pixel throw using %d sigma-levels ranging from %g down"
2950 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
2951 }
else if (pthrow < 0.0) {
2952 cpl_msg_info(cpl_func,
"Detecting the 2-beam object (Neg -> Pos) with "
2953 "%g pixel throw using %d sigma-levels ranging from %g down"
2954 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
2960 for (isigma = 0; isigma < nsigmas; isigma++) {
2965 cpl_apertures_delete(appos);
2966 appos = cpl_apertures_extract_sigma(
self, psigmas[isigma]);
2968 if (appos != NULL) {
2969 npos = cpl_apertures_get_size(appos);
2974 cpl_apertures_delete(apneg);
2975 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
2976 if (apneg != NULL) {
2977 nneg = cpl_apertures_get_size(apneg);
2980 cpl_msg_info(cpl_func,
"Found %d positive (need 1) and %d negative "
2981 "(need 1) object(s) at sigma=%g (%d of %d)", npos, nneg,
2982 psigmas[isigma], 1+isigma, nsigmas);
2986 double eccbest = eccmax;
2987 double eccmin = DBL_MAX;
2988 double fluxbest = 0.0;
2989 double fluxecc = DBL_MAX;
2990 cpl_boolean is_first = CPL_TRUE;
2993 #pragma omp parallel for private(ipos)
2995 for (ipos = 1; ipos < 1 + npos; ipos++) {
2997 for (ineg = 1; ineg < 1 + nneg; ineg++) {
2999 visir_img_check_line(appos, ipos, apneg, ineg,
3003 = cpl_apertures_get_flux(appos, ipos)
3004 + cpl_apertures_get_flux(apneg, ineg);
3007 if (ecc < 0.0 || flux <= 0.0 ||
3008 !cpl_errorstate_is_equal(cleanstate)) {
3009 irplib_error_recover(cleanstate,
"Invalid 2-"
3010 "object (%d of %d, "
3018 #pragma omp critical(visir_img_collapse_beam_two_min)
3026 if (eccmax <= ecc)
continue;
3029 #pragma omp critical(visir_img_collapse_beam_two_ok)
3031 if (is_first || ecc * fluxbest < eccbest * flux)
3034 is_first = CPL_FALSE;
3035 cpl_msg_info(cpl_func,
"Found 2 object posi"
3036 "tions with throw-scaled eccen"
3037 "tricity %g and flux %g", ecc,
3040 cpl_msg_info(cpl_func,
"Found 2 object posi"
3041 "tions with throw-scaled eccen"
3042 "tricity %g < %g and/or flux %g "
3043 "> %g", ecc, eccbest, flux,
3053 if (eccbest < eccmax) {
3054 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM "
3055 "ECCENTRICITY", eccbest));
3058 if (eccmin < DBL_MAX) {
3059 cpl_msg_info(cpl_func,
"Found 2 sigma-%g object positions with "
3060 "too large throw-scaled eccentricity %g >= %g and "
3061 "flux %g", psigmas[isigma], eccmin, eccmax,
3064 }
else if (npos >= 1 && nneg >= 2) {
3065 cpl_apertures_sort_by_flux(appos);
3066 cpl_apertures_sort_by_flux(apneg);
3070 if (isigma + 1 < nsigmas) {
3071 irplib_error_recover(cleanstate,
"2-Beam positions not found among "
3072 "%d postive and %d negative object(s) at "
3073 "sigma=%g, (%d of %d)", npos, nneg,
3074 psigmas[isigma], 1+isigma, nsigmas);
3078 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
3079 "2-Beam positions not found w. %d sigma(s) down to %g",
3080 nsigmas, psigmas[nsigmas - 1]);
3082 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
3083 cpl_apertures_dump(appos, stdout);
3084 cpl_apertures_dump(apneg, stdout);
3087 x2[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
3088 y2[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
3090 x2[1] = cpl_apertures_get_centroid_x(apneg, iapneg[0]);
3091 y2[1] = cpl_apertures_get_centroid_y(apneg, iapneg[0]);
3093 bug_if(cpl_propertylist_append_double(qclist,
"ESO QC ONEBEAM FLUX",
3094 cpl_apertures_get_flux(appos,
3097 cpl_msg_info(cpl_func,
"Centroid of positive object [pixel]: %g %g",
3100 cpl_msg_info(cpl_func,
"Centroid of negative object [pixel]: %g %g",
3104 cpl_msg_info(cpl_func,
"Expected object distance (chop throw) "
3105 "[pixel]: %g", pthrow);
3107 cpl_msg_info(cpl_func,
"Object Pos -> Neg x/y-distance [pixel]: %g %g",
3108 x2[1] - x2[0], y2[1] - y2[0]);
3110 cpl_msg_info(cpl_func,
"Expected object distance (chop throw) "
3111 "[pixel]: %g", -pthrow);
3113 cpl_msg_info(cpl_func,
"Object Neg -> x/y-distance [pixel]: %g %g",
3114 x2[0] - x2[1], y2[0] - y2[1]);
3119 cpl_apertures_delete(appos);
3120 cpl_apertures_delete(apneg);
3122 return cpl_error_get_code();
3148 double visir_img_check_box(
const cpl_apertures * appos,
3149 int ipos1,
int ipos2,
3150 const cpl_apertures * apneg,
3151 int ineg1,
int ineg2,
double ssize,
double angle,
3152 cpl_boolean * pswapp, cpl_boolean * pswapn)
3158 double xp1 = cpl_apertures_get_centroid_x(appos, ipos1) * cos(angle) -
3159 cpl_apertures_get_centroid_y(appos, ipos1) * sin(angle);
3160 double yp1 = cpl_apertures_get_centroid_x(appos, ipos1) * sin(angle) +
3161 cpl_apertures_get_centroid_y(appos, ipos1) * cos(angle);
3162 double xp2 = cpl_apertures_get_centroid_x(appos, ipos2) * cos(angle) -
3163 cpl_apertures_get_centroid_y(appos, ipos2) * sin(angle);
3164 double yp2 = cpl_apertures_get_centroid_x(appos, ipos2) * sin(angle) +
3165 cpl_apertures_get_centroid_y(appos, ipos2) * cos(angle);
3168 const double xpl = xp1 < xp2 ? xp1 : xp2;
3169 const double ypl = xp1 < xp2 ? yp1 : yp2;
3172 const double xpr = xp1 < xp2 ? xp2 : xp1;
3173 const double ypr = xp1 < xp2 ? yp2 : yp1;
3176 double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * cos(angle) -
3177 cpl_apertures_get_centroid_y(apneg, ineg1) * sin(angle);
3178 double yn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * sin(angle) +
3179 cpl_apertures_get_centroid_y(apneg, ineg1) * cos(angle);
3180 double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * cos(angle) -
3181 cpl_apertures_get_centroid_y(apneg, ineg2) * sin(angle);
3182 double yn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * sin(angle) +
3183 cpl_apertures_get_centroid_y(apneg, ineg2) * cos(angle);
3186 const double x_nl = xn1 < xn2 ? xn1 : xn2;
3187 const double y_nl = xn1 < xn2 ? yn1 : yn2;
3190 const double xnr = xn1 < xn2 ? xn2 : xn1;
3191 const double ynr = xn1 < xn2 ? yn2 : yn1;
3193 const double lx1 = xnr - xpl;
3194 const double lx2 = xpr - x_nl;
3195 const double ly1 = ypl - y_nl;
3196 const double ly2 = ynr - ypr;
3198 const double dx1 = lx1 - ssize;
3199 const double dx2 = lx2 - ssize;
3200 const double dy1 = ly1 - ssize;
3201 const double dy2 = ly2 - ssize;
3203 const double ey1 = ynr - ypl;
3204 const double ey2 = ypr - y_nl;
3205 const double ex1 = xpl - x_nl;
3206 const double ex2 = xpr - xnr;
3208 const double ok = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
3209 ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
3211 double result = -1.0;
3215 skip_if(pswapp == NULL);
3216 skip_if(pswapn == NULL);
3217 skip_if(appos == apneg);
3218 skip_if(ipos1 == ipos2);
3219 skip_if(ineg1 == ineg2);
3221 skip_if(ssize <= 0.0);
3223 *pswapp = xp1 < xp2 ? CPL_FALSE : CPL_TRUE;
3224 *pswapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
3255 double visir_img_check_align(
const cpl_apertures * appos,
int ipos,
3256 const cpl_apertures * apneg,
int ineg1,
int ineg2,
3257 double ssize,
double angle,
3258 cpl_boolean * pswapn)
3264 double xp = cpl_apertures_get_centroid_x(appos, ipos) * cos(angle) -
3265 cpl_apertures_get_centroid_y(appos, ipos) * sin(angle);
3266 double yp = cpl_apertures_get_centroid_x(appos, ipos) * sin(angle) +
3267 cpl_apertures_get_centroid_y(appos, ipos) * cos(angle);
3270 double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * cos(angle) -
3271 cpl_apertures_get_centroid_y(apneg, ineg1) * sin(angle);
3272 double yn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * sin(angle) +
3273 cpl_apertures_get_centroid_y(apneg, ineg1) * cos(angle);
3274 double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * cos(angle) -
3275 cpl_apertures_get_centroid_y(apneg, ineg2) * sin(angle);
3276 double yn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * sin(angle) +
3277 cpl_apertures_get_centroid_y(apneg, ineg2) * cos(angle);
3279 double result = -1.0;
3286 const double x_nl = yn1 < yn2 ? xn1 : xn2;
3287 const double y_nl = yn1 < yn2 ? yn1 : yn2;
3290 const double xnr = yn1 < yn2 ? xn2 : xn1;
3291 const double ynr = yn1 < yn2 ? yn2 : yn1;
3293 const double d1 = ynr - yp - ssize;
3294 const double d2 = yp - y_nl - ssize;
3296 const double e1 = xnr - xp;
3297 const double e2 = xp - x_nl;
3299 swapn = yn1 < yn2 ? CPL_FALSE : CPL_TRUE;
3301 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
3305 skip_if(pswapn == NULL);
3306 skip_if(appos == apneg);
3307 skip_if(ineg1 == ineg2);
3309 skip_if(ssize <= 0.0);
3340 double visir_img_check_line(
const cpl_apertures * apnear,
int inear,
3341 const cpl_apertures * apfar,
int ifar,
3342 double ssize,
double angle)
3348 double x_n = cpl_apertures_get_centroid_x(apnear, inear) * cos(angle) -
3349 cpl_apertures_get_centroid_y(apnear, inear) * sin(angle);
3350 double y_n = cpl_apertures_get_centroid_x(apnear, inear) * sin(angle) +
3351 cpl_apertures_get_centroid_y(apnear, inear) * cos(angle);
3354 double xf = cpl_apertures_get_centroid_x(apfar, ifar) * cos(angle) -
3355 cpl_apertures_get_centroid_y(apfar, ifar) * sin(angle);
3356 double yf = cpl_apertures_get_centroid_x(apfar, ifar) * sin(angle) +
3357 cpl_apertures_get_centroid_y(apfar, ifar) * cos(angle);
3359 double result = -1.0;
3363 const double d = yf - y_n - ssize;
3365 const double e = xf - x_n;
3367 ok = sqrt(d * d + e * e);
3371 skip_if(apnear == apfar);
3373 skip_if(ssize <= 0.0);
3396 static cpl_error_code
3397 get_aqu_data_type(
const cpl_frame * frame,
const cpl_propertylist * plist,
3398 const cpl_size next, visir_data_type * ptype)
3401 const char * format = NULL;
3402 if (cpl_propertylist_has(plist, VISIR_PFITS_INT_NAXIS3))
3405 if (cpl_propertylist_has(plist,
"ESO DET FRAM FORMAT"))
3406 format = cpl_propertylist_get_string(plist,
"ESO DET FRAM FORMAT");
3409 if (next >= 2 || (format && !strcmp(format,
"extension"))) {
3412 *ptype = VISIR_DATA_AQU_INT;
3415 *ptype = VISIR_DATA_AQU_HCYCLE;
3418 else if (next == 1 && (naxis3 == -1 || naxis3 == 0)) {
3419 *ptype = VISIR_DATA_AQU_BURST_EXT;
3421 else if (next == 0 && naxis3 > 0) {
3422 *ptype = VISIR_DATA_AQU_BURST;
3425 cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
3426 "Could not determine format of aquarius file %s",
3427 cpl_frame_get_filename(frame));
3430 return cpl_error_get_code();
3446 static cpl_error_code
3447 get_drs_data_type(
const cpl_frame * frame,
const cpl_propertylist * plist,
3448 visir_data_type * ptype)
3450 cpl_errorstate cleanstate = cpl_errorstate_get();
3455 const char * file = cpl_frame_get_filename(frame);
3456 cpl_boolean known_frametype = CPL_TRUE;
3460 cpl_ensure_code(ptype != NULL, CPL_ERROR_NULL_INPUT);
3464 visir_error_reset(
"Could not get FITS key");
3466 known_frametype = CPL_FALSE;
3467 }
else if (strcmp(sval,
"CUBE1")==0) {
3468 *ptype = VISIR_DATA_CUBE1;
3469 }
else if (strcmp(sval,
"CUBE2")==0) {
3470 *ptype = VISIR_DATA_CUBE2;
3473 known_frametype = CPL_FALSE;
3476 if (known_frametype && *ptype == VISIR_DATA_CUBE2) {
3477 if (naxis3 == 2 * nchop + 1) {
3479 }
else if (naxis3 == nchop + 2) {
3480 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE = '%s', but NAXIS3=%d "
3481 "and CHOP NCYCLES=%d imply a CUBE1. Assuming "
3482 "the frame type is really CUBE1", file, sval,
3484 *ptype = VISIR_DATA_CUBE1;
3486 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE = '%s', but NAXIS3=%d "
3487 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
3488 "Half-Cycle format", file, sval, naxis3, nchop);
3491 }
else if (known_frametype && *ptype == VISIR_DATA_CUBE1) {
3492 if (naxis3 == nchop + 2) {
3495 cpl_msg_debug(cpl_func,
"%s has %d INTERM-frames and one Half-"
3496 "Cycle frame (old CUBE1-format)", file, nchop);
3498 }
else if (naxis3 == 2 * nchop + 1) {
3499 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE = '%s', but NAXIS3=%d "
3500 "and CHOP NCYCLES=%d imply a CUBE2. Assuming "
3501 "the frame type is really CUBE2", file, sval,
3503 *ptype = VISIR_DATA_CUBE2;
3505 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE = '%s', but NAXIS3=%d "
3506 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
3507 "Half-Cycle format", file, sval, naxis3, nchop);
3510 }
else if (naxis3 == 2 * nchop + 1) {
3511 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE='%s', but NAXIS3=%d and "
3512 "CHOP NCYCLES=%d imply a CUBE2. Assuming the frame "
3513 "type is CUBE2", file, sval ? sval :
"<NULL>", naxis3,
3515 *ptype = VISIR_DATA_CUBE2;
3516 }
else if (naxis3 == nchop + 2) {
3517 cpl_msg_warning(cpl_func,
"%s has FRAM TYPE='%s', but NAXIS3=%d and "
3518 "CHOP NCYCLES=%d imply a CUBE1. Assuming the frame "
3519 "type is CUBE1", file, sval ? sval :
"<NULL>", naxis3,
3521 *ptype = VISIR_DATA_CUBE1;
3523 else if (!known_frametype && nchop * ndit * 2 >= naxis3) {
3524 cpl_msg_info(cpl_func,
"%s has FRAM TYPE='%s', NAXIS3=%d and "
3525 "CHOP NCYCLES=%d imply BURST data.",
3526 file, sval ? sval :
"<NULL>", naxis3, nchop);
3527 *ptype = VISIR_DATA_BURST;
3529 return cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
3530 "%s has FRAM TYPE='%s', NAXIS3 = %d and "
3531 "CHOP NCYCLES = %d", file,
3532 sval ? sval :
"<NULL>", naxis3, nchop);
3537 return cpl_error_get_code();
3552 cpl_error_code visir_get_data_type(
const cpl_frame * frame,
3553 const cpl_propertylist * plist,
3554 visir_data_type * ptype, cpl_size * pnext)
3556 const cpl_size next = cpl_frame_get_nextensions(frame);
3558 cpl_ensure_code(ptype != NULL, CPL_ERROR_NULL_INPUT);
3565 if (cpl_propertylist_has(plist,
"ESO DRS DTYPE"))
3566 *ptype = cpl_propertylist_get_int(plist,
"ESO DRS DTYPE");
3568 if (cpl_propertylist_has(plist, VISIR_PFITS_INT_NAVRG))
3569 skip_if(get_aqu_data_type(frame, plist, next, ptype));
3571 skip_if(get_drs_data_type(frame, plist, ptype));
3576 return cpl_error_get_code();
3589 cpl_error_code visir_img_burst_find_delta_chop(
const cpl_propertylist *
self,
3590 int * ichopchange,
int * ihalfcycle)
3593 const char * sdateobs =
3594 cpl_propertylist_get_string(
self, VISIR_PFITS_STRING_OBS_START);
3595 const char * schopstart =
3596 cpl_propertylist_get_string(
self, VISIR_PFITS_STRING_CHOP_START);
3598 const int nditskip =
3599 cpl_propertylist_get_int(
self, VISIR_PFITS_INT_NDITSKIP);
3602 double ddateobs, dchopstart;
3607 bug_if(irplib_wcs_mjd_from_string(&ddateobs, sdateobs));
3608 bug_if(irplib_wcs_mjd_from_string(&dchopstart, schopstart));
3610 skip_if(chop_freq <= 0.0);
3611 skip_if(dit <= 0.0);
3615 if (!cpl_propertylist_has(
self, VISIR_PFITS_INT_NAVRG)) {
3616 ddateobs += dit * nditskip / (double)VISIR_SECS_PER_DAY;
3619 period = 1.0/(chop_freq * dit);
3622 error_if((
int)(period + 0.5) % 2 != 0, CPL_ERROR_UNSUPPORTED_MODE,
3623 "Period %g not not an even number, chop frequency %g, dit %g",
3624 period, chop_freq, dit);
3626 error_if((
int)(period + 0.5) <= 1, CPL_ERROR_ILLEGAL_INPUT,
3627 "Period %d < 1", (
int)(period + 0.5));
3629 *ihalfcycle = (int)(period + 0.5)/2;
3631 cpl_msg_info(cpl_func,
"Number of A+B frames in one full chopping cycle: %g",
3634 if (dchopstart < ddateobs) {
3635 double tchop = (ddateobs - dchopstart) * (
double)VISIR_SECS_PER_DAY;
3637 double dprecycle = tchop * chop_freq;
3640 const double phase = ceil(dprecycle) - dprecycle;
3643 *ichopchange = (int)ceil(phase * period) - 1;
3645 cpl_msg_info(cpl_func,
"Chopping started %gs (%f cycles) before OBS start: "
3646 "%f < %f", tchop, dprecycle, dchopstart, ddateobs);
3648 }
else if (ddateobs < dchopstart) {
3651 double tchop = (dchopstart - ddateobs) * (
double)VISIR_SECS_PER_DAY;
3652 *ichopchange = (int)ceil(tchop / dit) - 1;
3653 cpl_msg_info(cpl_func,
"Chopping started %gs (wasted %g cycles) after OBS "
3654 "start: %f > %f", tchop, tchop * chop_freq, dchopstart,
3661 cpl_msg_info(cpl_func,
"Chopping started with OBS start: %f == %f",
3662 dchopstart, ddateobs);
3666 *ichopchange = *ichopchange % (*ihalfcycle * 2);
3668 cpl_msg_info(cpl_func,
"Frame of chop change: %d", *ichopchange);
3672 return cpl_error_get_code();
3675 #include "visir_destripe.c"
double visir_parameterlist_get_double(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR parameter of type double.
cpl_imagelist * irplib_imagelist_load_framelist(const irplib_framelist *self, cpl_type pixeltype, int planenum, int extnum)
Load an imagelist from a framelist.
double visir_pfits_get_cumoffsetx(const cpl_propertylist *self)
The cumulative offset in X.
int visir_pfits_get_naxis3(const cpl_propertylist *self)
The NAXIS3 key.
cpl_error_code visir_destripe_image(cpl_image *self, int niter, double threshold, double thres_detect, cpl_boolean morpho)
Remove the stripes frome an image using iterations.
int visir_pfits_get_navrg(const cpl_propertylist *self)
The NAVRG.
int visir_parameterlist_get_int(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR integer parameter.
const char * visir_pfits_get_frame_type(const cpl_propertylist *self)
The frame type.
cpl_boolean visir_parameterlist_get_bool(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR boolean parameter.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
int visir_pfits_get_chop_ncycles(const cpl_propertylist *self)
The number of chopping cycles.
double visir_pfits_get_chop_posang(const cpl_propertylist *self)
The chopping position angle in rad.
const char * visir_parameterlist_get_string(const cpl_parameterlist *self, const char *recipe, visir_parameter bitmask)
Retrieve the value of a VISIR string parameter.
int visir_pfits_get_ndit(const cpl_propertylist *self)
The NDIT keyword.
double visir_pfits_get_cumoffsety(const cpl_propertylist *self)
The cumulative offset in Y.
double visir_pfits_get_chop_freq(const cpl_propertylist *self)
The chopping frequency.
double visir_pfits_get_chop_throw(const cpl_propertylist *self)
The chopping throw.
const char * visir_pfits_get_nodpos(const cpl_propertylist *self)
The nodding position.
double visir_pfits_get_dit(const cpl_propertylist *self)
The DIT.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
double visir_pfits_get_pixscale(const cpl_propertylist *self)
The pixel scale.
const char * visir_pfits_get_chopnod_dir(const cpl_propertylist *self)
The chopping direction.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.