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 #include "visir_recipe.h"
00030
00031 #include "visir_spc_distortion.h"
00032 #include "visir_utils.h"
00033 #include "irplib_framelist.h"
00034 #include <cxlist.h>
00035 #include <string.h>
00036 #include <assert.h>
00037 #include <string.h>
00038 #include <math.h>
00039 #include <time.h>
00040 #ifdef _OPENMP
00041 #include <omp.h>
00042 #endif
00043
00044
00045
00046
00047 #define RECIPE_STRING "visir_util_detect_shift"
00048
00049 #define MAX_BEAMS 4
00050
00051 #define SQR(a) ((a)*(a))
00052
00053
00054
00055
00056
00057 typedef enum {
00058 VISIR_SHIFT_XCORRELATE,
00059 VISIR_SHIFT_BRIGHTEST
00060 } visir_shift_method;
00061
00062 typedef enum {
00063 VISIR_PLANE_AOFF = 0,
00064 VISIR_PLANE_BON = 1,
00065 VISIR_PLANE_AON = 2,
00066 VISIR_PLANE_BOFF = 3,
00067 VISIR_PLANE_UNDEFINED = 4,
00068 } visir_plane_type;
00069
00070 static const char * type2string[] = {"Aoff", "Bon", "Aon", "Boff", "full"};
00071
00072 typedef struct {
00073 cpl_size seqnb;
00074 cpl_image * img;
00075 cpl_propertylist * plist;
00076 visir_plane_type type;
00077
00078 double x;
00079 double y;
00080
00081 double xshift;
00082 double yshift;
00083 double correlation;
00084 double median;
00085 double mad;
00086 double stdev;
00087 double fwhmx;
00088 double fwhmy;
00089 double min;
00090 double max;
00091 double crval1;
00092 double crval2;
00093 } visir_plane;
00094
00095
00096 typedef struct {
00097 double min_cor;
00098 double max_shift;
00099 double max_mad;
00100 } stats_limits;
00101
00102 static
00103 cpl_error_code visir_util_detect_shift_one(cpl_frameset *,
00104 irplib_framelist * , int,
00105 const cpl_parameterlist *,
00106 cpl_mask *,
00107 visir_plane **);
00108
00109 #ifdef VISIR_OMP3
00110 static double t_loading = 0.;
00111 static double t_loading_blocked = 0.;
00112 static double t_handling_blocked_in = 0.;
00113 static double t_handling = 0.;
00114 static double t_handling_blocked_out = 0.;
00115 static double t_writing = 0.;
00116 static double t_writing_blocked = 0.;
00117 #endif
00118 static size_t nbytes_load = 0;
00119 static size_t nbytes_load_eff = 0;
00120 static size_t nbytes_save = 0;
00121
00122 static int is_aqu_data = -1;
00123
00124 #ifdef VISIR_CHAIN
00125 #define cpl_plugin_get_info visir_util_detect_shift_get_info
00126 #endif
00127 cpl_recipe_define(visir_util_detect_shift, VISIR_BINARY_VERSION,
00128 "Find beam positions and reject bad images",
00129 "Julian Tayor", PACKAGE_BUGREPORT, "2012",
00130 "Detects beams in a background subtracted multi-beam image,"
00131 " determines the shifts between different images and their "
00132 "correlation. Images can be rejected if their correlation "
00133 "is bad.\n"
00134 "The files listed in the Set Of Frames (sof-file) "
00135 "must be tagged: \n"
00136 "VISIR-chopnod-corrected-file.fits "
00137 VISIR_UTIL_CORRECTED
00138 "\nbad-pixel-mask.fits " VISIR_CALIB_STATIC_MASK
00139 "\nThe output consists of single beam images of the size "
00140 "of the throw. The shifts will be written int CRPIX[12].");
00141
00142
00146
00147
00148
00149
00150
00151
00152 static visir_plane * visir_plane_new(void)
00153 {
00154 return cpl_calloc(1, sizeof(visir_plane));
00155 }
00156
00157 static void visir_plane_delete(visir_plane * pl)
00158 {
00159 if (pl) {
00160 cpl_image_delete(pl->img);
00161 cpl_propertylist_delete(pl->plist);
00162 cpl_free(pl);
00163 }
00164 }
00165
00166 #ifdef _OPENMP
00167 static inline int
00168 pl_compare_seqnb(const visir_plane * a, const visir_plane * b)
00169 {
00170 if (a->seqnb < b->seqnb)
00171 return -1;
00172 if (a->seqnb > b->seqnb)
00173 return 1;
00174 return 0;
00175 }
00176 #endif
00177
00178 static void planelist_delete(cx_list * l)
00179 {
00180 if (l)
00181 cx_list_destroy(l, (cx_free_func)&visir_plane_delete);
00182 }
00183
00184 static inline cpl_image *
00185 window_extract(const cpl_image * img,
00186 const cpl_size x, const cpl_size y, const cpl_size window)
00187 {
00188 const cpl_size nx = cpl_image_get_size_x(img);
00189 const cpl_size ny = cpl_image_get_size_y(img);
00190 if (x > nx || y > ny || window <= 0)
00191 return NULL;
00192 return cpl_image_extract(img,
00193 CX_MAX(1, x - window / 2),
00194 CX_MAX(1, y - window / 2),
00195 CX_MIN(nx, x + window / 2),
00196 CX_MIN(ny, y + window / 2));
00197 }
00198
00199
00200 static inline void
00201 window_extract_p(visir_plane * pl, const cpl_image * img,
00202 const double x, const double y, const cpl_size window)
00203 {
00204 pl->img = window_extract(img, x, y, window);
00205 pl->x = x - CX_MAX(1, (cpl_size)x - window / 2) + 1;
00206 pl->y = y - CX_MAX(1, (cpl_size)y - window / 2) + 1;
00207 }
00208
00209
00215
00216 static void cut_aqu_illuminated(cpl_image ** img)
00217 {
00218 assert(is_aqu_data >= 0);
00219 if (!is_aqu_data) {
00220 return;
00221 }
00222
00223 cpl_size llx = cpl_image_get_size_x(*img) == 1024 ? 22 : 1;
00224 cpl_size lly = cpl_image_get_size_y(*img) == 1024 ? 92 : 1;
00225 cpl_size urx = cpl_image_get_size_x(*img) == 1024 ?
00226 878 : cpl_image_get_size_x(*img);
00227 cpl_size ury = cpl_image_get_size_y(*img) == 1024 ?
00228 948 : cpl_image_get_size_y(*img);
00229
00230 cpl_image * tmp = cpl_image_extract(*img, llx, lly, urx, ury);
00231 cpl_image_delete(*img);
00232 *img = tmp;
00233 }
00234
00235 static inline cpl_boolean
00236 is_image_bad(const visir_plane * pl, const stats_limits * limits)
00237 {
00238 return pl->correlation < limits->min_cor ||
00239 hypot(pl->xshift, pl->yshift) > limits->max_shift ||
00240 (limits->max_mad > 0 && pl->mad > limits->max_mad);
00241 }
00242
00243
00244
00252
00253 static cpl_error_code
00254 visir_util_detect_shift_fill_parameterlist(cpl_parameterlist * self)
00255 {
00256 const char * context = PACKAGE "." RECIPE_STRING;
00257 cpl_error_code err;
00258
00259 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00260
00261
00262
00263
00264 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00265 "template", VISIR_STR_PAR_EMPTY, NULL,
00266 context, "Correlation template used "
00267 "to detect shifts and reject bad "
00268 "images.\n If none given an "
00269 "averaged image is used");
00270 cpl_ensure_code(!err, err);
00271
00272
00273 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00274 "min-correlation", 0.5, NULL, context,
00275 "Minimal correlation to the template "
00276 "required to be accepted");
00277 cpl_ensure_code(!err, err);
00278
00279
00280 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00281 "max-shift", 10., NULL, context,
00282 "Maximal allowed object shift for an "
00283 "image to be accepted");
00284 cpl_ensure_code(!err, err);
00285
00286
00287 err = irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING,
00288 "max-mad", 0., NULL, context,
00289 "Maximal allowed median absolute "
00290 "deviation for an image to be "
00291 "accepted. <= 0 equals no limit");
00292 cpl_ensure_code(!err, err);
00293
00294
00295 err = irplib_parameterlist_set_int(self, PACKAGE, RECIPE_STRING,
00296 "naverage", 1, NULL, context,
00297 "Number of planes to average before "
00298 "attempting to detect the shifts.");
00299 cpl_ensure_code(!err, err);
00300
00301
00302 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00303 "method", "xcorrelate", NULL, context,
00304 "Method to determine beam shifts.\n"
00305 " xcorrelate: use the cross "
00306 "correlation shift.\n"
00307 " brightest: use the position of "
00308 "the brightest pixel");
00309 cpl_ensure_code(!err, err);
00310
00311
00312 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00313 "no-shift", CPL_FALSE, NULL, context,
00314 "Sets whether to apply the "
00315 "determined shifts in following "
00316 "recipes. Set to TRUE of shifts "
00317 "appear too large.");
00318 cpl_ensure_code(!err, err);
00319
00320
00321 err = irplib_parameterlist_set_bool(self, PACKAGE, RECIPE_STRING,
00322 "no-reject", CPL_TRUE, NULL, context,
00323 "If true images with bad "
00324 "statistics will not be rejected "
00325 "and no shift correction is done");
00326 cpl_ensure_code(!err, err);
00327
00328
00329 err = irplib_parameterlist_set_string(self, PACKAGE, RECIPE_STRING,
00330 "beampos", VISIR_STR_PAR_EMPTY,
00331 NULL, context,
00332 "Define the positions of the beams. "
00333 "These positions are cut by the "
00334 "window to extract the single "
00335 "beam images.\n Format: "
00336 "sign:x,y,window;sign:x,y,window;... "
00337 "\n where sign is \"pos\" or \"neg\" "
00338 "depending on whether the beam is "
00339 "positive or negative.\n "
00340 "The window is optional and defines "
00341 "the size of the cut image around "
00342 "the beam. The default window is "
00343 "the chop throw.\n E.g.: "
00344 "pos:50,60;neg:50,160;\n By default "
00345 "autodetection is attempted.\n");
00346 cpl_ensure_code(!err, err);
00347
00348 err =
00349 irplib_parameterlist_set_double(self, PACKAGE, RECIPE_STRING, "eccmax",
00350 3.0, NULL, context,
00351 "The maximum eccentricity allowed in the combination "
00352 "of the three (in parallel nod/chopping) or four (in "
00353 "perpendicular nod/chopping) beams. In parallel mode, "
00354 "three perfectly aligned points spaced with the "
00355 "chopnod throw will have eccentricity 0, while in "
00356 "perpedicular mode a square with the chopnod throw as "
00357 "the side length will have eccentricity 0"
00358 );
00359 cpl_ensure_code(!err, err);
00360
00361 return CPL_ERROR_NONE;
00362 }
00363
00364
00365
00372
00373 static int visir_util_detect_shift(cpl_frameset * framelist,
00374 const cpl_parameterlist * parlist)
00375 {
00376 irplib_framelist * allframes = NULL;
00377 irplib_framelist * rawframes = NULL;
00378 int n;
00379 cpl_mask * bpm = NULL;
00380 visir_plane * template = NULL;
00381
00382 #ifdef _OPENMP
00383 omp_set_num_threads(visir_get_num_threads(CPL_FALSE));
00384 #endif
00385
00386
00387 skip_if (visir_dfs_set_groups(framelist));
00388 cpl_fits_set_mode(CPL_FITS_START_CACHING);
00389
00390
00391 allframes = irplib_framelist_cast(framelist);
00392 skip_if(allframes == NULL);
00393 rawframes = irplib_framelist_extract_regexp(allframes, "^("
00394 VISIR_UTIL_CORRECTED
00395 ")$", CPL_FALSE);
00396 skip_if (rawframes == NULL);
00397 n = irplib_framelist_get_size(rawframes);
00398
00399
00400 if (cpl_frameset_find_const(framelist, VISIR_CALIB_STATIC_MASK)) {
00401 irplib_framelist * bpmframes =
00402 irplib_framelist_extract(allframes, VISIR_CALIB_STATIC_MASK);
00403 if (irplib_framelist_get_size(bpmframes) == 1) {
00404 const cpl_frame * bpmframe =
00405 irplib_framelist_get_const(bpmframes, 0);
00406 const char * bpmname = cpl_frame_get_filename(bpmframe);
00407 cpl_image * bpmimg =
00408 cpl_image_load(bpmname, CPL_TYPE_UNSPECIFIED, 0, 0);
00409 cpl_error_code errori;
00410
00411 bpm = cpl_mask_threshold_image_create(bpmimg, 0.1, DBL_MAX);
00412 cpl_image_delete(bpmimg);
00413
00414 errori = cpl_error_set_where(cpl_func);
00415 error_if(errori, errori, "Could not load bad pixel map");
00416 cpl_msg_info(cpl_func, "Loaded bad pixel map");
00417 }
00418 else
00419 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
00420 "Unexpected number of bad pixel maps");
00421 irplib_framelist_delete(bpmframes);
00422 }
00423
00424 for (cpl_size i = 0; i < n; i++) {
00425 skip_if(visir_util_detect_shift_one(framelist, rawframes, i,
00426 parlist, bpm, & template));
00427 cpl_fits_set_mode(CPL_FITS_RESTART_CACHING);
00428 }
00429
00430 end_skip;
00431
00432 irplib_framelist_delete(allframes);
00433 irplib_framelist_delete(rawframes);
00434 cpl_mask_delete(bpm);
00435 visir_plane_delete(template);
00436
00437 return cpl_error_get_code();
00438 }
00439
00440
00454
00455 static void
00456 parallel_load(const char * filename, cpl_size iext, cpl_size lim,
00457 cpl_image * imgbuf[], cpl_size nimgbuf)
00458 {
00459 assert(nimgbuf % 2 == 0);
00460 for (cpl_size i = 0; i < nimgbuf; i+=2) {
00461 OMP3_PRAGMA(omp task firstprivate(i) if (iext + i < lim))
00462 {
00463 cpl_errorstate prestate = cpl_errorstate_get();
00464 if (iext + i < lim) {
00465 imgbuf[i] = cpl_image_load(filename, CPL_TYPE_FLOAT, 0,
00466 iext + i);
00467 }
00468 if (iext + i + 1 < lim) {
00469 imgbuf[i + 1] = cpl_image_load(filename, CPL_TYPE_FLOAT, 0,
00470 iext + i + 1);
00471 }
00472 cpl_errorstate_set(prestate);
00473 }
00474 }
00475 OMP3_PRAGMA(omp taskwait)
00476 }
00477
00478
00479 static visir_imglist *
00480 load_range(const cpl_frame *frame, cpl_size * start, cpl_size nplanes,
00481 const cpl_size naverage, cpl_mask * bpm)
00482 {
00483 const cpl_size next = cpl_frame_get_nextensions(frame);
00484 visir_imglist * range = visir_imglist_new(nplanes, NULL);
00485 const char * filename = cpl_frame_get_filename(frame);
00486 cpl_size iext;
00487 cpl_propertylist * plist = NULL;
00488 size_t *pbpm = NULL;
00489 size_t ndata;
00490
00491 cpl_image * imgbuf[20] = {NULL};
00492 size_t nimgbuf = sizeof(imgbuf) / sizeof(imgbuf[0]);
00493
00494 nplanes = CX_MAX(nplanes, naverage);
00495
00496 cpl_ensure(naverage > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00497 cpl_imagelist * av = cpl_imagelist_new();
00498
00499 for (iext = *start; iext < 1 + next; iext++) {
00500 cpl_errorstate prestate = cpl_errorstate_get();
00501 size_t nbytes;
00502
00503 cpl_propertylist_delete(plist);
00504
00505 plist = cpl_propertylist_load(filename, iext);
00506 if (plist == NULL) {
00507 cpl_msg_info(cpl_func, "No propertylist in extension %d",
00508 (int)iext);
00509 cpl_errorstate_set(prestate);
00510 continue;
00511 }
00512
00513
00514
00515
00516
00517 if (imgbuf[0] == NULL) {
00518 parallel_load(filename, iext, next + 1, imgbuf, nimgbuf);
00519 }
00520
00521
00522 cpl_image * img = imgbuf[0];
00523 memmove(imgbuf, imgbuf + 1, sizeof(imgbuf) - sizeof(imgbuf[0]));
00524 imgbuf[nimgbuf - 1] = NULL;
00525
00526 if (img == NULL) {
00527 cpl_msg_debug(cpl_func, "No image-data in extension %d",
00528 (int)iext);
00529 cpl_propertylist_delete(plist);
00530 plist = NULL;
00531 cpl_errorstate_set(prestate);
00532 continue;
00533 }
00534
00535 nbytes = visir_get_nbytes_plist(plist);
00536
00537
00538
00539 if (iext == *start + 1) {
00540 visir_readahead(filename, iext * nbytes, nplanes * nbytes);
00541 }
00542
00543 nbytes_load += nbytes;
00544
00545 nbytes_load_eff += cpl_image_get_size_x(img) *
00546 cpl_image_get_size_y(img) * 4;
00547 cpl_imagelist_set(av, img, cpl_imagelist_get_size(av));
00548
00549 if (cpl_imagelist_get_size(av) == naverage) {
00550 cpl_image * avimg = naverage > 1 ? cpl_imagelist_collapse_create(av)
00551 : cpl_imagelist_unset(av, 0);
00552 if (bpm) {
00553 cpl_image_reject_from_mask(avimg, bpm);
00554
00555 visir_interpolate_rejected(avimg, &pbpm, &ndata);
00556 }
00557
00558 cut_aqu_illuminated(&avimg);
00559 visir_imglist_append(range, avimg, plist);
00560
00561 plist = NULL;
00562 cpl_imagelist_delete(av);
00563 av = cpl_imagelist_new();
00564 }
00565
00566 if (visir_imglist_get_size(range) == nplanes/naverage)
00567 break;
00568 }
00569
00570 if (cpl_imagelist_get_size(av) != 0) {
00571 cpl_image * avimg = cpl_imagelist_collapse_create(av);
00572 if (bpm) {
00573 cpl_image_reject_from_mask(avimg, bpm);
00574
00575 visir_interpolate_rejected(avimg, &pbpm, &ndata);
00576 }
00577 cut_aqu_illuminated(&avimg);
00578 visir_imglist_append(range, avimg, plist);
00579 }
00580
00581 cpl_free(pbpm);
00582 cpl_imagelist_delete(av);
00583 *start = iext + 1;
00584
00585
00586
00587 if (visir_imglist_get_size(range) > 1) {
00588
00589
00590 size_t nbytes = visir_get_nbytes_plist(visir_imglist_get_data(range, 1));
00591 visir_drop_cache(filename, 0, nbytes * (*start));
00592 }
00593
00594 return range;
00595 }
00596
00597 typedef struct {
00598 double x;
00599 double y;
00600 cpl_size window;
00601 int sign;
00602
00603
00604
00605 float weight;
00606 int type;
00607 } beam_info;
00608
00609
00610 static cx_list *
00611 parse_beampos_cmd(const char * bpstr)
00612 {
00613 char *str, *token, *istr = cpl_strdup(bpstr);
00614 cx_list * bpl = cx_list_new();
00615
00616 for (str = istr; ; str = NULL) {
00617 beam_info * bi;
00618 double w = 0;
00619 int ret;
00620
00621 token = strtok(str, ";");
00622 if (token == NULL)
00623 break;
00624
00625 bi = cpl_calloc(1, sizeof(beam_info));
00626 bi->type = cx_list_size(bpl);
00627 cx_list_push_back(bpl, bi);
00628
00629 bi->weight = 1;
00630 if (strncmp(token, "pos", 3) == 0)
00631 bi->sign=1;
00632 else if (strncmp(token, "neg", 3) == 0)
00633 bi->sign=-1;
00634 else
00635 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
00636 "Invalid beam sign: %s", bpstr);
00637
00638 ret = sscanf(token+4, "%lf,%lf,%lf", &bi->x, &bi->y, &w);
00639 if ((ret != 2 && ret != 3) || bi->x < 0 || bi->y < 0 || w < 0)
00640 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
00641 "Invalid beam position: %s", bpstr);
00642
00643 if (ret == 3)
00644 bi->window = ceil(w);
00645 else
00646 bi->window = 0;
00647 }
00648
00649 error_if(cx_list_size(bpl) < 1, CPL_ERROR_ILLEGAL_INPUT,
00650 "Invalid beam position: %s", bpstr);
00651 {
00652 beam_info * pos = NULL;
00653 int npos = 0, nneg = 0;
00654 FOR_EACH_T(beam_info * bi, bpl) {
00655 if (bi->sign > 0) {
00656 pos = bi;
00657 npos++;
00658 }
00659 else
00660 nneg--;
00661 }
00662
00663 if (nneg == 2 && npos == 1)
00664 pos->weight *= 2.;
00665 }
00666 end_skip;
00667
00668 cpl_free(istr);
00669
00670 return bpl;
00671 }
00672
00673 static cx_list *
00674 get_beam_positions(cpl_image * average, const cpl_parameterlist * parlist,
00675 cpl_propertylist * plist)
00676 {
00677 cpl_errorstate cleanstate = cpl_errorstate_get();
00678 cpl_propertylist * qclist = cpl_propertylist_new();
00679 cpl_image * inverse = cpl_image_duplicate(average);
00680 double x[4], y[4];
00681 const cpl_boolean chop_on =
00682 cpl_propertylist_get_bool(plist, VISIR_PFITS_BOOL_CHOP_STATUS);
00683 cx_list * beamposl = cx_list_new();
00684 int n;
00685
00686 skip_if(0);
00687
00688 cpl_image_multiply_scalar(inverse, -1);
00689
00690 visir_chopnod_mode mode =
00691 visir_img_find_beam(qclist, average, inverse,
00692 plist, parlist, RECIPE_STRING,
00693 x, y);
00694 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00695 irplib_error_recover(cleanstate, "Could not detect objects,"
00696 " using full image. Photometry "
00697 "will not work without object positions.");
00698 beam_info * bi = cpl_malloc(sizeof(beam_info));
00699 const cpl_size nx = cpl_image_get_size_x(average);
00700 const cpl_size ny = cpl_image_get_size_y(average);
00701 bi->x = nx / 2;
00702 bi->y = ny / 2;
00703 bi->window = CX_MAX(nx, ny);
00704 bi->sign = 1;
00705 bi->weight = 1;
00706 bi->type = VISIR_PLANE_UNDEFINED;
00707 cx_list_push_back(beamposl, bi);
00708 }
00709 else {
00710
00711 if (mode == VISIR_CHOPNOD_PERPENDICULAR)
00712 n = 4;
00713 else if (mode == VISIR_CHOPNOD_PARALLEL)
00714 n = 3;
00715 else
00716 error_if(1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported chop mode");
00717
00718 if (chop_on == CPL_FALSE)
00719 n = 2;
00720
00721 for (int i = 0; i < n; i++) {
00722 beam_info * bi = cpl_calloc(1, sizeof(beam_info));
00723 bi->x = x[i];
00724 bi->y = y[i];
00725
00726 if (n == 4 || n == 2) {
00727 bi->sign = i < n / 2 ? 1 : -1;
00728 bi->weight = 1.;
00729 }
00730 else {
00731 bug_if(n != 3);
00732
00733 bi->sign = i < 1 ? 1 : -1;
00734 bi->weight = i < 1 ? 2. : 1.;
00735 }
00736 bi->type = i;
00737 cx_list_push_back(beamposl, bi);
00738 }
00739 }
00740
00741 end_skip;
00742 cpl_image_delete(inverse);
00743 cpl_propertylist_delete(qclist);
00744
00745 return beamposl;
00746 }
00747
00748 static cx_list *
00749 cut_image(const cpl_image * img, const cpl_propertylist * plist,
00750 const cx_list * beampos, cpl_size window)
00751 {
00752 cx_list * l = cx_list_new();
00753
00754 FOR_EACH_T(const beam_info * bi, beampos) {
00755 const cpl_size win = bi->window > 0 ? bi->window : window;
00756
00757 visir_plane * pl = visir_plane_new();
00758 bug_if(0);
00759
00760 pl->plist = plist ?
00761 cpl_propertylist_duplicate(plist) : cpl_propertylist_new();
00762
00763 window_extract_p(pl, img, bi->x, bi->y, win);
00764 skip_if(pl->img == NULL);
00765
00766 pl->type = bi->type;
00767
00768 if (bi->sign != 1)
00769 cpl_image_multiply_scalar(pl->img, bi->sign);
00770
00771 cx_list_push_back(l, pl);
00772 }
00773
00774 end_skip;
00775
00776 return l;
00777 }
00778
00779
00780 static void
00781 generate_statistics(visir_plane * pl)
00782 {
00783 cpl_size mx, my;
00784 cpl_errorstate prestate = cpl_errorstate_get();
00785 cpl_stats * stat =
00786 cpl_stats_new_from_image(pl->img, CPL_STATS_MAD |
00787 CPL_STATS_MEDIAN | CPL_STATS_MAXPOS |
00788 CPL_STATS_MAX | CPL_STATS_MIN |
00789 CPL_STATS_STDEV);
00790 pl->stdev = cpl_stats_get_stdev(stat);
00791 pl->median = cpl_stats_get_median(stat);
00792 pl->mad = cpl_stats_get_mad(stat);
00793 pl->max = cpl_stats_get_max(stat);
00794 pl->min = cpl_stats_get_min(stat);
00795 mx = cpl_stats_get_max_x(stat);
00796 my = cpl_stats_get_max_y(stat);
00797 if (cpl_image_get_fwhm(pl->img, mx, my,
00798 &pl->fwhmx, &pl->fwhmy) != CPL_ERROR_NONE) {
00799 pl->fwhmx = 0;
00800 pl->fwhmy = 0;
00801 cpl_msg_warning(cpl_func, "Could not determine fwhm.");
00802 cpl_errorstate_set(prestate);
00803 }
00804
00805 cpl_stats_delete(stat);
00806 }
00807
00808
00809 static cx_list *
00810 handle_chunk(visir_imglist * chunk, const visir_plane * template,
00811 const cx_list * beampos,
00812 const visir_shift_method method,
00813 const stats_limits * limits)
00814 {
00815 const cpl_size n = visir_imglist_get_size(chunk);
00816 cpl_propertylist * mplist = visir_imglist_get_mplist(chunk);
00817 double pthrow = visir_pfits_get_chop_pthrow(mplist);
00818 cx_list * res = cx_list_new();
00819
00820
00821 visir_fftx_cache * fft_cache[MAX_BEAMS];
00822 for (size_t i = 0; i < MAX_BEAMS; i++) {
00823 fft_cache[i] = visir_new_fftx_cache();
00824 }
00825 if (n > 0) {
00826 cx_list * beams = cut_image(visir_imglist_get_img(chunk, 0),
00827 NULL, beampos, pthrow);
00828 skip_if(0);
00829 for (cpl_size j = 0, m = cx_list_size(beams); j < m; j++) {
00830 visir_plane * pl = cx_list_pop_front(beams);
00831 visir_fftxcorrelate(template->img, pl->img, CPL_TRUE,
00832 NULL, NULL, NULL, fft_cache[j]);
00833 visir_plane_delete(pl);
00834 }
00835 cx_list_delete(beams);
00836 }
00837
00838 skip_if(0);
00839
00840
00841
00842
00843
00844 for (cpl_size i = 0; i < n; i++)
00845 OMP3_PRAGMA(omp task firstprivate(i))
00846 {
00847 cx_list * beams = cut_image(visir_imglist_get_img(chunk, i),
00848 visir_imglist_get_data(chunk, i),
00849 beampos, pthrow);
00850
00851 for (cpl_size j = 0, m = cx_list_size(beams); j < m; j++) {
00852 double xshift = 0, yshift = 0, max_cor = 1;
00853 visir_plane * pl = cx_list_pop_front(beams);
00854
00855 if (limits->min_cor > 0 || method == VISIR_SHIFT_XCORRELATE) {
00856
00857 visir_fftxcorrelate(template->img, pl->img, CPL_TRUE,
00858 &xshift, &yshift, &max_cor, fft_cache[j]);
00859 xshift = template->x + xshift;
00860 yshift = template->y + yshift;
00861 }
00862
00863 if (method == VISIR_SHIFT_BRIGHTEST) {
00864 cpl_size ixshift, iyshift;
00865 double xsub, ysub;
00866 cpl_image_get_maxpos(pl->img, &ixshift, &iyshift);
00867 visir_get_subpixel_maxpos(pl->img, ixshift, iyshift,
00868 &xsub, &ysub);
00869 xshift = ixshift + xsub;
00870 yshift = iyshift + ysub;
00871 }
00872
00873 cpl_msg_debug(cpl_func, "%4s: correlation %5.3f shift %5.2f %5.2f",
00874 type2string[pl->type], max_cor, xshift, yshift);
00875
00876 pl->seqnb = i;
00877 pl->xshift = xshift - pl->x;
00878 pl->yshift = yshift - pl->y;
00879 pl->correlation = max_cor;
00880
00881 pl->crval1 = template->crval1;
00882 pl->crval2 = template->crval2;
00883
00884 generate_statistics(pl);
00885 OMP_PRAGMA(omp critical(chunk_lock))
00886 cx_list_push_back(res, pl);
00887 }
00888
00889 cx_list_delete(beams);
00890 }
00891 OMP3_PRAGMA(omp taskwait)
00892
00893 #ifdef _OPENMP
00894
00895
00896 cx_list_sort(res, (cx_compare_func)pl_compare_seqnb);
00897 #endif
00898
00899 end_skip;
00900
00901 for (size_t i = 0; i < sizeof(fft_cache)/sizeof(fft_cache[0]); i++)
00902 visir_delete_fftx_cache(fft_cache[i]);
00903
00904 return res;
00905 }
00906
00907 static visir_plane *
00908 improve_template(const cx_list *imgs, const stats_limits * limits)
00909 {
00910 cpl_imagelist * l = cpl_imagelist_new();
00911 visir_plane * template = visir_plane_new();
00912 cx_list_iterator it = cx_list_begin(imgs);
00913 const cx_list_iterator end = cx_list_end(imgs);
00914 cpl_size nx = 0;
00915 cpl_size ny = 0;
00916
00917 skip_if(cx_list_empty(imgs));
00918
00919 while (it != end) {
00920 visir_plane * pl = cx_list_get(imgs, it);
00921 cpl_image * img = cpl_image_duplicate(pl->img);
00922 nx = nx == 0 ? cpl_image_get_size_x(img) : nx;
00923 ny = ny == 0 ? cpl_image_get_size_y(img) : ny;
00924
00925
00926
00927 if (cpl_image_get_size_x(img) != nx ||
00928 cpl_image_get_size_y(img) != ny) {
00929 it = cx_list_next(imgs, it);
00930 continue;
00931 }
00932
00933
00934 if (is_image_bad(pl, limits) == CPL_FALSE)
00935 cpl_image_shift(img, -visir_round_to_int(pl->xshift),
00936 -visir_round_to_int(pl->yshift));
00937
00938 cpl_imagelist_set(l, img, cpl_imagelist_get_size(l));
00939
00940 it = cx_list_next(imgs, it);
00941 skip_if(0);
00942 }
00943
00944 {
00945
00946 cpl_image * tmp = visir_parallel_median_collapse(l);
00947 visir_plane * firstpl = cx_list_get(imgs, cx_list_begin(imgs));
00948 template->x = firstpl->x;
00949 template->y = firstpl->y;
00950 window_extract_p(template, tmp, firstpl->x, firstpl->y,
00951 cpl_image_get_size_x(tmp) / 2);
00952 cpl_image_delete(tmp);
00953 }
00954
00955 end_skip;
00956 cpl_imagelist_delete(l);
00957
00958 return template;
00959 }
00960
00961 static cpl_error_code
00962 save_images(cx_list * imgs, const cpl_propertylist * mplist,
00963 const cpl_parameterlist * parlist, const int iframe,
00964 const stats_limits * limits)
00965 {
00966 const cpl_boolean noshift =
00967 irplib_parameterlist_get_bool(parlist, PACKAGE,
00968 RECIPE_STRING, "no-shift");
00969 const cpl_boolean noreject =
00970 irplib_parameterlist_get_bool(parlist, PACKAGE,
00971 RECIPE_STRING, "no-reject");
00972 const int naverage =
00973 irplib_parameterlist_get_int(parlist, PACKAGE,
00974 RECIPE_STRING, "naverage");
00975
00976 for (cpl_size j = 0, n = cx_list_size(imgs); j < n; j++) {
00977 char buffer[128];
00978 visir_plane * pl = cx_list_pop_front(imgs);
00979
00980 cpl_boolean bad = is_image_bad(pl, limits);
00981 cpl_type save_type = CPL_TYPE_FLOAT;
00982
00983 if (noreject == CPL_FALSE && bad) {
00984 visir_plane_delete(pl);
00985 continue;
00986 }
00987
00988 if (pl->max <= CX_MAXSHORT && pl->min >= CX_MINSHORT &&
00989 naverage == 1 && cpl_propertylist_get_int(pl->plist, "BITPIX") > 0)
00990 save_type = CPL_TYPE_SHORT;
00991
00992 cpl_propertylist_copy_property_regexp(pl->plist, mplist, "^("
00993 IRPLIB_PFITS_WCS_REGEXP ")$",
00994 CPL_FALSE);
00995
00996
00997 if (noshift || (noreject && bad)) {
00998 cpl_propertylist_append_double(pl->plist, "CRPIX1", pl->x);
00999 cpl_propertylist_append_double(pl->plist, "CRPIX2", pl->y);
01000 } else {
01001 cpl_propertylist_append_double(pl->plist, "CRPIX1",
01002 pl->x + pl->xshift);
01003 cpl_propertylist_append_double(pl->plist, "CRPIX2",
01004 pl->y + pl->yshift);
01005 }
01006 cpl_propertylist_append_double(pl->plist, "CRVAL1", pl->crval1);
01007 cpl_propertylist_append_double(pl->plist, "CRVAL2", pl->crval2);
01008
01009 cpl_propertylist_append_double(pl->plist, "ESO QC CORR",
01010 pl->correlation);
01011
01012 cpl_propertylist_append_double(pl->plist, "ESO QC MEDIAN",
01013 pl->median);
01014 cpl_propertylist_append_double(pl->plist, "ESO QC MAD",
01015 pl->mad);
01016 cpl_propertylist_append_double(pl->plist, "ESO QC STDEV",
01017 pl->stdev);
01018 cpl_propertylist_append_double(pl->plist, "ESO QC FWHMX",
01019 pl->fwhmx);
01020 cpl_propertylist_append_double(pl->plist, "ESO QC FWHMY",
01021 pl->fwhmy);
01022
01023 sprintf(buffer, RECIPE_STRING"_%03d_%s"CPL_DFS_FITS,
01024 iframe+1, type2string[pl->type]);
01025
01026 cpl_image_save(pl->img, buffer, save_type,
01027 pl->plist, CPL_IO_EXTEND);
01028 nbytes_save += cpl_image_get_size_x(pl->img) *
01029 cpl_image_get_size_y(pl->img) * cpl_type_get_sizeof(save_type);
01030
01031 visir_plane_delete(pl);
01032 skip_if(0);
01033 }
01034
01035 end_skip;
01036
01037 return cpl_error_get_code();
01038 }
01039
01040
01041 #ifdef VISIR_OMP3
01042 static cpl_error_code
01043 read_data(visir_queue * readq, cpl_propertylist * mplist,
01044 cpl_frame * frame, const cpl_size chunksize,
01045 const cpl_size naverage, cpl_mask * bpm, cpl_size * cur)
01046 {
01047 visir_imglist * range = NULL;
01048 do {
01049 double t = cpl_test_get_walltime(), t2;
01050 range = load_range(frame, cur, chunksize,
01051 naverage, bpm);
01052 skip_if(0);
01053
01054 if (visir_imglist_get_size(range) == 0) {
01055 visir_imglist_delete(range, (visir_free)cpl_propertylist_delete);
01056 break;
01057 }
01058
01059 visir_imglist_set_mplist(range, mplist);
01060 t2 = cpl_test_get_walltime();
01061 t_loading += t2 - t;
01062 skip_if(visir_queue_put(readq, range));
01063 t_loading_blocked += cpl_test_get_walltime() - t2;
01064 } while (visir_imglist_get_size(range) != 0);
01065
01066 cpl_msg_info(cpl_func,
01067 "Loading thread done, %.3g MB/s (%.3g MB/s uncompressed)",
01068 (nbytes_load / 1024. / 1024.) / t_loading,
01069 (nbytes_load_eff / 1024. / 1024.) / t_loading);
01070
01071 end_skip;
01072
01073 visir_queue_put(readq, NULL);
01074
01075 cpl_error_code err = cpl_error_get_code();
01076 if (err != CPL_ERROR_NONE)
01077 visir_queue_set_error(readq, err);
01078
01079 return err;
01080 }
01081
01082 static cpl_error_code
01083 handle_data(visir_queue * readq, visir_queue * writeq,
01084 const visir_plane * template,
01085 cx_list * beampos, const visir_shift_method method,
01086 const stats_limits * limits)
01087 {
01088 visir_imglist * range = NULL;
01089 do {
01090 double t = cpl_test_get_walltime(), t2;
01091 range = visir_queue_pop(readq);
01092 t2 = cpl_test_get_walltime();
01093 t_handling_blocked_in += t2 - t;
01094 if (range == NULL)
01095 break;
01096 cx_list * res = handle_chunk(range, template, beampos,
01097 method, limits);
01098
01099 visir_imglist_delete(range, (visir_free)cpl_propertylist_delete);
01100
01101 t = cpl_test_get_walltime();
01102 t_handling += t - t2;
01103 skip_if(visir_queue_put(writeq, res));
01104 t_handling_blocked_out += cpl_test_get_walltime() - t;
01105 } while(range != NULL);
01106
01107 end_skip;
01108
01109 visir_queue_put(writeq, NULL);
01110
01111 cpl_error_code err = cpl_error_get_code();
01112 if (err != CPL_ERROR_NONE) {
01113 visir_queue_set_error(writeq, err);
01114 visir_queue_set_error(readq, err);
01115 }
01116
01117 return err;
01118 }
01119
01120
01121 static cpl_error_code
01122 write_data(visir_queue * writeq, cpl_propertylist * mplist,
01123 const cpl_parameterlist * parlist,
01124 const int iframe, const stats_limits * limits,
01125 const cpl_size chunksize, const cpl_size next)
01126 {
01127 cx_list * res = NULL;
01128 cpl_size count = 1;
01129 do {
01130 double t = cpl_test_get_walltime(), t2;
01131 res = visir_queue_pop(writeq);
01132 t2 = cpl_test_get_walltime();
01133 t_writing_blocked += t2 - t;
01134 if (res == NULL)
01135 break;
01136
01137 save_images(res, mplist, parlist, iframe, limits);
01138 planelist_delete(res);
01139 t_writing += cpl_test_get_walltime() - t2;
01140 skip_if(0);
01141 cpl_msg_info(cpl_func, "done: %d/%d",
01142 (int)CX_MIN((count * chunksize), next + 1),
01143 (int)next + 1);
01144 count++;
01145 } while(res != NULL);
01146
01147 cpl_msg_info(cpl_func, "Writing thread done, %.3g MB /s",
01148 (nbytes_save / 1024. / 1024.) / t_writing);
01149
01150 end_skip;
01151
01152 cpl_error_code err = cpl_error_get_code();
01153 if (err != CPL_ERROR_NONE)
01154 visir_queue_set_error(writeq, err);
01155
01156 return err;
01157 }
01158 #endif
01159
01160
01169
01170 static
01171 cpl_error_code visir_util_detect_shift_one(cpl_frameset * framelist,
01172 irplib_framelist * rawframes,
01173 int iframe,
01174 const cpl_parameterlist * parlist,
01175 cpl_mask * bpm,
01176 visir_plane ** ptemplate)
01177 {
01178 cpl_frameset * products = cpl_frameset_new();
01179 visir_plane * template = NULL;
01180 cpl_image * av = NULL;
01181 cpl_boolean bfirst = CPL_FALSE;
01182 cx_list * res = NULL;
01183 cpl_frame * frame = irplib_framelist_get(rawframes, iframe);
01184 const char * filename = cpl_frame_get_filename(frame);
01185 const char * fn_template =
01186 irplib_parameterlist_get_string(parlist, PACKAGE,
01187 RECIPE_STRING, "template");
01188 const int naverage =
01189 irplib_parameterlist_get_int(parlist, PACKAGE,
01190 RECIPE_STRING, "naverage");
01191 cpl_size cur = 0;
01192 const cpl_size chunksize = 200 * naverage;
01193 cpl_frame_set_group(frame, CPL_FRAME_GROUP_RAW);
01194
01195
01196 cpl_size next;
01197 cpl_propertylist * mplist = cpl_propertylist_load(filename, 0);
01198 {
01199 visir_data_type datatype;
01200 visir_get_data_type(frame, mplist, &datatype, &next);
01201 is_aqu_data = visir_data_is_aqu(datatype);
01202 }
01203 visir_imglist * range = load_range(frame, &cur, chunksize,
01204 naverage, bpm);
01205 visir_imglist_set_mplist(range, mplist);
01206 double pthrow = visir_pfits_get_chop_pthrow(mplist);
01207 const char * sbeampos =
01208 irplib_parameterlist_get_string(parlist, PACKAGE,
01209 RECIPE_STRING, "beampos");
01210 cx_list * beampos = NULL;
01211
01212 skip_if(range == NULL);
01213
01214 if (cpl_frameset_find(framelist, VISIR_UTIL_REPACK_MEAN_PROCATG)) {
01215 cpl_frame * fn = cpl_frameset_find(framelist, VISIR_UTIL_REPACK_MEAN_PROCATG);
01216 av = cpl_image_load(cpl_frame_get_filename(fn),
01217 CPL_TYPE_FLOAT, 0,0);
01218 cut_aqu_illuminated(&av);
01219 skip_if(0);
01220
01221 if (bpm) {
01222 cpl_image * ibpm = cpl_image_new_from_mask(bpm);
01223 cut_aqu_illuminated(&ibpm);
01224 cpl_mask * nbpm = cpl_mask_threshold_image_create(ibpm, 0.1, DBL_MAX);
01225
01226 cpl_image_reject_from_mask(av, nbpm);
01227
01228 cpl_image_delete(ibpm);
01229 cpl_mask_delete(nbpm);
01230
01231 skip_if(visir_interpolate_rejected(av, NULL, NULL));
01232 }
01233 }
01234 else {
01235 const cpl_imagelist * tmpl = visir_imglist_get_imglist(range);
01236 av = visir_parallel_median_collapse(tmpl);
01237 skip_if(0);
01238 }
01239
01240 if (!visir_str_par_is_empty(sbeampos)) {
01241 beampos = parse_beampos_cmd(sbeampos);
01242
01243 if (is_aqu_data) {
01244 FOR_EACH_T(beam_info * bi, beampos) {
01245 bi->x -= cpl_image_get_size_x(av) == 1024 - 22 - (1024 - 878 - 1) ? 22 : 0;
01246 bi->y -= cpl_image_get_size_y(av) == 1024 - 92 - (1024 - 948 - 1) ? 92 : 0;
01247 }
01248 }
01249 }
01250 else
01251 beampos = get_beam_positions(av, parlist, mplist);
01252
01253 skip_if(0);
01254
01255 error_if(cx_list_size(beampos) > MAX_BEAMS, CPL_ERROR_ILLEGAL_INPUT,
01256 "Too many beams, maximum supported: %d", MAX_BEAMS);
01257 error_if(ptemplate == NULL, CPL_ERROR_NULL_INPUT, "Bug: ptemplate == NULL");
01258
01259
01260
01261 if ((!visir_str_par_is_empty(sbeampos) ||
01262 cpl_frameset_find(framelist, VISIR_UTIL_REPACK_MEAN_PROCATG)) &&
01263 cpl_propertylist_has(mplist, VISIR_DRS_CUMOFFSETXA)) {
01264 double dxa = cpl_propertylist_get_double(mplist, VISIR_DRS_CUMOFFSETXA);
01265 double dya = cpl_propertylist_get_double(mplist, VISIR_DRS_CUMOFFSETYA);
01266 double dxb = cpl_propertylist_get_double(mplist, VISIR_DRS_CUMOFFSETXB);
01267 double dyb = cpl_propertylist_get_double(mplist, VISIR_DRS_CUMOFFSETYB);
01268 FOR_EACH_T(beam_info * bi, beampos) {
01269 if (bi->type == VISIR_PLANE_AOFF || bi->type == VISIR_PLANE_AON ||
01270 bi->type == VISIR_PLANE_UNDEFINED) {
01271 bi->x += dxa;
01272 bi->y += dya;
01273 }
01274 else if (bi->type == VISIR_PLANE_BOFF || bi->type == VISIR_PLANE_BON) {
01275 bi->x += dxb;
01276 bi->y += dyb;
01277 }
01278 }
01279 }
01280
01281 FOR_EACH_T(const beam_info * bi, beampos) {
01282 double window = bi->window > 0 ? bi->window : pthrow;
01283 cpl_msg_info(cpl_func, "Beam position: x %5.1f, y %5.1f, window %4.0f,"
01284 " sign %2d", bi->x, bi->y, window, bi->sign);
01285 }
01286
01287 stats_limits limits;
01288 limits.min_cor =
01289 irplib_parameterlist_get_double(parlist, PACKAGE,
01290 RECIPE_STRING, "min-correlation");
01291 limits.max_shift =
01292 irplib_parameterlist_get_double(parlist, PACKAGE,
01293 RECIPE_STRING, "max-shift");
01294 limits.max_mad =
01295 irplib_parameterlist_get_double(parlist, PACKAGE,
01296 RECIPE_STRING, "max-mad");
01297
01298 const char * smethod =
01299 irplib_parameterlist_get_string(parlist, PACKAGE,
01300 RECIPE_STRING, "method");
01301 visir_shift_method method = VISIR_SHIFT_XCORRELATE;
01302
01303 if (strncmp(smethod, "xcorrelate", sizeof("xcorrelate")) == 0)
01304 method = VISIR_SHIFT_XCORRELATE;
01305 else if (strncmp(smethod, "brightest", sizeof("brightest")) == 0)
01306 method = VISIR_SHIFT_BRIGHTEST;
01307 else
01308 cpl_msg_warning(cpl_func, "Unknown method %s. Using xcorrelate",
01309 smethod);
01310
01311
01312
01313 if (*ptemplate != NULL)
01314 template = *ptemplate;
01315 else if (!visir_str_par_is_empty(fn_template)) {
01316 cpl_msg_info(cpl_func, "Loading %s as template", fn_template);
01317 template = visir_plane_new();
01318 template->plist = cpl_propertylist_load(fn_template, 0);
01319 template->img = cpl_image_load(fn_template, CPL_TYPE_UNSPECIFIED, 0, 0);
01320 skip_if(template->img == NULL || template->plist == NULL);
01321 if (cpl_propertylist_has(template->plist, "CRPIX1") &&
01322 cpl_propertylist_has(template->plist, "CRPIX2") &&
01323 cpl_propertylist_has(template->plist, "CRVAL1") &&
01324 cpl_propertylist_has(template->plist, "CRVAL2")) {
01325 template->x = cpl_propertylist_get_double(template->plist, "CRPIX1");
01326 template->y = cpl_propertylist_get_double(template->plist, "CRPIX2");
01327 template->crval1 = cpl_propertylist_get_double(template->plist, "CRVAL1");
01328 template->crval2 = cpl_propertylist_get_double(template->plist, "CRVAL2");
01329 }
01330 else {
01331 error_if(1, CPL_ERROR_ILLEGAL_INPUT,
01332 "Input template must have WCS coordinates");
01333
01334 }
01335 *ptemplate = template;
01336 bfirst = CPL_TRUE;
01337 }
01338 else {
01339 template = visir_plane_new();
01340 cpl_msg_info(cpl_func, "Using average as template");
01341 const cpl_boolean noshift =
01342 irplib_parameterlist_get_bool(parlist, PACKAGE,
01343 RECIPE_STRING, "no-shift");
01344 beam_info * bi = cx_list_get(beampos, cx_list_begin(beampos));
01345
01346 const cpl_size window = bi->window > 0 ?
01347 bi->window * 2 / 3. : pthrow * 2 / 3.;
01348 window_extract_p(template, av, bi->x, bi->y, window);
01349 cpl_image_multiply_scalar(template->img, bi->sign);
01350
01351 if (!noshift &&
01352 (limits.min_cor > 0 || method == VISIR_SHIFT_XCORRELATE)) {
01353
01354 stats_limits lim;
01355 lim.min_cor = 0;
01356 lim.max_shift = 5000;
01357 lim.max_mad = 0;
01358 OMP_PRAGMA(omp parallel)
01359 OMP_PRAGMA(omp single)
01360 res = handle_chunk(range, template, beampos, method, &lim);
01361 visir_plane_delete(template);
01362 template = improve_template(res, &limits);
01363
01364 planelist_delete(res);
01365 res = NULL;
01366 }
01367 template->plist = cpl_propertylist_new();
01368 cpl_propertylist_append_double(template->plist, "CRPIX1", template->x);
01369 cpl_propertylist_append_double(template->plist, "CRPIX2", template->y);
01370 *ptemplate = template;
01371
01372
01373 cpl_wcs * wcs = cpl_wcs_new_from_propertylist(mplist);
01374 cpl_matrix * from = cpl_matrix_new(1, 2);
01375 cpl_matrix * to = NULL;
01376 cpl_matrix_set(from, 0, 0, bi->x);
01377 cpl_matrix_set(from, 0, 1, bi->y);
01378 cpl_array * status = NULL;
01379 skip_if(cpl_wcs_convert(wcs, from, &to, &status, CPL_WCS_PHYS2WORLD));
01380 template->crval1 = cpl_matrix_get(to, 0, 0);
01381 template->crval2 = cpl_matrix_get(to, 0, 1);
01382 cpl_wcs_delete(wcs);
01383 cpl_matrix_delete(from);
01384 cpl_matrix_delete(to);
01385 cpl_array_delete(status);
01386
01387 bfirst = CPL_TRUE;
01388 }
01389 skip_if(0);
01390
01391 if (bpm) {
01392 int i = 0;
01393 cpl_frame * frm = cpl_frameset_find(framelist, VISIR_CALIB_STATIC_MASK);
01394 cpl_image * ibpm = cpl_image_new_from_mask(bpm);
01395 cut_aqu_illuminated(&ibpm);
01396 cx_list * cbpml = cut_image(ibpm, NULL, beampos, pthrow);
01397 cpl_frameset * usedframes = cpl_frameset_new();
01398 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frm));
01399
01400 FOR_EACH(it, cbpml) {
01401 char buffer[128];
01402 cpl_image * img = ((visir_plane*)cx_list_get(cbpml, it))->img;
01403 cpl_image_abs(img);
01404 sprintf(buffer, RECIPE_STRING"_bpm_%03d_%s"CPL_DFS_FITS,
01405 iframe+1, type2string[i++]);
01406 irplib_dfs_save_image(products, parlist,
01407 usedframes, img, CPL_BPP_8_UNSIGNED,
01408 RECIPE_STRING,
01409 VISIR_CALIB_BPM,
01410 NULL, NULL, visir_pipe_id,
01411 buffer);
01412 }
01413 planelist_delete(cbpml);
01414 cpl_image_delete(ibpm);
01415 cpl_frameset_delete(usedframes);
01416 }
01417
01418 skip_if(0);
01419
01420 if (bfirst) {
01421 char buffer[128];
01422 cpl_frameset * usedframes = cpl_frameset_new();
01423 sprintf(buffer, RECIPE_STRING"_template_%03d"CPL_DFS_FITS,
01424 iframe+1);
01425
01426 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frame));
01427 skip_if(irplib_dfs_save_image(products, parlist,
01428 usedframes, template->img, CPL_TYPE_FLOAT,
01429 RECIPE_STRING,
01430 VISIR_UTIL_DETECT_SHIFT_TEMPLATE_PROCATG,
01431 template->plist, NULL, visir_pipe_id,
01432 buffer));
01433 cpl_frameset_delete(usedframes);
01434 }
01435
01436 FOR_EACH_T(const beam_info * bi, beampos) {
01437 char buffer[128];
01438 cpl_frameset * usedframes = cpl_frameset_new();
01439 cpl_propertylist * _mplist = cpl_propertylist_new();
01440 cpl_propertylist_copy_property_regexp(_mplist, mplist, ".*", 0);
01441
01442 if (bi->type != VISIR_PLANE_UNDEFINED)
01443 sprintf(buffer, "%01d", bi->type);
01444 else
01445 sprintf(buffer, "UNDEFINED");
01446 cpl_propertylist_append_string(_mplist, "ESO QC BEAMID", buffer);
01447 cpl_propertylist_append_float(_mplist, "ESO DRS IMGWGT", bi->weight);
01448 cpl_propertylist_append_double(_mplist, "ESO QC BEAMX", bi->x);
01449 cpl_propertylist_append_double(_mplist, "ESO QC BEAMY", bi->y);
01450
01451 sprintf(buffer, RECIPE_STRING"_%03d_%s"CPL_DFS_FITS,
01452 iframe+1, type2string[bi->type]);
01453
01454 cpl_frameset_insert(usedframes, cpl_frame_duplicate(frame));
01455 irplib_dfs_save_propertylist(products, parlist,
01456 usedframes, RECIPE_STRING,
01457 VISIR_UTIL_DETECT_SHIFT_PROCATG,
01458 _mplist, NULL, visir_pipe_id, buffer);
01459 cpl_frameset_delete(usedframes);
01460 cpl_propertylist_delete(_mplist);
01461 skip_if(0);
01462 }
01463
01464 cpl_msg_info(cpl_func, "Working on frame %d", iframe);
01465
01466
01467 #ifdef VISIR_OMP3
01468 cpl_error_code serr, werr, lerr;
01469 serr = werr = lerr = CPL_ERROR_NONE;
01470 visir_queue * readq = visir_queue_init(3);
01471 visir_queue * writeq = visir_queue_init(3);
01472 visir_queue_put(readq, range);
01473 range = NULL;
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 int nthreads = CX_MAX(visir_get_num_threads(CPL_FALSE) + 2, 3);
01487 #pragma omp parallel num_threads(nthreads)
01488 {
01489 #pragma omp single nowait
01490 lerr = read_data(readq, mplist, frame, chunksize, naverage, bpm, &cur);
01491 #pragma omp single nowait
01492 serr = handle_data(readq, writeq, template, beampos, method, &limits);
01493 #pragma omp single nowait
01494 werr = write_data(writeq, mplist, parlist, iframe, &limits,
01495 chunksize, next);
01496 }
01497 visir_queue_delete(readq);
01498 visir_queue_delete(writeq);
01499
01500 error_if(serr, serr, "Failed to save data");
01501 error_if(werr, werr, "Failed to handle data");
01502 error_if(lerr, lerr, "Failed to load data");
01503
01504 cpl_msg_info(cpl_func, "Time spent loading data: %3.3gs",
01505 t_loading);
01506 cpl_msg_info(cpl_func, "Time loading thread was blocked on output: %3.3gs",
01507 t_loading_blocked < 1e-3 ? 0. : t_loading_blocked);
01508 cpl_msg_info(cpl_func, "Time working thread was blocked on input: %3.3gs",
01509 t_handling_blocked_in < 1e-3 ? 0. : t_handling_blocked_in);
01510 cpl_msg_info(cpl_func, "Time working on data: %3.3gs",
01511 t_handling);
01512 cpl_msg_info(cpl_func, "Time working thread was blocked on output: %3.3gs",
01513 t_handling_blocked_out < 1e-3 ? 0. : t_handling_blocked_out);
01514 cpl_msg_info(cpl_func, "Time saving thread was blocked on input: %3.3gs",
01515 t_writing_blocked < 1e-3 ? 0. : t_writing_blocked);
01516 cpl_msg_info(cpl_func, "Time spent saving data: %3.3gs",
01517 t_writing);
01518 #else
01519
01520 do {
01521 res = handle_chunk(range, template, beampos,
01522 method, &limits);
01523
01524 skip_if(0);
01525 cpl_msg_info(cpl_func, "done: %d/%d",
01526 (int)cur - 1, (int)next + 1);
01527 visir_imglist_delete(range,
01528 (visir_free)cpl_propertylist_delete);
01529 skip_if(0);
01530
01531 range = load_range(frame, &cur, chunksize,
01532 naverage, bpm);
01533 skip_if(0);
01534 visir_imglist_set_mplist(range, mplist);
01535
01536 save_images(res, mplist, parlist, iframe, &limits);
01537 planelist_delete(res);
01538 res = NULL;
01539 skip_if(0);
01540 } while (visir_imglist_get_size(range) != 0);
01541 #endif
01542
01543
01544 FOR_EACH_FRAMESET_C(frm, products) {
01545 if (cpl_frame_get_nextensions(frm) > 0 ||
01546 strcmp(cpl_frame_get_tag(frm),
01547 VISIR_UTIL_DETECT_SHIFT_TEMPLATE_PROCATG) == 0 ||
01548 strcmp(cpl_frame_get_tag(frm),
01549 VISIR_CALIB_BPM) == 0 ||
01550 cpl_frame_get_group(frm) != CPL_FRAME_GROUP_PRODUCT) {
01551 cpl_frameset_insert(framelist, cpl_frame_duplicate(frm));
01552 }
01553 }
01554
01555 end_skip;
01556 planelist_delete(res);
01557 cpl_image_delete(av);
01558 cx_list_destroy(beampos, (visir_free)cpl_free);
01559 visir_imglist_delete(range, (visir_free)cpl_propertylist_delete);
01560 cpl_propertylist_delete(mplist);
01561 cpl_frameset_delete(products);
01562
01563 return cpl_error_get_code();
01564 }
01565