00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025
00026
00027
00028
00029
00030 #include "visir_utils.h"
00031 #include "visir_pfits.h"
00032 #include "visir_parameter.h"
00033 #include "visir_pfits.h"
00034 #include "visir_spc_distortion.h"
00035 #include "visir_inputs.h"
00036 #include "irplib_framelist.h"
00037 #include "irplib_wcs.h"
00038 #include <cpl.h>
00039
00040 #include <string.h>
00041 #include <math.h>
00042 #include <float.h>
00043 #include <assert.h>
00044
00045
00046
00047
00048
00049 #define VISIR_SECS_PER_DAY (24 * 3600)
00050
00051 #define FIND_BEAM_MAX_APERTURES_SQR (40 * 40)
00052
00053
00054
00055
00056
00057
00058 #include "visir_destripe.h"
00059
00060 static cpl_image * visir_load_average(const char *,
00061 const cpl_propertylist *);
00062 static cpl_imagelist * visir_load_intermint(const irplib_framelist *, int);
00063 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist *);
00064 static cpl_error_code visir_rem_glitch(cpl_image *);
00065 static cpl_error_code visir_rem_bad_images(cpl_imagelist *);
00066 static cpl_error_code visir_offset_hcycle(cpl_image *);
00067
00068 static cpl_image ** visir_img_collapse_beam_four(cpl_propertylist *,
00069 const cpl_image *,
00070 const cpl_image *,
00071 double, double, double,
00072 const cpl_propertylist *);
00073
00074 static cpl_image ** visir_img_collapse_beam_three(cpl_propertylist *,
00075 const cpl_image *,
00076 const cpl_image *,
00077 double, double,
00078 const cpl_propertylist *);
00079
00080
00081 static cpl_error_code visir_img_find_beam_three(cpl_propertylist *,
00082 const cpl_image *,
00083 const cpl_image *,
00084 double, double, double,
00085 double *,
00086 double *);
00087
00088 static cpl_error_code visir_img_find_beam_four(cpl_propertylist *,
00089 const cpl_image *,
00090 const cpl_image *,
00091 double, double, double,
00092 double *,
00093 double *);
00094
00095
00096
00100
00101
00105
00118
00119
00120 static
00121 cpl_error_code visir_load_cube2_split_(cpl_imagelist * alist, cpl_imagelist * blist,
00122 cpl_imagelist * packed, cpl_image * prevd)
00123 {
00124
00125 int naxis3 = cpl_imagelist_get_size(packed);
00126 int prevd_insert_pos = cpl_imagelist_get_size(blist);
00127
00128 bug_if(alist == NULL);
00129 bug_if(blist == NULL);
00130
00131
00132 if (prevd)
00133 cpl_imagelist_set(blist, prevd, prevd_insert_pos);
00134
00135
00136 for (int i = 0; i < naxis3/2; i++) {
00137 cpl_image * aimage = cpl_imagelist_unset(packed, 0);
00138 cpl_image * dimage = cpl_imagelist_unset(packed, 0);
00139
00140 cpl_imagelist_set(alist, aimage, cpl_imagelist_get_size(alist));
00141 cpl_imagelist_set(blist, dimage, cpl_imagelist_get_size(blist));
00142
00143 }
00144
00145 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00146
00147
00148 bug_if(visir_imagelist_unpack_interm(blist));
00149
00150
00151 if (prevd)
00152 cpl_imagelist_unset(blist, prevd_insert_pos);
00153
00154 for (int i = 0; i < naxis3/2; i++) {
00155 cpl_image * aimage = cpl_imagelist_get(alist, i);
00156 cpl_image * dimage = cpl_imagelist_get(blist, i);
00157
00158 cpl_image * bimage = cpl_image_subtract_create(aimage, dimage);
00159
00160 visir_offset_hcycle(aimage);
00161 visir_offset_hcycle(bimage);
00162
00163 bug_if(cpl_imagelist_set(blist, bimage, i));
00164
00165 }
00166
00167 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00168
00169 end_skip;
00170
00171 return cpl_error_get_code();
00172
00173 }
00174
00175
00176
00188
00189 static cpl_imagelist * load_range(const char * filename,
00190 cpl_type im_type,
00191 int iext,
00192 int pstart,
00193 int pend)
00194 {
00195 int selfsize = 0;
00196 cpl_imagelist * self = cpl_imagelist_new();
00197
00198 for (int iplane = pstart; iplane < pend; iplane++) {
00199 cpl_image * image = cpl_image_load(filename, im_type, iplane, iext);
00200
00201 if (image == NULL) break;
00202
00203 if (cpl_imagelist_set(self, image, selfsize)) {
00204 cpl_image_delete(image);
00205 break;
00206 }
00207
00208 selfsize++;
00209 }
00210 return self;
00211 }
00212
00213
00214
00237
00238 cpl_error_code visir_load_cube2_split(cpl_imagelist * alist, cpl_imagelist * blist,
00239 const irplib_framelist * rawframes, int pos,
00240 const int planestart, const int planeend)
00241 {
00242
00243 cpl_imagelist * packed = NULL;
00244 const cpl_frame * frame = irplib_framelist_get_const(rawframes, pos);
00245 const char * file = cpl_frame_get_filename(frame);
00246 int naxis3;
00247 visir_data_type data_type;
00248 int pend;
00249 cpl_image * prevd = NULL;
00250 const cpl_propertylist * plist =
00251 irplib_framelist_get_propertylist_const(rawframes, pos);
00252 const int iext = cpl_propertylist_has(plist, "ZNAXIS3") ? 1 : 0;
00253 const int nchop = plist ? visir_pfits_get_chop_ncycles(plist) : -1;
00254
00255 skip_if(0);
00256
00257 skip_if(visir_get_data_type(frame, plist, &data_type, NULL));
00258
00259 cpl_ensure_code(data_type == VISIR_DATA_CUBE2, CPL_ERROR_ILLEGAL_INPUT);
00260
00261 naxis3 = visir_pfits_get_naxis3(plist);
00262
00263
00264
00265 error_if(planestart % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
00266 "Plane start %d wrong. It must be even.", planestart);
00267 error_if(planeend < naxis3 && planeend % 2 == 1, CPL_ERROR_ILLEGAL_INPUT,
00268 "Plane end %d wrong. It must be even if not larger naxis3=%d",
00269 planeend, naxis3);
00270
00271 any_if("Cannot split non-CUBE2 frame %d/%d in %s", 1+pos,
00272 irplib_framelist_get_size(rawframes), file);
00273 bug_if(alist == NULL);
00274 bug_if(blist == NULL);
00275
00276 error_if(data_type != VISIR_DATA_CUBE2, CPL_ERROR_INCOMPATIBLE_INPUT,
00277 "Cannot split non-CUBE2 frame %d/%d w. NAXIS3=%d, "
00278 "NCYCLES=%d in %s", 1+pos,
00279 irplib_framelist_get_size(rawframes), naxis3, nchop, file);
00280
00281 if (planeend >= naxis3 || planeend < 0)
00282 pend = naxis3 - 1;
00283 else
00284 pend = planeend;
00285
00286 if (planestart != 0) {
00287 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
00288 iext, planestart - 1, pend);
00289 prevd = cpl_imagelist_unset(packed, 0);
00290 }
00291 else
00292 packed = load_range(file, CPL_TYPE_UNSPECIFIED, iext, planestart, pend);
00293
00294 skip_if(visir_load_cube2_split_(alist, blist, packed, prevd));
00295
00296 end_skip;
00297
00298 cpl_image_delete(prevd);
00299 cpl_imagelist_delete(packed);
00300
00301 return cpl_error_get_code();
00302 }
00303
00304
00305
00322
00323 static
00324 cpl_error_code visir_load_burst_(cpl_imagelist * alist, cpl_imagelist * blist,
00325 cpl_imagelist * packed,
00326 const int ichopchange, const int ihalfcycle,
00327 const int trimlow, int const trimhigh)
00328 {
00329 cpl_boolean bon = CPL_TRUE;
00330 const int offset = 0;
00331 const int pend = cpl_imagelist_get_size(packed);
00332 int lorej = ihalfcycle - trimlow;
00333 int hirej = trimhigh + 1;
00334
00335
00336
00337 int chpmv = ichopchange - ihalfcycle * 2;
00338
00339 cpl_ensure_code(trimhigh >= -1, CPL_ERROR_ILLEGAL_INPUT);
00340 cpl_ensure_code(trimlow >= 0, CPL_ERROR_ILLEGAL_INPUT);
00341 cpl_ensure_code(ichopchange < ihalfcycle * 2, CPL_ERROR_ILLEGAL_INPUT);
00342 cpl_ensure_code(alist != NULL, CPL_ERROR_NULL_INPUT);
00343 cpl_ensure_code(blist != NULL, CPL_ERROR_NULL_INPUT);
00344
00345 skip_if(0);
00346
00347
00348
00349
00350 for (int i = chpmv; i < pend; i++) {
00351 if ((i + ihalfcycle * 2) % ihalfcycle == ichopchange % ihalfcycle) {
00352 bon = !bon;
00353 hirej = trimhigh + 1;
00354 lorej = ihalfcycle - trimlow;
00355 }
00356 if (hirej <= 0 && lorej > 0 && i >= 0) {
00357 if (bon) {
00358 cpl_image * image= cpl_imagelist_unset(packed, offset);
00359 cpl_imagelist_set(alist, image, cpl_imagelist_get_size(alist));
00360 }
00361 else {
00362 cpl_image * image= cpl_imagelist_unset(packed, offset);
00363 cpl_imagelist_set(blist, image, cpl_imagelist_get_size(blist));
00364 }
00365 }
00366 else if (i >= 0)
00367 cpl_image_delete(cpl_imagelist_unset(packed, offset));
00368
00369 hirej--;
00370 lorej--;
00371 }
00372
00373 cpl_msg_info(cpl_func, "On: %d, Off %d, Skipped %d",
00374 (int)cpl_imagelist_get_size(alist),
00375 (int)cpl_imagelist_get_size(blist),
00376 (int)(pend - cpl_imagelist_get_size(alist)
00377 - cpl_imagelist_get_size(blist)));
00378
00379 skip_if_lt(0, cpl_imagelist_get_size(packed), "Too many packed frames");
00380
00381 end_skip;
00382
00383 return cpl_error_get_code();
00384 }
00385
00386
00387
00396
00397 static int get_to_off_plane(int chopchange, const int offset,
00398 const int ihalfcycle)
00399 {
00400 const int ifullcycle = ihalfcycle * 2;
00401
00402 if (offset -
00403 (offset / ifullcycle) * ifullcycle > chopchange)
00404 chopchange += ifullcycle - (offset % ifullcycle);
00405 else
00406 chopchange -= (offset % ifullcycle);
00407 return chopchange;
00408 }
00409
00410
00411
00432
00433 cpl_error_code visir_load_burst(cpl_imagelist * alist, cpl_imagelist * blist,
00434 const cpl_frame * frame, const cpl_propertylist * plist,
00435 const int ichopchange, const int ihalfcycle,
00436 const int planestart, const int planeend,
00437 const int trimlow, const int trimhigh)
00438 {
00439 const char * file = cpl_frame_get_filename(frame);
00440 const int naxis3 = visir_pfits_get_naxis3(plist);
00441 const int pend = planeend <= 0 || planeend > naxis3 ? naxis3 : planeend;
00442 cpl_imagelist * packed;
00443 int to_off = get_to_off_plane(ichopchange, planestart, ihalfcycle);
00444
00445 cpl_msg_info(cpl_func, "Loading planes %d to %d, to off %d",
00446 planestart, pend, planestart + to_off);
00447
00448 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
00449 cpl_propertylist_has(plist, "ZNAXIS3") ? 1 : 0,
00450 planestart, pend);
00451
00452 skip_if(packed == NULL);
00453
00454 if (cpl_imagelist_get_size(packed) > 0) {
00455 cpl_image * timg = cpl_imagelist_get(packed, 0);
00456 size_t nbytes = visir_get_nbytes(timg);
00457 visir_drop_cache(file, 0, nbytes * pend);
00458 }
00459
00460 skip_if(visir_load_burst_(alist, blist, packed, to_off, ihalfcycle,
00461 trimlow, trimhigh));
00462
00463 end_skip;
00464
00465 cpl_imagelist_delete(packed);
00466
00467 return cpl_error_get_code();
00468 }
00469
00470
00471 cpl_error_code
00472 visir_load_burst_aqu(cpl_imagelist * alist, cpl_imagelist * blist,
00473 const cpl_frame * frame, const cpl_propertylist * plist,
00474 const int ihalfcycle,
00475 const int planestart, const int planeend)
00476 {
00477 const char * file = cpl_frame_get_filename(frame);
00478 const int naxis3 = visir_pfits_get_naxis3(plist);
00479 const size_t pend = planeend <= 0 || planeend > naxis3 ? naxis3 : planeend;
00480 cpl_imagelist * packed;
00481
00482 cpl_msg_info(cpl_func, "Loading planes %d to %zu",
00483 planestart, pend);
00484
00485 packed = load_range(file, CPL_TYPE_UNSPECIFIED,
00486 cpl_propertylist_has(plist, "ZNAXIS3") ? 1 : 0,
00487 planestart, pend);
00488
00489 skip_if(packed == NULL);
00490
00491 if (cpl_imagelist_get_size(packed) > 0) {
00492 cpl_image * timg = cpl_imagelist_get(packed, 0);
00493 size_t nbytes = visir_get_nbytes(timg);
00494 visir_drop_cache(file, 0, nbytes * pend);
00495 }
00496
00497 cpl_boolean bon = CPL_FALSE;
00498 int it = 0;
00499 for (size_t i = planestart; i < pend; i++) {
00500 if (bon) {
00501 cpl_image * image = cpl_imagelist_unset(packed, 0);
00502 cpl_imagelist_set(alist, image, cpl_imagelist_get_size(alist));
00503 }
00504 else {
00505 cpl_image * image = cpl_imagelist_unset(packed, 0);
00506 cpl_imagelist_set(blist, image, cpl_imagelist_get_size(blist));
00507 }
00508 it++;
00509 if (it == ihalfcycle){
00510 bon = !bon;
00511 it = 0;
00512 }
00513 }
00514
00515 end_skip;
00516
00517 cpl_imagelist_delete(packed);
00518
00519 return cpl_error_get_code();
00520 }
00521
00522
00531
00532 cpl_bivector * visir_load_lintable(cpl_frame * linframe, cpl_boolean is_spec)
00533 {
00534 cpl_bivector * lintable = NULL;
00535 const char * extname;
00536 cpl_ensure(linframe, CPL_ERROR_NULL_INPUT, NULL);
00537 if (is_spec) {
00538 extname = "SPEC_LIN";
00539 }
00540 else {
00541 extname = "IMAGE_LIN";
00542 }
00543 const char * fn = cpl_frame_get_filename(linframe);
00544 cpl_size iext = cpl_fits_find_extension(fn, extname);
00545 error_if(iext < 0, CPL_ERROR_ILLEGAL_INPUT,
00546 "Linearity correction extension %s not found in %s", extname, fn);
00547
00548 cpl_table * tab = cpl_table_load(fn, iext, 0);
00549 const size_t nrow = cpl_table_get_nrow(tab);
00550 lintable = cpl_bivector_new(nrow);
00551 memcpy(cpl_bivector_get_x_data(lintable),
00552 cpl_table_get_data_double(tab, "dc_level"),
00553 sizeof(double) * nrow);
00554 memcpy(cpl_bivector_get_y_data(lintable),
00555 cpl_table_get_data_double(tab, "conv_gain"),
00556 sizeof(double) * nrow);
00557 cpl_table_delete(tab);
00558
00559
00560 cpl_vector_divide_scalar(cpl_bivector_get_y(lintable),
00561 cpl_vector_get_mean(cpl_bivector_get_y(lintable)));
00562 cleanup:
00563 return lintable;
00564 }
00565
00566
00567 cpl_image *
00568 visir_load_bpm(cpl_frame * frm, visir_data_type dtype, cpl_boolean is_spec)
00569 {
00570 const char * fn = cpl_frame_get_filename(frm);
00571 const char * extname;
00572 if (visir_data_is_aqu(dtype)) {
00573 extname = is_spec ? "BPM_AQU_SPC" : "BPM_AQU_IMG";
00574 }
00575 else {
00576 extname = is_spec ? "BPM_DRS_SPC" : "BPM_DRS_IMG";
00577 }
00578 cpl_size iext = cpl_fits_find_extension(fn, extname);
00579 cpl_msg_info(cpl_func, "Loading BPM extension %s from %s", extname, fn);
00580 if (iext < 0) {
00581 return NULL;
00582 }
00583 return cpl_image_load(fn, CPL_TYPE_UNSPECIFIED, 0, iext);
00584 }
00585
00586
00608
00609 cpl_image ** visir_img_collapse_beam(cpl_propertylist * qclist,
00610 const cpl_image * self,
00611 const cpl_parameterlist * parlist,
00612 const char * recipename,
00613 visir_chopnod_mode mode,
00614 const cpl_propertylist * plist)
00615 {
00616
00617 cpl_image ** combined = NULL;
00618
00619 cpl_image * inverse = cpl_image_multiply_scalar_create(self, -1.0);
00620
00621 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
00622 VISIR_PARAM_ECCMAX);
00623
00624
00625 const double pscale = visir_pfits_get_pixscale(plist);
00626 const double pthrow = pscale > 0.0
00627 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
00628 double angle = visir_pfits_get_chop_posang(plist);
00629
00630 skip_if(self == NULL);
00631 skip_if(parlist == NULL);
00632 skip_if(qclist == NULL);
00633 skip_if(plist == NULL);
00634
00635 if (mode == VISIR_CHOPNOD_PERPENDICULAR) {
00636
00637 combined = visir_img_collapse_beam_four(qclist, self, inverse, eccmax,
00638 pthrow, angle, plist);
00639 } else if (mode == VISIR_CHOPNOD_PARALLEL) {
00640
00641 combined = visir_img_collapse_beam_three(qclist, self, inverse, eccmax,
00642 pthrow, plist);
00643 } else if (mode == VISIR_CHOPNOD_AUTO) {
00644 cpl_errorstate cleanstate = cpl_errorstate_get();
00645
00646 const char * sdir = visir_pfits_get_chopnod_dir(plist);
00647
00648 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
00649
00650 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00651 eccmax, pthrow, angle, plist);
00652 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
00653
00654 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00655 eccmax, pthrow, plist);
00656 } else {
00657 if (sdir == NULL) {
00658 visir_error_reset("Could not get FITS key");
00659 } else {
00660 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
00661 sdir);
00662 }
00663 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
00664 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
00665 "PERPENDICULAR");
00666 combined = visir_img_collapse_beam_four(qclist, self, inverse,
00667 eccmax, pthrow, angle, plist);
00668 if (combined == NULL) {
00669 visir_error_reset("Proceeding as if FITS card "
00670 VISIR_PFITS_STRING_CHOPNOD_DIR
00671 " had value: %s", "PARALLEL");
00672 combined = visir_img_collapse_beam_three(qclist, self, inverse,
00673 eccmax, pthrow, plist);
00674 }
00675 }
00676 } else {
00677 bug_if(1);
00678 }
00679
00680 skip_if(combined == NULL);
00681
00682 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
00683 pthrow));
00684 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
00685 "The throw in pixels (TEL CHOP THROW "
00686 "divided by INS PFOV)"));
00687
00688 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM XPOS",
00689 "The X pixel position (centroid) "
00690 "of the one-beam object"));
00691
00692 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM YPOS",
00693 "The Y pixel position (centroid) "
00694 "of the one-beam object"));
00695 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM ECCENTRICITY",
00696 "Eccentricity: 0 for perfect, throw-"
00697 "sized square/line"));
00698
00699 end_skip;
00700
00701 cpl_image_delete(inverse);
00702
00703 return combined;
00704 }
00705
00706
00707
00790
00791 cpl_imagelist * visir_inputs_combine(const char * recipename,
00792 const cpl_parameterlist * parlist,
00793 const irplib_framelist * rawframes,
00794 const char * badpix,
00795 const char * flat,
00796 int * nodding_p,
00797 cpl_boolean do_spc_fix,
00798 double wlen,
00799 visir_spc_resol resol)
00800 {
00801 const char * fnodpos;
00802 int nfiles;
00803 cpl_imagelist * in = NULL;
00804 cpl_image * collapsed = NULL;
00805 cpl_image * prev = NULL;
00806 cpl_vector * nods_vec = NULL;
00807 double * nods_data;
00808 int * nod_pos = NULL;
00809 cpl_image ** images = NULL;
00810 cpl_imagelist * nodded = NULL;
00811 int nnod;
00812 cpl_image * flat_image = NULL;
00813 cpl_image * bpm_im_int = NULL;
00814 cpl_mask * bpm_im_bin = NULL;
00815 cpl_imagelist * hcycle = NULL;
00816 cpl_boolean no_rem;
00817 cpl_boolean is_nodding = CPL_FALSE;
00818 int i, j;
00819 cpl_boolean auto_bpm, rem_glitch, rem_bad;
00820 int ndestripe;
00821 int naxis1, naxis2;
00822 cpl_boolean morpho_destripe;
00823 double tstart, tstop;
00824 const cpl_propertylist * plist1;
00825 #ifdef _OPENMP
00826 cpl_errorstate cleanstate = cpl_errorstate_get();
00827 #endif
00828 cpl_error_code didfail = CPL_ERROR_NONE;
00829
00830
00831 skip_if (0);
00832 skip_if(recipename == NULL);
00833 skip_if(parlist == NULL);
00834 skip_if(rawframes == NULL);
00835
00836
00837 nfiles = irplib_framelist_get_size(rawframes);
00838
00839
00840 if (nfiles % 2) {
00841 cpl_msg_warning(cpl_func, "Expecting even number of files, "
00842 "ignoring the last of %d file(s)", nfiles);
00843 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
00844 "At least two files are required");
00845 nfiles--;
00846 }
00847
00848 nnod = nfiles/2;
00849
00850 skip_if (nnod <= 0);
00851
00852 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_FRAME_TYPE,
00853 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00854 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_DOUBLE_DIT,
00855 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00856
00857 skip_if (irplib_framelist_contains(rawframes, "NAXIS1",
00858 CPL_TYPE_INT, CPL_TRUE, 0.0));
00859 skip_if (irplib_framelist_contains(rawframes, "NAXIS2",
00860 CPL_TYPE_INT, CPL_TRUE, 0.0));
00861 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
00862 CPL_TYPE_INT, CPL_FALSE, 0.0));
00863 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_CHOP_NCYCLES,
00864 CPL_TYPE_INT, CPL_FALSE, 0.0));
00865
00866 plist1 = irplib_framelist_get_propertylist_const(rawframes, 0);
00867 naxis1 = irplib_pfits_get_int(plist1, "NAXIS1");
00868 naxis2 = irplib_pfits_get_int(plist1, "NAXIS2");
00869 skip_if(0);
00870
00871
00872 fnodpos = visir_parameterlist_get_string(parlist, recipename,
00873 VISIR_PARAM_NODPOS);
00874 skip_if (0);
00875
00876 auto_bpm = visir_parameterlist_get_bool(parlist, recipename,
00877 VISIR_PARAM_AUTOBPM);
00878 skip_if (0);
00879
00880 rem_glitch = visir_parameterlist_get_bool(parlist, recipename,
00881 VISIR_PARAM_GLITCH);
00882 skip_if (0);
00883
00884 rem_bad = visir_parameterlist_get_bool(parlist, recipename,
00885 VISIR_PARAM_PURGE);
00886 skip_if (0);
00887
00888 ndestripe = visir_parameterlist_get_int(parlist, recipename,
00889 VISIR_PARAM_STRIPITE);
00890 bug_if (0);
00891
00892 morpho_destripe = ndestripe <= 0 ? CPL_FALSE :
00893 visir_parameterlist_get_bool(parlist, recipename,
00894 VISIR_PARAM_STRIPMOR);
00895 bug_if (0);
00896
00897 no_rem = !rem_glitch && !rem_bad;
00898
00899
00900
00901 nod_pos = nodding_p ? nodding_p : cpl_malloc(nfiles * sizeof(int));
00902 j = 0;
00903 if (!visir_str_par_is_empty(fnodpos)) {
00904
00905 nods_vec = cpl_vector_read(fnodpos);
00906 skip_if (cpl_vector_get_size(nods_vec) != nfiles);
00907 nods_data = cpl_vector_get_data(nods_vec);
00908 skip_if (0);
00909 for (i=0 ; i<nfiles ; i++) {
00910 if ((int)nods_data[i] == 0) {
00911 nod_pos[i] = 1;
00912 j++;
00913 } else if ((int)nods_data[i] == 1) {
00914 nod_pos[i] = -1;
00915 is_nodding = CPL_TRUE;
00916 } else {
00917 error_if(1, CPL_ERROR_BAD_FILE_FORMAT,
00918 "Wrong values in line %d in %s", i+1, fnodpos);
00919 }
00920 }
00921 } else {
00922 skip_if (irplib_framelist_contains(rawframes, VISIR_PFITS_STRING_NODPOS,
00923 CPL_TYPE_STRING, CPL_FALSE, 0.0));
00924 }
00925
00926 if (no_rem) cpl_msg_info(cpl_func, "No glitch removal and no purge of bad "
00927 "frames requested: Using fast I/O method");
00928
00929
00930 if (badpix != NULL) {
00931
00932 cpl_msg_info(cpl_func, "Loading bad pixel map from %s", badpix);
00933
00934 bpm_im_int = cpl_image_load(badpix, CPL_TYPE_INT, 0, 0);
00935 skip_if (0);
00936
00937
00938 bpm_im_bin = cpl_mask_threshold_image_create(bpm_im_int, -0.5, 0.5);
00939 cpl_image_delete(bpm_im_int);
00940 bpm_im_int = NULL;
00941 skip_if (cpl_mask_not(bpm_im_bin));
00942 } else if (auto_bpm) {
00943
00944
00945
00946 hcycle = visir_load_imagelist(rawframes, 0, CPL_FALSE);
00947 skip_if(0);
00948
00949 bpm_im_bin =
00950 cpl_mask_threshold_image_create(cpl_imagelist_get(hcycle,0),
00951 VISIR_HCYCLE_BPM_THRESHOLD,
00952 DBL_MAX);
00953 cpl_imagelist_delete(hcycle);
00954 hcycle = NULL;
00955 skip_if(0);
00956 }
00957
00958
00959 if (flat != NULL) {
00960 cpl_msg_info(cpl_func, "Divide the nodded images by the flatfield");
00961
00962 flat_image = cpl_image_load(flat, CPL_TYPE_FLOAT, 0, 0);
00963 any_if ("Cannot load the flat field %s", flat ? flat : "<NULL>");
00964 }
00965
00966
00967 nodded = cpl_imagelist_new();
00968
00969 tstart = cpl_test_get_walltime();
00970
00971
00972
00973 for (i=0; i < nfiles/2 ; i++) {
00974 cpl_image * empty = cpl_image_new(naxis1, naxis2, CPL_TYPE_FLOAT);
00975
00976
00977
00978
00979 bug_if (cpl_imagelist_set(nodded, empty, i));
00980 }
00981
00982 #ifdef _OPENMP
00983 #pragma omp parallel for private(i) firstprivate(prev, collapsed) \
00984 schedule(static, 2)
00985 #endif
00986 for (i = 0; i < nfiles ; i++) {
00987 cpl_error_code errori = cpl_error_get_code();
00988
00989
00990
00991
00992
00993
00994
00995 if (didfail) continue;
00996
00997 do {
00998
00999 const char * file =
01000 cpl_frame_get_filename(irplib_framelist_get_const(rawframes, i));
01001 const cpl_propertylist * plist;
01002
01003 double dit;
01004 double factor;
01005
01006
01007 plist = irplib_framelist_get_propertylist_const(rawframes, i);
01008 if (plist == NULL) {
01009 errori = cpl_error_set_where(cpl_func);
01010 break;
01011 }
01012
01013 if (nods_vec == NULL) {
01014 const char * sval = visir_pfits_get_nodpos(plist);
01015 if (sval == NULL) {
01016 errori = cpl_error_set_message(cpl_func,
01017 CPL_ERROR_DATA_NOT_FOUND,
01018 "Cannot get nodding position "
01019 "for file %d/%d", i+1, nfiles);
01020 break;
01021 }
01022 if (!strcmp(sval, "A")) {
01023 nod_pos[i] = 1;
01024 # ifdef _OPENMP
01025 # pragma omp atomic
01026 # endif
01027 j++;
01028 } else {
01029 nod_pos[i] = -1;
01030 is_nodding = CPL_TRUE;
01031 }
01032 }
01033
01034
01035 cpl_msg_info(cpl_func, "File %02d: %s (%c)", i+1, file,
01036 nod_pos[i]==1 ? '+' : '-');
01037
01038
01039 if (is_nodding && (i & 1) == 1 && nod_pos[i] == nod_pos[i-1]) {
01040 cpl_msg_error(cpl_func, "Nodding pair (%d,%d) does not comprise an "
01041 "on-object (A) and an off-object (B) image: %s", i-1,
01042 i, nod_pos[i] == 1 ? "A" : "B");
01043 }
01044
01045
01046 dit = visir_pfits_get_dit(plist);
01047 if (cpl_error_get_code()) {
01048 errori = cpl_error_set_where(cpl_func);
01049 break;
01050 }
01051
01052 if (dit <= 0) {
01053 errori = cpl_error_set_message(cpl_func,
01054 CPL_ERROR_ILLEGAL_INPUT,
01055 "DIT in file %d/%d is too small: "
01056 "%g", i+1, nfiles, dit);
01057 break;
01058 }
01059
01060 factor = dit * nod_pos[i] * 2.0;
01061
01062 if (no_rem){
01063 collapsed = visir_load_average(file, plist);
01064 } else {
01065 in = visir_load_intermint(rawframes, i);
01066 if (in == NULL) {
01067 errori = cpl_error_set_message(cpl_func,
01068 CPL_ERROR_ILLEGAL_INPUT,
01069 "Could not load image set %d",
01070 i+1);
01071 break;
01072 }
01073
01074
01075 if (visir_imagelist_unpack_interm(in)) {
01076 errori = cpl_error_set_message(cpl_func,
01077 cpl_error_get_code(),
01078 "Failure for file %d/%d",
01079 i+1, nfiles);
01080 break;
01081 }
01082
01083
01084
01085 if (rem_glitch) {
01086 int jj;
01087 for (jj=0 ; jj < cpl_imagelist_get_size(in); jj++) {
01088 if (visir_rem_glitch(cpl_imagelist_get(in, jj))) {
01089 errori = cpl_error_set_message(cpl_func,
01090 cpl_error_get_code(),
01091 "Could not remove "
01092 "glitch in image %d in "
01093 "set %d", jj+1, i+1);
01094 break;
01095 }
01096 }
01097 }
01098
01099
01100 if (rem_bad) {
01101 cpl_msg_info(cpl_func, "Remove the bad A-B input images");
01102 if (visir_rem_bad_images(in)) {
01103 errori = cpl_error_set_message(cpl_func,
01104 cpl_error_get_code(),
01105 "Could not remove bad "
01106 "images in list %d", i+1);
01107 break;
01108 }
01109 }
01110
01111 collapsed = cpl_imagelist_collapse_create(in);
01112
01113 cpl_imagelist_delete(in);
01114 in = NULL;
01115
01116 }
01117
01118 if (cpl_error_get_code()) {
01119 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01120 "Failure for file %d/%d",
01121 i+1, nfiles);
01122 break;
01123 }
01124
01125
01126 if (cpl_image_divide_scalar(collapsed, 2*factor)) {
01127 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01128 "Failure for file %d/%d",
01129 i+1, nfiles);
01130 break;
01131 }
01132
01133
01134 if (i & 1) {
01135 if (cpl_image_add(prev, collapsed)) {
01136 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01137 "Failure for file %d/%d",
01138 i+1, nfiles);
01139 break;
01140 }
01141 cpl_image_delete(collapsed);
01142 collapsed = NULL;
01143
01144
01145
01146
01147 if (bpm_im_bin != NULL) {
01148
01149 if (cpl_image_reject_from_mask(prev, bpm_im_bin)) {
01150 errori = cpl_error_set_message(cpl_func,
01151 cpl_error_get_code(),
01152 "Failure for file %d/%d",
01153 i+1, nfiles);
01154 break;
01155 }
01156 if (cpl_detector_interpolate_rejected(prev)) {
01157 errori = cpl_error_set_message(cpl_func,
01158 cpl_error_get_code(),
01159 "Failure for file %d/%d",
01160 i+1, nfiles);
01161 break;
01162 }
01163 }
01164
01165 if (ndestripe > 0)
01166 if(visir_destripe_image(prev, ndestripe,
01167 VISIR_DESTRIPE_DETECT,
01168 VISIR_DESTRIPE_DETECT_THRESHOLD,
01169 morpho_destripe)) {
01170 errori = cpl_error_set_message(cpl_func,
01171 cpl_error_get_code(),
01172 "Failure for file %d/%d",
01173 i+1, nfiles);
01174 break;
01175 }
01176
01177 if (flat_image != NULL) {
01178
01179 if (cpl_image_divide(prev, flat_image)) {
01180 errori = cpl_error_set_message(cpl_func,
01181 cpl_error_get_code(),
01182 "Failure for file %d/%d",
01183 i+1, nfiles);
01184 break;
01185 }
01186 }
01187
01188 if (cpl_imagelist_set(nodded, prev, i/2)) {
01189 errori = cpl_error_set_message(cpl_func, cpl_error_get_code(),
01190 "Failure for file %d/%d",
01191 i+1, nfiles);
01192 break;
01193 }
01194 prev = NULL;
01195 } else {
01196 prev = collapsed;
01197 collapsed = NULL;
01198 }
01199 } while (0);
01200
01201 if (errori) {
01202 #ifdef _OPENMP
01203
01204
01205 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
01206 cpl_errorstate_set(cleanstate);
01207
01208
01209 cpl_image_delete(prev); prev = NULL;
01210 cpl_image_delete(collapsed); collapsed = NULL;
01211
01212 #pragma omp critical(visir_inputs_combine)
01213 #endif
01214 didfail = errori;
01215 }
01216 }
01217
01218 error_if(didfail, didfail, "Failed to create %d nodded images from %d "
01219 "files", nnod, nfiles);
01220
01221 tstop = cpl_test_get_walltime();
01222 cpl_msg_info(cpl_func, "Time to create %d nodded images [s]: %g", nnod,
01223 tstop - tstart);
01224
01225 cpl_vector_delete(nods_vec);
01226 nods_vec = NULL;
01227
01228 cpl_image_delete(flat_image);
01229 flat_image = NULL;
01230
01231 cpl_mask_delete(bpm_im_bin);
01232 bpm_im_bin = NULL;
01233
01234 if (nod_pos != nodding_p) cpl_free(nod_pos);
01235 nod_pos = NULL;
01236
01237 error_if(is_nodding && j != nnod, CPL_ERROR_INCOMPATIBLE_INPUT,
01238 "With nodding exactly half of the images "
01239 "must be on-object, not %d of %d", j, 2*nnod);
01240
01241 if (do_spc_fix) {
01242 const double ksi = visir_parameterlist_get_double(parlist, recipename,
01243 VISIR_PARAM_SPECSKEW);
01244 const double eps = visir_parameterlist_get_double(parlist, recipename,
01245 VISIR_PARAM_VERTARC);
01246 const double delta = visir_parameterlist_get_double(parlist, recipename,
01247 VISIR_PARAM_HORIARC);
01248 const double phi = visir_parameterlist_get_double(parlist, recipename,
01249 VISIR_PARAM_SLITSKEW);
01250 const int doplot = visir_parameterlist_get_int(parlist, recipename,
01251 VISIR_PARAM_PLOT);
01252
01253
01254 skip_if (0);
01255
01256 images = cpl_malloc(nnod * sizeof(cpl_image*));
01257
01258 for (j = 0; j < nnod; j++) images[j] = cpl_imagelist_get(nodded, j);
01259
01260 skip_if (visir_spc_det_fix(images, nnod, CPL_TRUE, wlen, resol,
01261 phi, ksi, eps, delta, doplot));
01262 }
01263
01264 end_skip;
01265
01266 cpl_msg_set_time_off();
01267
01268 cpl_free(images);
01269 cpl_imagelist_delete(in);
01270
01271 if (nod_pos != nodding_p) cpl_free(nod_pos);
01272 cpl_vector_delete(nods_vec);
01273 cpl_image_delete(bpm_im_int);
01274 cpl_mask_delete(bpm_im_bin);
01275 cpl_image_delete(collapsed);
01276 cpl_image_delete(prev);
01277 if (cpl_error_get_code() && nodded != NULL) {
01278 cpl_imagelist_delete(nodded);
01279 nodded = NULL;
01280 }
01281
01282 return nodded;
01283 }
01284
01285
01294
01295 static double
01296 get_cumoffsets(const cpl_propertylist * plist, double * x, double * y)
01297 {
01298 cpl_errorstate cleanstate = cpl_errorstate_get();
01299
01300 *x = irplib_pfits_get_double(plist, "ESO DRS CUMOFFSETX");
01301 *y = irplib_pfits_get_double(plist, "ESO DRS CUMOFFSETY");
01302
01303 if (cpl_error_get_code() != CPL_ERROR_NONE) {
01304 cpl_errorstate_set(cleanstate);
01305 cpl_msg_info(cpl_func, "DRS CUMOFFSET[XY] not found, falling back"
01306 " to SEQ CUMOFFSET[XY]");
01307 *x = visir_pfits_get_cumoffsetx(plist);
01308 *y = visir_pfits_get_cumoffsety(plist);
01309 }
01310 return cpl_error_get_code();
01311 }
01312
01313
01328
01329 cpl_image ** visir_img_recombine_list(const char * recipename,
01330 const cpl_parameterlist * parlist,
01331 cpl_imagelist * nodded,
01332 const cpl_propertylist ** plists,
01333 cpl_geom_combine combine_mode,
01334 cpl_boolean * pdid_resize)
01335 {
01336 cpl_size nnod;
01337 cpl_bivector * offsets_est = NULL;
01338 cpl_bivector * objs = NULL;
01339 cpl_image ** combined = NULL;
01340 cpl_vector * sigmas = NULL;
01341 cpl_propertylist * qclist = cpl_propertylist_new();
01342
01343
01344 bug_if (0);
01345
01346 bug_if (recipename == NULL);
01347 bug_if (parlist == NULL);
01348 bug_if (pdid_resize == NULL);
01349 bug_if (nodded == NULL);
01350
01351 nnod = cpl_imagelist_get_size(nodded);
01352
01353
01354 if (nnod == 1) {
01355 combined = cpl_malloc(2*sizeof(cpl_image*));
01356 combined[1] = NULL;
01357
01358 combined[0] = cpl_imagelist_unset(nodded, 0);
01359 bug_if (combined[0] == NULL);
01360
01361 combined[1] = cpl_image_new(cpl_image_get_size_x(combined[0]),
01362 cpl_image_get_size_y(combined[0]),
01363 CPL_TYPE_INT);
01364 bug_if (combined[1] == NULL);
01365
01366
01367 bug_if(cpl_image_threshold(combined[1], 1.0, 1.0, 1.0, 1.0));
01368
01369 *pdid_resize = CPL_FALSE;
01370
01371 } else {
01372 const double psigmas[] = {5, 2, 1, 0.5};
01373 const char * sval;
01374 const char * offsets;
01375 const char * objects;
01376 int sx, sy, mx, my;
01377 int rej_low, rej_high;
01378 cpl_boolean refine;
01379
01380
01381 refine = visir_parameterlist_get_bool(parlist, recipename,
01382 VISIR_PARAM_REFINE);
01383 skip_if (0);
01384
01385 offsets = visir_parameterlist_get_string(parlist, recipename,
01386 VISIR_PARAM_OFFSETS);
01387 skip_if (0);
01388
01389 objects = visir_parameterlist_get_string(parlist, recipename,
01390 VISIR_PARAM_OBJECTS);
01391 skip_if (0);
01392
01393 sval = visir_parameterlist_get_string(parlist, recipename,
01394 VISIR_PARAM_XCORR);
01395 skip_if (0);
01396
01397 if (sscanf(sval, "%d-%d-%d-%d", &sx, &sy, &mx, &my) != 4)
01398 skip_if (sscanf(sval, "%d %d %d %d", &sx, &sy, &mx, &my) != 4);
01399
01400
01401 sval = visir_parameterlist_get_string(parlist, recipename,
01402 VISIR_PARAM_REJECT);
01403 skip_if (0);
01404
01405 if (sscanf(sval, "%d-%d", &rej_low, &rej_high) !=2 )
01406 skip_if (sscanf(sval, "%d %d", &rej_low, &rej_high) !=2 );
01407
01408
01409 cpl_msg_info(cpl_func, "Get the offsets estimation");
01410 if (!visir_str_par_is_empty(offsets)) {
01411
01412 offsets_est = cpl_bivector_read(offsets);
01413 skip_if (offsets_est==NULL);
01414
01415 error_if (cpl_bivector_get_size(offsets_est) != nnod,
01416 CPL_ERROR_BAD_FILE_FORMAT, "The offsets file %s must "
01417 "have %d entries, not %d", offsets, (int)nnod,
01418 (int)cpl_bivector_get_size(offsets_est));
01419 } else {
01420 double * offsets_est_x;
01421 double * offsets_est_y;
01422 double xoff0, yoff0;
01423
01424
01425 offsets_est = cpl_bivector_new(nnod);
01426 offsets_est_x = cpl_bivector_get_x_data(offsets_est);
01427 offsets_est_y = cpl_bivector_get_y_data(offsets_est);
01428
01429 skip_if (0);
01430
01431 offsets_est_x[0] = 0.0;
01432 offsets_est_y[0] = 0.0;
01433 get_cumoffsets(plists[0], &xoff0, &yoff0);
01434
01435 for (cpl_size i = 1; i < nnod ; i++) {
01436 double xoff, yoff;
01437
01438 skip_if(get_cumoffsets(plists[i], &xoff, &yoff));
01439
01440
01441 offsets_est_x[i] = xoff0 - xoff;
01442 offsets_est_y[i] = yoff0 - yoff;
01443 }
01444 }
01445
01446
01447
01448 if (!visir_str_par_is_empty(objects)) {
01449 objs = cpl_bivector_read(objects);
01450 any_if ("Could not read objects from %s", objects);
01451 }
01452
01453 cpl_msg_info(cpl_func, "Recombining the list of nodded images using "
01454 "mode: %d (I=%d:U=%d:F=%d), rej-lo=%d, rej-hi=%d",
01455 combine_mode, CPL_GEOM_INTERSECT, CPL_GEOM_UNION,
01456 CPL_GEOM_FIRST, rej_low, rej_high);
01457
01458 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
01459 cpl_msg_debug(cpl_func, "The offsets for the recombination:");
01460 cpl_bivector_dump(offsets_est, stdout);
01461 }
01462
01463 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
01464 sigmas = cpl_vector_wrap(4, (double*)psigmas);
01465 IRPLIB_DIAG_PRAGMA_POP;
01466 combined = cpl_geom_img_offset_combine(nodded, offsets_est, refine,
01467 objs, sigmas, NULL, sx, sy,
01468 mx, my, rej_low, rej_high,
01469 combine_mode);
01470 any_if("Could not recombine the images");
01471
01472 *pdid_resize = (cpl_boolean)(cpl_image_get_size_x(combined[0])
01473 != cpl_image_get_size_x(cpl_imagelist_get_const(nodded, 0)) ||
01474 cpl_image_get_size_y(combined[0])
01475 != cpl_image_get_size_y(cpl_imagelist_get_const(nodded, 0)));
01476 }
01477
01478 if (visir_parameterlist_get_int(parlist, recipename, VISIR_PARAM_PLOT) > 0)
01479 visir_image_plot("", "t 'The combined image'", "", combined[0]);
01480
01481 end_skip;
01482
01483 cpl_propertylist_delete(qclist);
01484 cpl_bivector_delete(offsets_est);
01485 cpl_bivector_delete(objs);
01486 cpl_vector_unwrap(sigmas);
01487
01488 return combined;
01489 }
01490
01491
01538
01539 cpl_image ** visir_img_recombine(const char * recipename,
01540 const cpl_parameterlist * parlist,
01541 const irplib_framelist * rawframes,
01542 const char * badpix,
01543 const char * flat,
01544 cpl_geom_combine combine_mode,
01545 cpl_boolean * pdid_resize,
01546 cpl_boolean do_spc_fix,
01547 double wlen,
01548 visir_spc_resol resol)
01549 {
01550 int nfiles;
01551 int * nod_pos = NULL;
01552 cpl_imagelist * nodded = NULL;
01553 cpl_size nnod;
01554 cpl_bivector * objs = NULL;
01555 cpl_propertylist * qclist = cpl_propertylist_new();
01556 const cpl_propertylist ** plists = NULL;
01557 cpl_image ** rec = NULL;
01558
01559
01560 bug_if (0);
01561
01562 bug_if (recipename == NULL);
01563 bug_if (parlist == NULL);
01564 bug_if (rawframes == NULL);
01565 bug_if (pdid_resize == NULL);
01566
01567
01568 nfiles = irplib_framelist_get_size(rawframes);
01569
01570
01571 if (nfiles % 2) {
01572 cpl_msg_warning(cpl_func, "Expecting even number of files, "
01573 "ignoring the last of %d file(s)", nfiles);
01574 error_if (nfiles == 1, CPL_ERROR_DATA_NOT_FOUND,
01575 "At least two files are required");
01576 nfiles--;
01577 }
01578
01579 skip_if ( nfiles <= 0);
01580
01581
01582 nod_pos = cpl_malloc(nfiles * sizeof(int));
01583
01584
01585 cpl_msg_info(cpl_func, "Combining the input frames into the nodded images");
01586 nodded = visir_inputs_combine(recipename, parlist, rawframes, badpix, flat,
01587 nod_pos, do_spc_fix, wlen, resol);
01588 skip_if(nodded == NULL);
01589
01590 nnod = cpl_imagelist_get_size(nodded);
01591 plists = cpl_malloc(nnod * sizeof(cpl_propertylist *));
01592 for (cpl_size i=0; i < nnod ; i++) {
01593 const cpl_size iframe = nod_pos[2*i] == 1 ? 2*i : 2*i+1;
01594
01595 plists[i] = irplib_framelist_get_propertylist_const(rawframes,
01596 iframe);
01597 }
01598
01599 rec = visir_img_recombine_list(recipename, parlist, nodded,
01600 plists, combine_mode, pdid_resize);
01601
01602 end_skip;
01603
01604 cpl_propertylist_delete(qclist);
01605 cpl_free(nod_pos);
01606 cpl_free(plists);
01607 cpl_imagelist_delete(nodded);
01608 cpl_bivector_delete(objs);
01609
01610 return rec;
01611 }
01612
01613
01636
01637 cpl_imagelist * visir_load_hcycle(const irplib_framelist * rawframes, int pos)
01638 {
01639 return visir_load_imagelist(rawframes, pos, CPL_FALSE);
01640 }
01641
01642
01653
01654 cpl_error_code visir_image_reject_hot(cpl_image * self, const char * bpmfile)
01655 {
01656
01657 cpl_image * im_bpm = NULL;
01658 cpl_mask * bpm = NULL;
01659 const int upper = VISIR_HCYCLE_BPM_THRESHOLD;
01660
01661
01662 skip_if (0);
01663
01664 skip_if (self == NULL);
01665
01666 if (bpmfile == NULL) {
01667 bpm = cpl_mask_threshold_image_create(self, upper, DBL_MAX);
01668 skip_if (0);
01669 } else {
01670
01671
01672 cpl_msg_info(cpl_func, "Clean user specified bad pixels");
01673
01674 im_bpm = cpl_image_load(bpmfile, CPL_TYPE_INT, 0, 0);
01675 any_if ("Could not load the bad pixel map %s",
01676 bpmfile ? bpmfile : "<NULL>");
01677
01678 bpm = cpl_mask_threshold_image_create(im_bpm, -0.5, 0.5);
01679 skip_if (0);
01680 cpl_image_delete(im_bpm);
01681 im_bpm = NULL;
01682
01683 skip_if (cpl_mask_not(bpm));
01684 }
01685
01686 skip_if (cpl_image_reject_from_mask(self, bpm));
01687
01688 end_skip;
01689
01690 cpl_image_delete(im_bpm);
01691 cpl_mask_delete(bpm);
01692
01693 return cpl_error_get_code();
01694
01695 }
01696
01697
01698
01705
01706 cpl_imagelist * visir_imagelist_load_last(const irplib_framelist * rawframes)
01707 {
01708 cpl_imagelist * self = NULL;
01709 int naxis3;
01710
01711
01712 skip_if(irplib_framelist_contains(rawframes, VISIR_PFITS_INT_NAXIS3,
01713 CPL_TYPE_INT, CPL_TRUE, 0.0));
01714
01715 naxis3 = visir_pfits_get_naxis3(irplib_framelist_get_propertylist_const(
01716 rawframes,
01717 0));
01718
01719
01720 self = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, naxis3-1,
01721 0);
01722
01723 skip_if (self == NULL);
01724
01725 end_skip;
01726
01727 return self;
01728
01729 }
01730
01731
01732
01742
01743 cpl_imagelist * visir_load_imagelist(const irplib_framelist * rawframes,
01744 int pos, cpl_boolean is_interm)
01745 {
01746 cpl_imagelist * self = NULL;
01747 cpl_image * image = NULL;
01748 const cpl_frame * frame = irplib_framelist_get_const(rawframes, pos);
01749 const cpl_propertylist * plist =
01750 irplib_framelist_get_propertylist_const(rawframes, pos);
01751 const char * file = cpl_frame_get_filename(frame);
01752 const int nchop = plist ? visir_pfits_get_chop_ncycles(plist) : -1;
01753 int naxis3;
01754 visir_data_type data_type;
01755 int plane_step;
01756 int nsize;
01757 int iplane;
01758 int i;
01759
01760 skip_if (plist == NULL);
01761
01762 skip_if(visir_get_data_type(frame, plist, &data_type, NULL));
01763
01764 switch (data_type) {
01765 case VISIR_DATA_AQU_HCYCLE:
01766 case VISIR_DATA_AQU_BURST:
01767 case VISIR_DATA_AQU_BURST_EXT:
01768 error_if(1, CPL_ERROR_UNSUPPORTED_MODE,
01769 "Aquarius data not supported");
01770 default:
01771 naxis3 = visir_pfits_get_naxis3(plist);
01772 break;
01773 }
01774
01775 bug_if (file == NULL);
01776
01777 if (data_type == VISIR_DATA_CUBE1) {
01778
01779 iplane = is_interm ? 0 : nchop;
01780
01781 nsize = is_interm ? nchop : 1;
01782 plane_step = 1;
01783 } else if (naxis3 == 1) {
01784 iplane = 0;
01785 nsize = 1;
01786 plane_step = 1;
01787 } else {
01788
01789 iplane = is_interm ? 1 : 0;
01790 nsize = nchop;
01791 plane_step = 2;
01792 }
01793
01794 self = cpl_imagelist_new();
01795
01796 for (i=0 ; i < nsize; i++, iplane += plane_step) {
01797
01798 image = cpl_image_load(file, CPL_TYPE_FLOAT, iplane, 0);
01799 skip_if (image == NULL);
01800
01801 skip_if (!is_interm && visir_offset_hcycle(image));
01802
01803 skip_if (cpl_imagelist_set(self, image, i));
01804
01805 image = NULL;
01806 }
01807
01808 skip_if (i < nsize);
01809
01810 end_skip;
01811
01812 if (cpl_error_get_code()) {
01813 if (file != NULL) cpl_msg_warning(cpl_func, "Could not load the %s "
01814 "frame(s) from: %s",
01815 is_interm ? "INTERM" : "Half-Cycle",
01816 file);
01817 cpl_image_delete(image);
01818 cpl_imagelist_delete(self);
01819 self = NULL;
01820 }
01821
01822 return self;
01823 }
01824
01825
01828
01852
01853 static cpl_imagelist * visir_load_intermint(const irplib_framelist * rawframes,
01854 int pos)
01855 {
01856 return visir_load_imagelist(rawframes, pos, CPL_TRUE);
01857
01858 }
01859
01860
01869
01870 static cpl_image * visir_load_average(const char * file,
01871 const cpl_propertylist * plist)
01872 {
01873 cpl_errorstate cleanstate = cpl_errorstate_get();
01874 cpl_image * self = NULL;
01875 int nchop, naxis3;
01876
01877
01878 skip_if (0);
01879 skip_if (file == NULL);
01880 skip_if (plist == NULL);
01881
01882 naxis3 = visir_pfits_get_naxis3(plist);
01883 nchop = visir_pfits_get_chop_ncycles(plist);
01884
01885 skip_if (0);
01886
01887 if (nchop == 0 && naxis3 == 1) {
01888 self = cpl_image_load(file, CPL_TYPE_FLOAT, 0, 0);
01889 } else {
01890 const char * sval;
01891
01892
01893 const int plane_offset = (naxis3 == 2 * nchop + 1) ? 2 : 3;
01894
01895
01896 error_if (nchop <= 0, CPL_ERROR_BAD_FILE_FORMAT, "CHOP NCYCLES in %s "
01897 "is non-positive (and NAXIS3=%d): %d", file, naxis3, nchop);
01898
01899 error_if (plane_offset == 3 && naxis3 != nchop+2,
01900 CPL_ERROR_BAD_FILE_FORMAT, "NAXIS3=%d and CHOP NCYCLES=%d "
01901 "in %s is not a valid VISIR INTERM+Half-Cycle format", naxis3,
01902 nchop, file);
01903
01904 if (plane_offset == 3 && nchop > 1)
01905 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
01906 "Cycle frame (old CUBE1-format)", file, nchop);
01907
01908
01909 sval = visir_pfits_get_frame_type(plist);
01910 if (sval == NULL) {
01911
01912 visir_error_reset("Could not get FITS key");
01913
01914 } else if (strlen(sval) == 0) {
01915
01916 } else if (plane_offset == 3) {
01917 if (strcmp(sval, "CUBE2")==0)
01918 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE2, but NAXIS3="
01919 "%d and CHOP NCYCLES=%d imply a CUBE1. Assuming"
01920 " the frame type is really CUBE1", file,
01921 naxis3, nchop);
01922 } else if (nchop > 1) {
01923
01924 if (strcmp(sval, "CUBE1")==0)
01925 cpl_msg_error(cpl_func, "%s has FRAM TYPE = CUBE1, but NAXIS3="
01926 "%d and CHOP NCYCLES=%d imply a CUBE2. Assuming"
01927 "the frame type is really CUBE2", file,
01928 naxis3, nchop);
01929 }
01930
01931
01932 self = cpl_image_load(file, CPL_TYPE_FLOAT, naxis3-plane_offset, 0);
01933
01934 }
01935
01936 skip_if (0);
01937
01938 end_skip;
01939
01940 if (cpl_error_get_code()) {
01941 cpl_msg_warning(cpl_func, "Could not load the last INTERM frame from: "
01942 "%s", file ? file : "<NULL>");
01943 cpl_image_delete(self);
01944 self = NULL;
01945 }
01946
01947 return self;
01948 }
01949
01950
01973
01974 static cpl_error_code visir_imagelist_unpack_interm(cpl_imagelist * self)
01975 {
01976 cpl_image * iprev;
01977 cpl_image * image;
01978 const int n = cpl_imagelist_get_size(self);
01979 int i;
01980
01981 skip_if (0);
01982
01983 if (n == 1) return CPL_ERROR_NONE;
01984
01985 iprev = cpl_imagelist_get(self, n - 1);
01986
01987 skip_if (0);
01988
01989 skip_if (cpl_image_multiply_scalar(iprev, n));
01990
01991
01992 for (i = n-1 ; i > 1 ; i--, iprev = image) {
01993 image = cpl_imagelist_get(self, i-1);
01994
01995 skip_if (0);
01996
01997 skip_if (cpl_image_multiply_scalar(image, i));
01998
01999 skip_if (cpl_image_subtract(iprev, image));
02000
02001 }
02002
02003 image = cpl_imagelist_get(self, 0);
02004
02005 skip_if (0);
02006
02007 skip_if (cpl_image_subtract(iprev, image));
02008
02009 end_skip;
02010
02011 return cpl_error_get_code();
02012 }
02013
02014
02027
02028 static cpl_error_code visir_rem_glitch(cpl_image * glitchy)
02029 {
02030 cpl_image * med_filt = NULL;
02031 cpl_mask * bpm = NULL;
02032 cpl_mask * kernel = cpl_mask_new(3, 3);
02033 double mean, stdev;
02034 double low_thresh, high_thresh;
02035 const int nx = cpl_image_get_size_x(glitchy);
02036 const int ny = cpl_image_get_size_y(glitchy);
02037 int i;
02038
02039
02040 double factor1 = 3.0;
02041 double factor2 = 10.0;
02042 const int niterations = 5;
02043 const double median_corr = 1.5;
02044
02045 bug_if (0);
02046
02047
02048 bug_if(cpl_mask_not(kernel));
02049
02050
02051 med_filt = cpl_image_new(cpl_image_get_size_x(glitchy),
02052 cpl_image_get_size_y(glitchy),
02053 cpl_image_get_type(glitchy));
02054 bug_if(med_filt == NULL);
02055 bug_if(cpl_image_filter_mask(med_filt, glitchy, kernel, CPL_FILTER_MEDIAN,
02056 CPL_BORDER_FILTER));
02057 cpl_mask_delete(kernel);
02058 kernel = NULL;
02059
02060
02061 skip_if (cpl_image_subtract(glitchy, med_filt));
02062
02063
02064 for (i=0 ; i < niterations ; i++) {
02065
02066 mean = cpl_image_get_mean(glitchy);
02067 stdev = cpl_image_get_stdev(glitchy);
02068
02069 skip_if (0);
02070
02071
02072 low_thresh = mean - factor1 * stdev;
02073 high_thresh = mean + factor1 * stdev;
02074
02075
02076 bpm = cpl_mask_threshold_image_create(glitchy,low_thresh,high_thresh);
02077 skip_if (cpl_mask_not(bpm));
02078 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
02079 cpl_mask_delete(bpm);
02080 bpm = NULL;
02081
02082
02083 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
02084 }
02085
02086
02087
02088 mean = cpl_image_get_mean(glitchy);
02089 stdev = cpl_image_get_stdev(glitchy) * median_corr;
02090
02091 skip_if (0);
02092
02093 low_thresh = mean - factor2 * stdev;
02094 high_thresh = mean + factor2 * stdev;
02095
02096 bpm = cpl_mask_threshold_image_create(glitchy, low_thresh, high_thresh);
02097 skip_if (cpl_mask_not(bpm));
02098 skip_if (cpl_image_reject_from_mask(glitchy, bpm));
02099 cpl_mask_delete(bpm);
02100 bpm = NULL;
02101
02102
02103 skip_if (cpl_image_count_rejected(glitchy) == nx*ny);
02104
02105
02106 skip_if (cpl_image_fill_rejected(glitchy, 0.0));
02107 skip_if (cpl_image_accept_all(glitchy));
02108
02109
02110 skip_if (cpl_image_add(glitchy, med_filt));
02111
02112 end_skip;
02113
02114 cpl_image_delete(med_filt);
02115 cpl_mask_delete(bpm);
02116 cpl_mask_delete(kernel);
02117
02118 return cpl_error_get_code();
02119 }
02120
02121
02132
02133 static cpl_error_code visir_rem_bad_images(cpl_imagelist * in)
02134 {
02135 cpl_vector * medians = NULL;
02136 cpl_vector * stdevs = NULL;
02137 cpl_vector * selection = NULL;
02138 double mean_medians, mean_stdevs, stdev_medians, stdev_stdevs;
02139 const double threshold = 3;
02140 const int nima = cpl_imagelist_get_size(in);
02141 int i;
02142
02143
02144 skip_if (0);
02145
02146 if (nima <= 3) return CPL_ERROR_NONE;
02147
02148
02149 medians = cpl_vector_new(nima);
02150 stdevs = cpl_vector_new(nima);
02151
02152
02153 for (i=0 ; i < nima ; i++) {
02154 cpl_stats * stats = cpl_stats_new_from_image(cpl_imagelist_get(in, i),
02155 CPL_STATS_STDEV | CPL_STATS_MEDIAN);
02156
02157 cpl_vector_set(medians, i, cpl_stats_get_median(stats));
02158 cpl_vector_set(stdevs, i, cpl_stats_get_stdev(stats));
02159 cpl_stats_delete(stats);
02160 }
02161
02162 skip_if( 0);
02163
02164
02165 mean_medians = cpl_vector_get_mean(medians);
02166 stdev_medians = cpl_vector_get_stdev(medians);
02167 mean_stdevs = cpl_vector_get_mean(stdevs);
02168 stdev_stdevs = cpl_vector_get_stdev(stdevs);
02169
02170 skip_if (cpl_vector_subtract_scalar(medians, mean_medians));
02171 skip_if (cpl_vector_subtract_scalar(stdevs, mean_stdevs));
02172
02173 stdev_medians *= threshold;
02174 stdev_stdevs *= threshold;
02175
02176
02177 selection = cpl_vector_new(nima);
02178 skip_if( cpl_vector_fill(selection, 0));
02179 for (i=0 ; i < nima ; i++) {
02180 if (fabs(cpl_vector_get(medians, i)) <= stdev_medians &&
02181 fabs(cpl_vector_get(stdevs, i)) <= stdev_stdevs) continue;
02182
02183 cpl_vector_set(selection, i, -1);
02184 cpl_msg_info(cpl_func, "Image %d of %d rejected: median=%g, stdev=%g",
02185 i+1, nima, stdev_medians, stdev_stdevs);
02186 }
02187
02188
02189 cpl_imagelist_erase(in, selection);
02190
02191 end_skip;
02192
02193 cpl_vector_delete(medians);
02194 cpl_vector_delete(stdevs);
02195
02196 cpl_vector_delete(selection);
02197
02198 return CPL_ERROR_NONE;
02199 }
02200
02201
02210
02211 static cpl_error_code visir_offset_hcycle(cpl_image * hcycle)
02212 {
02213 double minval;
02214
02215 skip_if (0);
02216
02217 skip_if (cpl_image_add_scalar(hcycle, VISIR_HCYCLE_OFFSET));
02218
02219 minval = cpl_image_get_min(hcycle);
02220
02221
02222 if (minval < 1) cpl_msg_warning(cpl_func, "HCycle pixel minval: %g", minval);
02223
02224 end_skip;
02225
02226 return CPL_ERROR_NONE;
02227 }
02228
02229
02241
02242 static
02243 cpl_image ** visir_img_collapse_beam_four(cpl_propertylist * qclist,
02244 const cpl_image * self,
02245 const cpl_image * inverse,
02246 double eccmax,
02247 double pthrow,
02248 double angle,
02249 const cpl_propertylist * plist)
02250 {
02251
02252 cpl_image ** combined = NULL;
02253 const int nx = cpl_image_get_size_x(self);
02254 const int ny = cpl_image_get_size_y(self);
02255 const cpl_type type = cpl_image_get_type(self);
02256 cpl_imagelist * list4 = cpl_imagelist_new();
02257 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
02258 cpl_image * swrap = type == CPL_TYPE_DOUBLE
02259 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)self))
02260 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)self));
02261 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02262 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02263 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02264 IRPLIB_DIAG_PRAGMA_POP;
02265 cpl_bivector * offs = cpl_bivector_new(4);
02266 double * x4 = cpl_bivector_get_x_data(offs);
02267 double * y4 = cpl_bivector_get_y_data(offs);
02268 double pos_x, pos_y;
02269
02270 skip_if (0);
02271
02272 skip_if(plist == NULL);
02273
02274 skip_if(visir_img_find_beam_four(qclist, self, inverse, eccmax, pthrow,
02275 angle, x4, y4));
02276
02277
02278 for (int i = 1; i < 4; i++) {
02279 x4[i] = x4[0] - x4[i];
02280 y4[i] = y4[0] - y4[i];
02281 }
02282
02283 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02284 x4[0]));
02285 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02286 y4[0]));
02287 x4[0] = y4[0] = 0.0;
02288
02289 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
02290 bug_if(cpl_imagelist_set(list4, (cpl_image*)self, 0));
02291 bug_if(cpl_imagelist_set(list4, swrap, 1));
02292 bug_if(cpl_imagelist_set(list4, (cpl_image*)inverse, 2));
02293 bug_if(cpl_imagelist_set(list4, iwrap, 3));
02294 IRPLIB_DIAG_PRAGMA_POP;
02295
02296 combined = cpl_geom_img_offset_saa(list4, offs, CPL_KERNEL_DEFAULT, 0, 0,
02297 CPL_GEOM_FIRST, &pos_x, &pos_y);
02298
02299 skip_if(combined == NULL);
02300
02301 end_skip;
02302
02303 cpl_bivector_delete(offs);
02304 visir_imagelist_unwrap(list4);
02305 (void)cpl_image_unwrap(swrap);
02306 (void)cpl_image_unwrap(iwrap);
02307 if (cpl_error_get_code() && combined != NULL) {
02308 cpl_image_delete(combined[0]);
02309 cpl_image_delete(combined[1]);
02310 cpl_free(combined);
02311 }
02312
02313 return combined;
02314 }
02315
02316
02330
02331 visir_chopnod_mode visir_img_find_beam(cpl_propertylist * qclist,
02332 const cpl_image * self,
02333 const cpl_image * inverse,
02334 const cpl_propertylist * plist,
02335 const cpl_parameterlist * parlist,
02336 const char * recipename,
02337 double x4[],
02338 double y4[])
02339 {
02340
02341 cpl_errorstate cleanstate = cpl_errorstate_get();
02342 visir_chopnod_mode mode = VISIR_CHOPNOD_AUTO;
02343
02344 const double eccmax = visir_parameterlist_get_double(parlist, recipename,
02345 VISIR_PARAM_ECCMAX);
02346
02347 const char * sdir;
02348
02349
02350 const double pscale = visir_pfits_get_pixscale(plist);
02351 const double pthrow = pscale > 0.0
02352 ? visir_pfits_get_chop_throw(plist) / pscale : 0.0;
02353 double angle = visir_pfits_get_chop_posang(plist);
02354
02355 skip_if(x4 == NULL);
02356 skip_if(y4 == NULL);
02357 skip_if(self == NULL);
02358 skip_if(inverse == NULL);
02359 skip_if(parlist == NULL);
02360 skip_if(recipename == NULL);
02361 skip_if(qclist == NULL);
02362
02363 sdir = visir_pfits_get_chopnod_dir(plist);
02364
02365 if (sdir != NULL && !strcmp(sdir, "PERPENDICULAR")) {
02366
02367
02368 mode = VISIR_CHOPNOD_PERPENDICULAR;
02369
02370 skip_if (visir_img_find_beam_four(qclist, self, inverse, eccmax,
02371 pthrow, angle, x4, y4));
02372
02373 } else if (sdir != NULL && !strcmp(sdir, "PARALLEL")) {
02374
02375
02376 mode = VISIR_CHOPNOD_PARALLEL;
02377
02378 skip_if (visir_img_find_beam_three(qclist, self, inverse, eccmax,
02379 pthrow, angle, x4, y4));
02380
02381 } else {
02382 if (sdir == NULL) {
02383 visir_error_reset("Could not get FITS key");
02384 } else {
02385 cpl_msg_warning(cpl_func, "Unknown chopping direction: %s",
02386 sdir);
02387 }
02388 cpl_msg_warning(cpl_func, "Proceeding as if FITS card "
02389 VISIR_PFITS_STRING_CHOPNOD_DIR " had value: %s",
02390 "PERPENDICULAR");
02391
02392 if (visir_img_find_beam_four(qclist, self, inverse, eccmax,
02393 pthrow, angle, x4, y4)) {
02394
02395 visir_error_reset("Proceeding as if FITS card "
02396 VISIR_PFITS_STRING_CHOPNOD_DIR
02397 " had value: %s", "PARALLEL");
02398
02399 skip_if (visir_img_find_beam_three(qclist, self, inverse,
02400 eccmax, pthrow, angle,
02401 x4, y4));
02402
02403
02404 mode = VISIR_CHOPNOD_PARALLEL;
02405
02406 } else {
02407
02408 mode = VISIR_CHOPNOD_PERPENDICULAR;
02409 }
02410 }
02411
02412 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM THROW",
02413 pthrow));
02414 bug_if (cpl_propertylist_set_comment(qclist, "ESO QC ONEBEAM THROW",
02415 "The throw in pixels (TEL CHOP THROW "
02416 "divided by INS PFOV)"));
02417 end_skip;
02418
02419 return mode;
02420 }
02421
02422
02423
02436
02437 static
02438 cpl_error_code visir_img_find_beam_four(cpl_propertylist * qclist,
02439 const cpl_image * self,
02440 const cpl_image * inverse,
02441 double eccmax,
02442 double pthrow,
02443 double angle,
02444 double x4[],
02445 double y4[])
02446 {
02447
02448 cpl_errorstate cleanstate = cpl_errorstate_get();
02449 cpl_apertures * appos = NULL;
02450 cpl_apertures * apneg = NULL;
02451 const double psigmas[] = {2.0, 1.0, 0.5};
02452 const int nsigmas = sizeof(psigmas)/sizeof(double);
02453 int isigma;
02454 int iappos2[] = {1, 2};
02455 int iapneg2[] = {1, 2};
02456
02457 bug_if(0);
02458 skip_if(self == NULL);
02459 skip_if(qclist == NULL);
02460 skip_if(pthrow <= 0.0);
02461 skip_if(x4 == NULL);
02462 skip_if(y4 == NULL);
02463
02464 cpl_msg_info(cpl_func, "Detecting the 4-beam object with %g pixel throw "
02465 "using %d sigma-levels ranging from %g down to %g", pthrow,
02466 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02467
02468 bug_if(0);
02469 for (isigma = 0; isigma < nsigmas; isigma++) {
02470 int npos = 0;
02471 int nneg = 0;
02472
02473
02474 cpl_apertures_delete(appos);
02475 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02476
02477 if (appos != NULL) {
02478 npos = cpl_apertures_get_size(appos);
02479 }
02480
02481
02482
02483 cpl_apertures_delete(apneg);
02484 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02485 if (apneg != NULL) {
02486 nneg = cpl_apertures_get_size(apneg);
02487 }
02488
02489 cpl_msg_info(cpl_func, "Found %d positive (need 2) and %d negative "
02490 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02491 psigmas[isigma], 1+isigma, nsigmas);
02492
02493
02494 error_if(npos * nneg > FIND_BEAM_MAX_APERTURES_SQR,
02495 CPL_ERROR_DATA_NOT_FOUND, "Too many objects found, aborting");
02496
02497 if (eccmax > 0.0) {
02498 int ipos1;
02499 double eccbest = eccmax;
02500 double eccmin = DBL_MAX;
02501 double fluxbest = 0.0;
02502 double fluxecc = DBL_MAX;
02503 cpl_boolean is_first = CPL_TRUE;
02504
02505 #ifdef _OPENMP
02506 #pragma omp parallel for private(ipos1)
02507 #endif
02508 for (ipos1 = 2; ipos1 < 1 + npos; ipos1++) {
02509 int ipos2, ineg1, ineg2;
02510 for (ipos2 = 1; ipos2 < ipos1; ipos2++) {
02511 for (ineg1 = 2; ineg1 < 1 + nneg; ineg1++) {
02512 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02513 cpl_boolean swappos, swapneg;
02514 const double ecc
02515 = visir_img_check_box(appos, ipos1, ipos2,
02516 apneg, ineg1, ineg2,
02517 pthrow, angle, &swappos,
02518 &swapneg);
02519
02520 const double flux
02521 = cpl_apertures_get_flux(appos, ipos1)
02522 + cpl_apertures_get_flux(appos, ipos2)
02523 + cpl_apertures_get_flux(apneg, ineg1)
02524 + cpl_apertures_get_flux(apneg, ineg2);
02525
02526
02527 if (ecc < 0.0 || flux <= 0.0 ||
02528 !cpl_errorstate_is_equal(cleanstate)) {
02529 irplib_error_recover(cleanstate, "Invalid 4-"
02530 "object (%d & %d of %d, "
02531 "%d & %d of %d)",
02532 ipos2, ipos1, npos,
02533 ineg2, ineg1, nneg);
02534 continue;
02535 }
02536
02537 #ifdef _OPENMP
02538 #pragma omp critical(visir_img_find_beam_four_min)
02539 #endif
02540 if (ecc < eccmin)
02541 {
02542 eccmin = ecc;
02543 fluxecc = flux;
02544 }
02545
02546 if (eccmax <= ecc) continue;
02547
02548 #ifdef _OPENMP
02549 #pragma omp critical(visir_img_find_beam_four_ok)
02550 #endif
02551 if (is_first || ecc * fluxbest < eccbest * flux)
02552 {
02553 if (is_first) {
02554 is_first = CPL_FALSE;
02555 cpl_msg_info(cpl_func, "Found 4 object "
02556 "positions with throw-"
02557 "scaled eccentricity %g "
02558 "and flux %g", ecc, flux);
02559 } else {
02560 cpl_msg_info(cpl_func, "Found 4 object "
02561 "positions with throw-"
02562 "scaled eccentricity %g "
02563 "< %g and/or flux %g > %g",
02564 ecc, eccbest, flux, fluxbest);
02565 }
02566 eccbest = ecc;
02567 fluxbest = flux;
02568 iappos2[0] = swappos ? ipos2 : ipos1;
02569 iappos2[1] = swappos ? ipos1 : ipos2;
02570 iapneg2[0] = swapneg ? ineg2 : ineg1;
02571 iapneg2[1] = swapneg ? ineg1 : ineg2;
02572 }
02573 }
02574 }
02575 }
02576 }
02577 if (eccbest < eccmax) {
02578 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02579 "ECCENTRICITY", eccbest));
02580
02581 break;
02582 }
02583 if (eccmin < DBL_MAX) {
02584 cpl_msg_info(cpl_func, "Found 4 sigma-%g object positions with "
02585 "too large throw-scaled eccentricity %g >= %g and "
02586 "flux %g", psigmas[isigma], eccmin, eccmax,
02587 fluxecc);
02588 }
02589 } else if (npos >= 2 && nneg >= 2) {
02590 cpl_apertures_sort_by_flux(appos);
02591 cpl_apertures_sort_by_flux(apneg);
02592 break;
02593 }
02594
02595 if (isigma + 1 < nsigmas) {
02596 irplib_error_recover(cleanstate, "4-Beam positions not found among "
02597 "%d postive and %d negative object(s) at "
02598 "sigma=%g, (%d of %d)", npos, nneg,
02599 psigmas[isigma], 1+isigma, nsigmas);
02600 }
02601 }
02602
02603 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02604 "4-Beam positions not found w. %d sigma(s) down to %g",
02605 nsigmas, psigmas[nsigmas - 1]);
02606
02607 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02608 cpl_apertures_dump(appos, stdout);
02609 cpl_apertures_dump(apneg, stdout);
02610 }
02611
02612 x4[0] = cpl_apertures_get_centroid_x(appos, iappos2[0]);
02613 y4[0] = cpl_apertures_get_centroid_y(appos, iappos2[0]);
02614 x4[1] = cpl_apertures_get_centroid_x(appos, iappos2[1]);
02615 y4[1] = cpl_apertures_get_centroid_y(appos, iappos2[1]);
02616
02617 x4[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02618 y4[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02619 x4[3] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02620 y4[3] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02621
02622 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
02623 cpl_apertures_get_flux(appos,
02624 iappos2[0])));
02625
02626 cpl_msg_info(cpl_func, "Centroid of positive object 1 [pixel]: %g %g",
02627 x4[0], y4[0]);
02628 cpl_msg_info(cpl_func, "Centroid of positive object 2 [pixel]: %g %g",
02629 x4[1], y4[1]);
02630
02631 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02632 x4[2], y4[2]);
02633 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02634 x4[3], y4[3]);
02635
02636 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02637 pthrow);
02638 cpl_msg_info(cpl_func, "Object Pos -> Pos x/y-distance [pixel]: %g %g",
02639 x4[1] - x4[0], y4[1] - y4[0]);
02640 cpl_msg_info(cpl_func, "Object Neg -> Neg x/y-distance [pixel]: %g %g",
02641 x4[3] - x4[2], y4[3] - y4[2]);
02642 cpl_msg_info(cpl_func, "Object Pos -> Pos angle [degrees]: %g",
02643 atan2(y4[1] - y4[0], x4[1] - x4[0]) * CPL_MATH_DEG_RAD);
02644 cpl_msg_info(cpl_func, "Object Neg -> Neg angle [degrees]: %g",
02645 atan2(y4[3] - y4[2], x4[3] - x4[2]) * CPL_MATH_DEG_RAD);
02646
02647 end_skip;
02648
02649 cpl_apertures_delete(appos);
02650 cpl_apertures_delete(apneg);
02651
02652 return cpl_error_get_code();
02653 }
02654
02655
02667
02668 static
02669 cpl_image ** visir_img_collapse_beam_three(cpl_propertylist * qclist,
02670 const cpl_image * self,
02671 const cpl_image * inverse,
02672 double eccmax,
02673 double pthrow,
02674 const cpl_propertylist * plist)
02675 {
02676
02677 cpl_image ** combined = NULL;
02678 const int nx = cpl_image_get_size_x(self);
02679 const int ny = cpl_image_get_size_y(self);
02680 const cpl_type type = cpl_image_get_type(self);
02681 cpl_imagelist * list3 = cpl_imagelist_new();
02682 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
02683 cpl_image * iwrap = type == CPL_TYPE_DOUBLE
02684 ? cpl_image_wrap_double(nx, ny, cpl_image_get_data((cpl_image*)inverse))
02685 : cpl_image_wrap_float(nx, ny, cpl_image_get_data((cpl_image*)inverse));
02686 IRPLIB_DIAG_PRAGMA_POP;
02687 cpl_bivector * offs = cpl_bivector_new(3);
02688 double * x3 = cpl_bivector_get_x_data(offs);
02689 double * y3 = cpl_bivector_get_y_data(offs);
02690 double pos_x, pos_y;
02691 double angle = visir_pfits_get_chop_posang(plist);
02692
02693 skip_if (0);
02694
02695 skip_if(plist == NULL);
02696
02697 skip_if(visir_img_find_beam_three(qclist, self, inverse, eccmax, pthrow,
02698 angle, x3, y3));
02699
02700
02701 for (int i = 1; i < 3; i++) {
02702 x3[i] = x3[0] - x3[i];
02703 y3[i] = y3[0] - y3[i];
02704 }
02705 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM XPOS",
02706 x3[0]));
02707 bug_if (cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM YPOS",
02708 y3[0]));
02709
02710 x3[0] = y3[0] = 0.0;
02711
02712 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
02713 bug_if(cpl_imagelist_set(list3, (cpl_image*)self, 0));
02714 bug_if(cpl_imagelist_set(list3, (cpl_image*)inverse, 1));
02715 bug_if(cpl_imagelist_set(list3, iwrap, 2));
02716 IRPLIB_DIAG_PRAGMA_POP;
02717
02718 combined = cpl_geom_img_offset_saa(list3, offs, CPL_KERNEL_DEFAULT, 0, 0,
02719 CPL_GEOM_FIRST, &pos_x, &pos_y);
02720
02721 skip_if(combined == NULL);
02722
02723 end_skip;
02724
02725 cpl_bivector_delete(offs);
02726 visir_imagelist_unwrap(list3);
02727 (void)cpl_image_unwrap(iwrap);
02728 if (cpl_error_get_code() && combined != NULL) {
02729 cpl_image_delete(combined[0]);
02730 cpl_image_delete(combined[1]);
02731 cpl_free(combined);
02732 }
02733
02734 return combined;
02735 }
02736
02737
02738
02752
02753 static
02754 cpl_error_code visir_img_find_beam_three(cpl_propertylist * qclist,
02755 const cpl_image * self,
02756 const cpl_image * inverse,
02757 double eccmax,
02758 double pthrow,
02759 double angle,
02760 double x3[],
02761 double y3[])
02762 {
02763
02764 cpl_errorstate cleanstate = cpl_errorstate_get();
02765 cpl_apertures * appos = NULL;
02766 cpl_apertures * apneg = NULL;
02767 const double psigmas[] = {2.0, 1.0, 0.5};
02768 const int nsigmas = sizeof(psigmas)/sizeof(double);
02769 int isigma;
02770 int iappos [] = {1};
02771 int iapneg2[] = {1, 2};
02772
02773 bug_if(0);
02774 skip_if(self == NULL);
02775 skip_if(qclist == NULL);
02776 skip_if(pthrow <= 0.0);
02777 skip_if(eccmax < 0.0);
02778 skip_if(x3 == NULL);
02779 skip_if(y3 == NULL);
02780
02781
02782 cpl_msg_info(cpl_func, "Detecting the 3-beam object with %g pixel throw "
02783 "using %d sigma-levels ranging from %g down to %g", pthrow,
02784 nsigmas, psigmas[0], psigmas[nsigmas-1]);
02785
02786 bug_if(0);
02787 for (isigma = 0; isigma < nsigmas; isigma++) {
02788 int npos = 0;
02789 int nneg = 0;
02790
02791
02792 cpl_apertures_delete(appos);
02793 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
02794
02795 if (appos != NULL) {
02796 npos = cpl_apertures_get_size(appos);
02797 }
02798
02799
02800
02801 cpl_apertures_delete(apneg);
02802 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
02803 if (apneg != NULL) {
02804 nneg = cpl_apertures_get_size(apneg);
02805 }
02806
02807 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
02808 "(need 2) object(s) at sigma=%g (%d of %d)", npos, nneg,
02809 psigmas[isigma], 1+isigma, nsigmas);
02810
02811
02812 error_if(npos * nneg > FIND_BEAM_MAX_APERTURES_SQR,
02813 CPL_ERROR_DATA_NOT_FOUND, "Too many objects found, aborting");
02814
02815 if (eccmax > 0.0) {
02816 int ipos;
02817 double eccbest = eccmax;
02818 double eccmin = DBL_MAX;
02819 double fluxbest = 0.0;
02820 double fluxecc = DBL_MAX;
02821 cpl_boolean is_first = CPL_TRUE;
02822
02823 #ifdef _OPENMP
02824 #pragma omp parallel for private(ipos)
02825 #endif
02826 for (ipos = 1; ipos < 1 + npos; ipos++) {
02827 int ineg1, ineg2;
02828 for (ineg1 = 2; ineg1 < 1 + nneg; ineg1++) {
02829 for (ineg2 = 1; ineg2 < ineg1; ineg2++) {
02830 cpl_boolean swapneg;
02831
02832 const double ecc
02833 = visir_img_check_align(appos, ipos, apneg, ineg1,
02834 ineg2, pthrow, angle,
02835 &swapneg);
02836
02837 const double flux
02838 = cpl_apertures_get_flux(appos, ipos)
02839 + cpl_apertures_get_flux(apneg, ineg1)
02840 + cpl_apertures_get_flux(apneg, ineg2);
02841
02842
02843 if (ecc < 0.0 || flux <= 0.0 ||
02844 !cpl_errorstate_is_equal(cleanstate)) {
02845 irplib_error_recover(cleanstate, "Invalid 3-"
02846 "object (%d of %d, "
02847 "%d & %d of %d)",
02848 ipos, npos,
02849 ineg2, ineg1, nneg);
02850 continue;
02851 }
02852
02853 #ifdef _OPENMP
02854 #pragma omp critical(visir_img_collapse_beam_three_min)
02855 #endif
02856 if (ecc < eccmin)
02857 {
02858 eccmin = ecc;
02859 fluxecc = flux;
02860 }
02861
02862 if (eccmax <= ecc) continue;
02863
02864 #ifdef _OPENMP
02865 #pragma omp critical(visir_img_collapse_beam_three_ok)
02866 #endif
02867 if (is_first || ecc * fluxbest < eccbest * flux)
02868 {
02869 if (is_first) {
02870 is_first = CPL_FALSE;
02871 cpl_msg_info(cpl_func, "Found 3 object posi"
02872 "tions with throw-scaled "
02873 "eccentricity %g and flux %g",
02874 ecc, flux);
02875 } else {
02876 cpl_msg_info(cpl_func, "Found 3 object posi"
02877 "tions with throw-scaled "
02878 "eccentricity %g < %g and/or "
02879 "flux %g > %g", ecc, eccbest,
02880 flux, fluxbest);
02881 }
02882 eccbest = ecc;
02883 fluxbest = flux;
02884 iappos[0] = ipos;
02885 iapneg2[0] = swapneg ? ineg2 : ineg1;
02886 iapneg2[1] = swapneg ? ineg1 : ineg2;
02887 }
02888 }
02889 }
02890 }
02891 if (eccbest < eccmax) {
02892 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
02893 "ECCENTRICITY", eccbest));
02894 break;
02895 }
02896 if (eccmin < DBL_MAX) {
02897 cpl_msg_info(cpl_func, "Found 3 sigma-%g object positions with "
02898 "too large throw-scaled eccentricity %g >= %g and "
02899 "flux %g", psigmas[isigma], eccmin, eccmax,
02900 fluxecc);
02901 }
02902 } else if (npos >= 1 && nneg >= 2) {
02903 cpl_apertures_sort_by_flux(appos);
02904 cpl_apertures_sort_by_flux(apneg);
02905 break;
02906 }
02907
02908 if (isigma + 1 < nsigmas) {
02909 irplib_error_recover(cleanstate, "3-Beam positions not found among "
02910 "%d postive and %d negative object(s) at "
02911 "sigma=%g, (%d of %d)", npos, nneg,
02912 psigmas[isigma], 1+isigma, nsigmas);
02913 }
02914 }
02915
02916 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
02917 "3-Beam positions not found w. %d sigma(s) down to %g",
02918 nsigmas, psigmas[nsigmas - 1]);
02919
02920 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
02921 cpl_apertures_dump(appos, stdout);
02922 cpl_apertures_dump(apneg, stdout);
02923 }
02924
02925 x3[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
02926 y3[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
02927
02928 x3[1] = cpl_apertures_get_centroid_x(apneg, iapneg2[0]);
02929 y3[1] = cpl_apertures_get_centroid_y(apneg, iapneg2[0]);
02930 x3[2] = cpl_apertures_get_centroid_x(apneg, iapneg2[1]);
02931 y3[2] = cpl_apertures_get_centroid_y(apneg, iapneg2[1]);
02932
02933 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
02934 cpl_apertures_get_flux(appos,
02935 iappos[0])));
02936
02937 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
02938 x3[0], y3[0]);
02939
02940 cpl_msg_info(cpl_func, "Centroid of negative object 1 [pixel]: %g %g",
02941 x3[1], y3[1]);
02942 cpl_msg_info(cpl_func, "Centroid of negative object 2 [pixel]: %g %g",
02943 x3[2], y3[2]);
02944
02945 cpl_msg_info(cpl_func, "Expected object distance (chop throw) [pixel]: %g",
02946 pthrow);
02947 cpl_msg_info(cpl_func, "Object Neg1 -> Pos x/y-distance [pixel]: %g %g",
02948 x3[2] - x3[0], y3[2] - y3[0]);
02949 cpl_msg_info(cpl_func, "Object Pos -> Neg2 x/y-distance [pixel]: %g %g",
02950 x3[0] - x3[1], y3[0] - y3[1]);
02951
02952 end_skip;
02953
02954 cpl_apertures_delete(appos);
02955 cpl_apertures_delete(apneg);
02956
02957 return cpl_error_get_code();
02958 }
02959
02960
02961
02976
02977 cpl_error_code visir_img_find_beam_two(cpl_propertylist * qclist,
02978 const cpl_image * self,
02979 const cpl_image * inverse,
02980 double eccmax,
02981 double pthrow,
02982 double angle,
02983 double x2[],
02984 double y2[])
02985 {
02986
02987 cpl_errorstate cleanstate = cpl_errorstate_get();
02988 cpl_apertures * appos = NULL;
02989 cpl_apertures * apneg = NULL;
02990 const double psigmas[] = {2.0, 1.0, 0.5};
02991 const int nsigmas = sizeof(psigmas)/sizeof(double);
02992 int isigma;
02993 int iappos[] = {1};
02994 int iapneg[] = {1};
02995
02996 bug_if(0);
02997 skip_if(self == NULL);
02998 skip_if(qclist == NULL);
02999 skip_if(eccmax < 0.0);
03000 skip_if(x2 == NULL);
03001 skip_if(y2 == NULL);
03002
03003 if (pthrow > 0.0) {
03004 cpl_msg_info(cpl_func, "Detecting the 2-beam object (Pos -> Neg) with "
03005 "%g pixel throw using %d sigma-levels ranging from %g down"
03006 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
03007 } else if (pthrow < 0.0) {
03008 cpl_msg_info(cpl_func, "Detecting the 2-beam object (Neg -> Pos) with "
03009 "%g pixel throw using %d sigma-levels ranging from %g down"
03010 " to %g", pthrow, nsigmas, psigmas[0], psigmas[nsigmas-1]);
03011 } else {
03012 skip_if(1);
03013 }
03014
03015 bug_if(0);
03016 for (isigma = 0; isigma < nsigmas; isigma++) {
03017 int npos = 0;
03018 int nneg = 0;
03019
03020
03021 cpl_apertures_delete(appos);
03022 appos = cpl_apertures_extract_sigma(self, psigmas[isigma]);
03023
03024 if (appos != NULL) {
03025 npos = cpl_apertures_get_size(appos);
03026 }
03027
03028
03029
03030 cpl_apertures_delete(apneg);
03031 apneg = cpl_apertures_extract_sigma(inverse, psigmas[isigma]);
03032 if (apneg != NULL) {
03033 nneg = cpl_apertures_get_size(apneg);
03034 }
03035
03036 cpl_msg_info(cpl_func, "Found %d positive (need 1) and %d negative "
03037 "(need 1) object(s) at sigma=%g (%d of %d)", npos, nneg,
03038 psigmas[isigma], 1+isigma, nsigmas);
03039
03040 if (eccmax > 0.0) {
03041 int ipos;
03042 double eccbest = eccmax;
03043 double eccmin = DBL_MAX;
03044 double fluxbest = 0.0;
03045 double fluxecc = DBL_MAX;
03046 cpl_boolean is_first = CPL_TRUE;
03047
03048 #ifdef _OPENMP
03049 #pragma omp parallel for private(ipos)
03050 #endif
03051 for (ipos = 1; ipos < 1 + npos; ipos++) {
03052 int ineg;
03053 for (ineg = 1; ineg < 1 + nneg; ineg++) {
03054 const double ecc =
03055 visir_img_check_line(appos, ipos, apneg, ineg,
03056 pthrow, angle);
03057
03058 const double flux
03059 = cpl_apertures_get_flux(appos, ipos)
03060 + cpl_apertures_get_flux(apneg, ineg);
03061
03062
03063 if (ecc < 0.0 || flux <= 0.0 ||
03064 !cpl_errorstate_is_equal(cleanstate)) {
03065 irplib_error_recover(cleanstate, "Invalid 2-"
03066 "object (%d of %d, "
03067 "%d of %d)",
03068 ipos, npos,
03069 ineg, nneg);
03070 continue;
03071 }
03072
03073 #ifdef _OPENMP
03074 #pragma omp critical(visir_img_collapse_beam_two_min)
03075 #endif
03076 if (ecc < eccmin)
03077 {
03078 eccmin = ecc;
03079 fluxecc = flux;
03080 }
03081
03082 if (eccmax <= ecc) continue;
03083
03084 #ifdef _OPENMP
03085 #pragma omp critical(visir_img_collapse_beam_two_ok)
03086 #endif
03087 if (is_first || ecc * fluxbest < eccbest * flux)
03088 {
03089 if (is_first) {
03090 is_first = CPL_FALSE;
03091 cpl_msg_info(cpl_func, "Found 2 object posi"
03092 "tions with throw-scaled eccen"
03093 "tricity %g and flux %g", ecc,
03094 flux);
03095 } else {
03096 cpl_msg_info(cpl_func, "Found 2 object posi"
03097 "tions with throw-scaled eccen"
03098 "tricity %g < %g and/or flux %g "
03099 "> %g", ecc, eccbest, flux,
03100 fluxbest);
03101 }
03102 eccbest = ecc;
03103 fluxbest = flux;
03104 iappos[0] = ipos;
03105 iapneg[0] = ineg;
03106 }
03107 }
03108 }
03109 if (eccbest < eccmax) {
03110 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM "
03111 "ECCENTRICITY", eccbest));
03112 break;
03113 }
03114 if (eccmin < DBL_MAX) {
03115 cpl_msg_info(cpl_func, "Found 2 sigma-%g object positions with "
03116 "too large throw-scaled eccentricity %g >= %g and "
03117 "flux %g", psigmas[isigma], eccmin, eccmax,
03118 fluxecc);
03119 }
03120 } else if (npos >= 1 && nneg >= 2) {
03121 cpl_apertures_sort_by_flux(appos);
03122 cpl_apertures_sort_by_flux(apneg);
03123 break;
03124 }
03125
03126 if (isigma + 1 < nsigmas) {
03127 irplib_error_recover(cleanstate, "2-Beam positions not found among "
03128 "%d postive and %d negative object(s) at "
03129 "sigma=%g, (%d of %d)", npos, nneg,
03130 psigmas[isigma], 1+isigma, nsigmas);
03131 }
03132 }
03133
03134 error_if (isigma == nsigmas, CPL_ERROR_DATA_NOT_FOUND,
03135 "2-Beam positions not found w. %d sigma(s) down to %g",
03136 nsigmas, psigmas[nsigmas - 1]);
03137
03138 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
03139 cpl_apertures_dump(appos, stdout);
03140 cpl_apertures_dump(apneg, stdout);
03141 }
03142
03143 x2[0] = cpl_apertures_get_centroid_x(appos, iappos[0]);
03144 y2[0] = cpl_apertures_get_centroid_y(appos, iappos[0]);
03145
03146 x2[1] = cpl_apertures_get_centroid_x(apneg, iapneg[0]);
03147 y2[1] = cpl_apertures_get_centroid_y(apneg, iapneg[0]);
03148
03149 bug_if(cpl_propertylist_append_double(qclist, "ESO QC ONEBEAM FLUX",
03150 cpl_apertures_get_flux(appos,
03151 iappos[0])));
03152
03153 cpl_msg_info(cpl_func, "Centroid of positive object [pixel]: %g %g",
03154 x2[0], y2[0]);
03155
03156 cpl_msg_info(cpl_func, "Centroid of negative object [pixel]: %g %g",
03157 x2[1], y2[1]);
03158
03159 if (pthrow > 0.0) {
03160 cpl_msg_info(cpl_func, "Expected object distance (chop throw) "
03161 "[pixel]: %g", pthrow);
03162
03163 cpl_msg_info(cpl_func, "Object Pos -> Neg x/y-distance [pixel]: %g %g",
03164 x2[1] - x2[0], y2[1] - y2[0]);
03165 } else {
03166 cpl_msg_info(cpl_func, "Expected object distance (chop throw) "
03167 "[pixel]: %g", -pthrow);
03168
03169 cpl_msg_info(cpl_func, "Object Neg -> x/y-distance [pixel]: %g %g",
03170 x2[0] - x2[1], y2[0] - y2[1]);
03171 }
03172
03173 end_skip;
03174
03175 cpl_apertures_delete(appos);
03176 cpl_apertures_delete(apneg);
03177
03178 return cpl_error_get_code();
03179 }
03180
03181
03182
03183
03203
03204 double visir_img_check_box(const cpl_apertures * appos,
03205 int ipos1, int ipos2,
03206 const cpl_apertures * apneg,
03207 int ineg1, int ineg2, double ssize, double angle,
03208 cpl_boolean * pswapp, cpl_boolean * pswapn)
03209 {
03210
03211
03212
03213
03214 double xp1 = cpl_apertures_get_centroid_x(appos, ipos1) * cos(angle) -
03215 cpl_apertures_get_centroid_y(appos, ipos1) * sin(angle);
03216 double yp1 = cpl_apertures_get_centroid_x(appos, ipos1) * sin(angle) +
03217 cpl_apertures_get_centroid_y(appos, ipos1) * cos(angle);
03218 double xp2 = cpl_apertures_get_centroid_x(appos, ipos2) * cos(angle) -
03219 cpl_apertures_get_centroid_y(appos, ipos2) * sin(angle);
03220 double yp2 = cpl_apertures_get_centroid_x(appos, ipos2) * sin(angle) +
03221 cpl_apertures_get_centroid_y(appos, ipos2) * cos(angle);
03222
03223
03224 const double xpl = xp1 < xp2 ? xp1 : xp2;
03225 const double ypl = xp1 < xp2 ? yp1 : yp2;
03226
03227
03228 const double xpr = xp1 < xp2 ? xp2 : xp1;
03229 const double ypr = xp1 < xp2 ? yp2 : yp1;
03230
03231
03232 double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * cos(angle) -
03233 cpl_apertures_get_centroid_y(apneg, ineg1) * sin(angle);
03234 double yn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * sin(angle) +
03235 cpl_apertures_get_centroid_y(apneg, ineg1) * cos(angle);
03236 double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * cos(angle) -
03237 cpl_apertures_get_centroid_y(apneg, ineg2) * sin(angle);
03238 double yn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * sin(angle) +
03239 cpl_apertures_get_centroid_y(apneg, ineg2) * cos(angle);
03240
03241
03242 const double x_nl = xn1 < xn2 ? xn1 : xn2;
03243 const double y_nl = xn1 < xn2 ? yn1 : yn2;
03244
03245
03246 const double xnr = xn1 < xn2 ? xn2 : xn1;
03247 const double ynr = xn1 < xn2 ? yn2 : yn1;
03248
03249 const double lx1 = xnr - xpl;
03250 const double lx2 = xpr - x_nl;
03251 const double ly1 = ypl - y_nl;
03252 const double ly2 = ynr - ypr;
03253
03254 const double dx1 = lx1 - ssize;
03255 const double dx2 = lx2 - ssize;
03256 const double dy1 = ly1 - ssize;
03257 const double dy2 = ly2 - ssize;
03258
03259 const double ey1 = ynr - ypl;
03260 const double ey2 = ypr - y_nl;
03261 const double ex1 = xpl - x_nl;
03262 const double ex2 = xpr - xnr;
03263
03264 const double ok = sqrt(dx1 * dx1 + dx2 * dx2 + dy1 * dy1 + dy2 * dy2 +
03265 ex1 * ex1 + ex2 * ex2 + ey1 * ey1 + ey2 * ey2);
03266
03267 double result = -1.0;
03268
03269 skip_if(0);
03270
03271 skip_if(pswapp == NULL);
03272 skip_if(pswapn == NULL);
03273 skip_if(appos == apneg);
03274 skip_if(ipos1 == ipos2);
03275 skip_if(ineg1 == ineg2);
03276
03277 skip_if(ssize <= 0.0);
03278
03279 *pswapp = xp1 < xp2 ? CPL_FALSE : CPL_TRUE;
03280 *pswapn = xn1 < xn2 ? CPL_FALSE : CPL_TRUE;
03281
03282 result = ok/ssize;
03283
03284 end_skip;
03285
03286 return result;
03287 }
03288
03289
03290
03309
03310 double visir_img_check_align(const cpl_apertures * appos, int ipos,
03311 const cpl_apertures * apneg, int ineg1, int ineg2,
03312 double ssize, double angle,
03313 cpl_boolean * pswapn)
03314 {
03315
03316
03317
03318
03319 double xp = cpl_apertures_get_centroid_x(appos, ipos) * cos(angle) -
03320 cpl_apertures_get_centroid_y(appos, ipos) * sin(angle);
03321 double yp = cpl_apertures_get_centroid_x(appos, ipos) * sin(angle) +
03322 cpl_apertures_get_centroid_y(appos, ipos) * cos(angle);
03323
03324
03325 double xn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * cos(angle) -
03326 cpl_apertures_get_centroid_y(apneg, ineg1) * sin(angle);
03327 double yn1 = cpl_apertures_get_centroid_x(apneg, ineg1) * sin(angle) +
03328 cpl_apertures_get_centroid_y(apneg, ineg1) * cos(angle);
03329 double xn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * cos(angle) -
03330 cpl_apertures_get_centroid_y(apneg, ineg2) * sin(angle);
03331 double yn2 = cpl_apertures_get_centroid_x(apneg, ineg2) * sin(angle) +
03332 cpl_apertures_get_centroid_y(apneg, ineg2) * cos(angle);
03333
03334 double result = -1.0;
03335
03336 double ok;
03337
03338 cpl_boolean swapn;
03339
03340
03341 const double x_nl = yn1 < yn2 ? xn1 : xn2;
03342 const double y_nl = yn1 < yn2 ? yn1 : yn2;
03343
03344
03345 const double xnr = yn1 < yn2 ? xn2 : xn1;
03346 const double ynr = yn1 < yn2 ? yn2 : yn1;
03347
03348 const double d1 = ynr - yp - ssize;
03349 const double d2 = yp - y_nl - ssize;
03350
03351 const double e1 = xnr - xp;
03352 const double e2 = xp - x_nl;
03353
03354 swapn = yn1 < yn2 ? CPL_FALSE : CPL_TRUE;
03355
03356 ok = sqrt(d1 * d1 + d2 * d2 + e1 * e1 + e2 * e2);
03357
03358 skip_if(0);
03359
03360 skip_if(pswapn == NULL);
03361 skip_if(appos == apneg);
03362 skip_if(ineg1 == ineg2);
03363
03364 skip_if(ssize <= 0.0);
03365
03366 *pswapn = swapn;
03367
03368 result = ok/ssize;
03369
03370 end_skip;
03371
03372 return result;
03373 }
03374
03375
03376
03393
03394 double visir_img_check_line(const cpl_apertures * apnear, int inear,
03395 const cpl_apertures * apfar, int ifar,
03396 double ssize, double angle)
03397 {
03398
03399
03400
03401
03402 double x_n = cpl_apertures_get_centroid_x(apnear, inear) * cos(angle) -
03403 cpl_apertures_get_centroid_y(apnear, inear) * sin(angle);
03404 double y_n = cpl_apertures_get_centroid_x(apnear, inear) * sin(angle) +
03405 cpl_apertures_get_centroid_y(apnear, inear) * cos(angle);
03406
03407
03408 double xf = cpl_apertures_get_centroid_x(apfar, ifar) * cos(angle) -
03409 cpl_apertures_get_centroid_y(apfar, ifar) * sin(angle);
03410 double yf = cpl_apertures_get_centroid_x(apfar, ifar) * sin(angle) +
03411 cpl_apertures_get_centroid_y(apfar, ifar) * cos(angle);
03412
03413 double result = -1.0;
03414
03415 double ok;
03416
03417 const double d = yf - y_n - ssize;
03418
03419 const double e = xf - x_n;
03420
03421 ok = sqrt(d * d + e * e);
03422
03423 skip_if(0);
03424
03425 skip_if(apnear == apfar);
03426
03427 skip_if(ssize <= 0.0);
03428
03429 result = ok/ssize;
03430
03431 end_skip;
03432
03433 return result;
03434 }
03435
03436
03437
03448
03449 static cpl_error_code
03450 get_aqu_data_type(const cpl_frame * frame, const cpl_propertylist * plist,
03451 const cpl_size next, visir_data_type * ptype)
03452 {
03453 int naxis3 = -1;
03454 const char * format = NULL;
03455 if (cpl_propertylist_has(plist, VISIR_PFITS_INT_NAXIS3))
03456 naxis3 = visir_pfits_get_naxis3(plist);
03457
03458 if (cpl_propertylist_has(plist, "ESO DET FRAM FORMAT"))
03459 format = cpl_propertylist_get_string(plist, "ESO DET FRAM FORMAT");
03460
03461
03462 if (next >= 2 || (format && !strcmp(format, "extension"))) {
03463
03464 if (next == 1) {
03465 *ptype = VISIR_DATA_AQU_INT;
03466 }
03467 else {
03468 *ptype = VISIR_DATA_AQU_HCYCLE;
03469 }
03470 }
03471 else if (next == 1 && (naxis3 == -1 || naxis3 == 0)) {
03472 *ptype = VISIR_DATA_AQU_BURST_EXT;
03473 }
03474 else if (next == 0 && naxis3 > 0) {
03475 *ptype = VISIR_DATA_AQU_BURST;
03476 }
03477 else {
03478 cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
03479 "Could not determine format of aquarius file %s",
03480 cpl_frame_get_filename(frame));
03481 }
03482
03483 return cpl_error_get_code();
03484 }
03485
03486
03487
03498
03499 static cpl_error_code
03500 get_drs_data_type(const cpl_frame * frame, const cpl_propertylist * plist,
03501 visir_data_type * ptype)
03502 {
03503 cpl_errorstate cleanstate = cpl_errorstate_get();
03504 const char * sval = visir_pfits_get_frame_type(plist);
03505 const int naxis3 = visir_pfits_get_naxis3(plist);
03506 const int nchop = visir_pfits_get_chop_ncycles(plist);
03507 const int ndit = visir_pfits_get_ndit(plist);
03508 const char * file = cpl_frame_get_filename(frame);
03509 cpl_boolean known_frametype = CPL_TRUE;
03510
03511
03512
03513 cpl_ensure_code(ptype != NULL, CPL_ERROR_NULL_INPUT);
03514
03515 if (sval == NULL) {
03516
03517 visir_error_reset("Could not get FITS key");
03518
03519 known_frametype = CPL_FALSE;
03520 } else if (strcmp(sval, "CUBE1")==0) {
03521 *ptype = VISIR_DATA_CUBE1;
03522 } else if (strcmp(sval, "CUBE2")==0) {
03523 *ptype = VISIR_DATA_CUBE2;
03524 }
03525 else
03526 known_frametype = CPL_FALSE;
03527
03528
03529 if (known_frametype && *ptype == VISIR_DATA_CUBE2) {
03530 if (naxis3 == 2 * nchop + 1) {
03531
03532 } else if (naxis3 == nchop + 2) {
03533 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03534 "and CHOP NCYCLES=%d imply a CUBE1. Assuming "
03535 "the frame type is really CUBE1", file, sval,
03536 naxis3, nchop);
03537 *ptype = VISIR_DATA_CUBE1;
03538 } else {
03539 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03540 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
03541 "Half-Cycle format", file, sval, naxis3, nchop);
03542 skip_if(1);
03543 }
03544 } else if (known_frametype && *ptype == VISIR_DATA_CUBE1) {
03545 if (naxis3 == nchop + 2) {
03546
03547 if (nchop > 1)
03548 cpl_msg_debug(cpl_func, "%s has %d INTERM-frames and one Half-"
03549 "Cycle frame (old CUBE1-format)", file, nchop);
03550
03551 } else if (naxis3 == 2 * nchop + 1) {
03552 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03553 "and CHOP NCYCLES=%d imply a CUBE2. Assuming "
03554 "the frame type is really CUBE2", file, sval,
03555 naxis3, nchop);
03556 *ptype = VISIR_DATA_CUBE2;
03557 } else {
03558 cpl_msg_warning(cpl_func, "%s has FRAM TYPE = '%s', but NAXIS3=%d "
03559 "and CHOP NCYCLES=%d is not a valid VISIR INTERM+"
03560 "Half-Cycle format", file, sval, naxis3, nchop);
03561 skip_if(1);
03562 }
03563 } else if (naxis3 == 2 * nchop + 1) {
03564 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
03565 "CHOP NCYCLES=%d imply a CUBE2. Assuming the frame "
03566 "type is CUBE2", file, sval ? sval : "<NULL>", naxis3,
03567 nchop);
03568 *ptype = VISIR_DATA_CUBE2;
03569 } else if (naxis3 == nchop + 2) {
03570 cpl_msg_warning(cpl_func, "%s has FRAM TYPE='%s', but NAXIS3=%d and "
03571 "CHOP NCYCLES=%d imply a CUBE1. Assuming the frame "
03572 "type is CUBE1", file, sval ? sval : "<NULL>", naxis3,
03573 nchop);
03574 *ptype = VISIR_DATA_CUBE1;
03575 }
03576 else if (!known_frametype && nchop * ndit * 2 >= naxis3) {
03577 cpl_msg_info(cpl_func, "%s has FRAM TYPE='%s', NAXIS3=%d and "
03578 "CHOP NCYCLES=%d imply BURST data.",
03579 file, sval ? sval : "<NULL>", naxis3, nchop);
03580 *ptype = VISIR_DATA_BURST;
03581 } else {
03582 return cpl_error_set_message(cpl_func, CPL_ERROR_BAD_FILE_FORMAT,
03583 "%s has FRAM TYPE='%s', NAXIS3 = %d and "
03584 "CHOP NCYCLES = %d", file,
03585 sval ? sval : "<NULL>", naxis3, nchop);
03586 }
03587
03588 end_skip;
03589
03590 return cpl_error_get_code();
03591 }
03592
03593
03594
03604
03605 cpl_error_code visir_get_data_type(const cpl_frame * frame,
03606 const cpl_propertylist * plist,
03607 visir_data_type * ptype, cpl_size * pnext)
03608 {
03609 const cpl_size next = cpl_frame_get_nextensions(frame);
03610
03611 cpl_ensure_code(ptype != NULL, CPL_ERROR_NULL_INPUT);
03612
03613 skip_if(0);
03614
03615 if (pnext)
03616 *pnext = next;
03617
03618 if (cpl_propertylist_has(plist, "ESO DRS DTYPE"))
03619 *ptype = cpl_propertylist_get_int(plist, "ESO DRS DTYPE");
03620 else {
03621 if (cpl_propertylist_has(plist, VISIR_PFITS_INT_NAVRG))
03622 skip_if(get_aqu_data_type(frame, plist, next, ptype));
03623 else
03624 skip_if(get_drs_data_type(frame, plist, ptype));
03625 }
03626
03627 end_skip;
03628
03629 return cpl_error_get_code();
03630 }
03631
03632
03633
03641
03642 cpl_error_code visir_img_burst_find_delta_chop(const cpl_propertylist * self,
03643 int * ichopchange, int * ihalfcycle)
03644 {
03645
03646 const char * sdateobs =
03647 cpl_propertylist_get_string(self, VISIR_PFITS_STRING_OBS_START);
03648 const char * schopstart =
03649 cpl_propertylist_get_string(self, VISIR_PFITS_STRING_CHOP_START);
03650 const double chop_freq = visir_pfits_get_chop_freq(self);
03651 const int nditskip =
03652 cpl_propertylist_get_int(self, VISIR_PFITS_INT_NDITSKIP);
03653 const double dit = visir_pfits_get_dit(self) *
03654 visir_pfits_get_navrg(self);
03655 double ddateobs, dchopstart;
03656 double period;
03657
03658 skip_if(0);
03659
03660 bug_if(irplib_wcs_mjd_from_string(&ddateobs, sdateobs));
03661 bug_if(irplib_wcs_mjd_from_string(&dchopstart, schopstart));
03662
03663 skip_if(chop_freq <= 0.0);
03664 skip_if(dit <= 0.0);
03665
03666
03667
03668 if (!cpl_propertylist_has(self, VISIR_PFITS_INT_NAVRG)) {
03669 ddateobs += dit * nditskip / (double)VISIR_SECS_PER_DAY;
03670 }
03671
03672 period = 1.0/(chop_freq * dit);
03673
03674
03675 error_if((int)(period + 0.5) % 2 != 0, CPL_ERROR_UNSUPPORTED_MODE,
03676 "Period %g not not an even number, chop frequency %g, dit %g",
03677 period, chop_freq, dit);
03678
03679 error_if((int)(period + 0.5) <= 1, CPL_ERROR_ILLEGAL_INPUT,
03680 "Period %d < 1", (int)(period + 0.5));
03681
03682 *ihalfcycle = (int)(period + 0.5)/2;
03683
03684 cpl_msg_info(cpl_func, "Number of A+B frames in one full chopping cycle: %g",
03685 period);
03686
03687 if (dchopstart < ddateobs) {
03688 double tchop = (ddateobs - dchopstart) * (double)VISIR_SECS_PER_DAY;
03689
03690 double dprecycle = tchop * chop_freq;
03691
03692
03693 const double phase = ceil(dprecycle) - dprecycle;
03694
03695
03696 *ichopchange = (int)ceil(phase * period) - 1;
03697
03698 cpl_msg_info(cpl_func, "Chopping started %gs (%f cycles) before OBS start: "
03699 "%f < %f", tchop, dprecycle, dchopstart, ddateobs);
03700
03701 } else if (ddateobs < dchopstart) {
03702
03703
03704 double tchop = (dchopstart - ddateobs) * (double)VISIR_SECS_PER_DAY;
03705 *ichopchange = (int)ceil(tchop / dit) - 1;
03706 cpl_msg_info(cpl_func, "Chopping started %gs (wasted %g cycles) after OBS "
03707 "start: %f > %f", tchop, tchop * chop_freq, dchopstart,
03708 ddateobs);
03709 } else {
03710
03711
03712
03713 *ichopchange = 0;
03714 cpl_msg_info(cpl_func, "Chopping started with OBS start: %f == %f",
03715 dchopstart, ddateobs);
03716 }
03717
03718
03719 *ichopchange = *ichopchange % (*ihalfcycle * 2);
03720
03721 cpl_msg_info(cpl_func, "Frame of chop change: %d", *ichopchange);
03722
03723 end_skip;
03724
03725 return cpl_error_get_code();
03726 }
03727
03728 #include "visir_destripe.c"