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 #if !defined _XOPEN_SOURCE
00027 #define _XOPEN_SOURCE 500
00028 #endif
00029
00030
00031
00032
00033
00034 #include "visir_utils.h"
00035
00036 #include "irplib_utils.h"
00037
00038 #include "visir_inputs.h"
00039 #include "visir_pfits.h"
00040 #define visir_pfits_get_int(KEY) irplib_pfits_get_int(self, KEY)
00041 #include "visir_spc_distortion.h"
00042 #include "visir_cpl_compat.h"
00043 #include <cpl.h>
00044 #include <cxlist.h>
00045 #include <sys/types.h>
00046 #include <sys/wait.h>
00047 #include <errno.h>
00048
00049 #include <string.h>
00050 #include <math.h>
00051 #include <assert.h>
00052 #include <stdlib.h>
00053 #include <unistd.h>
00054 #include <libgen.h>
00055 #include <stdint.h>
00056
00057
00058 #include <sys/stat.h>
00059 #include <sys/types.h>
00060 #include <fcntl.h>
00061
00062 #include <signal.h>
00063
00064 #ifdef _OPENMP
00065 #include <omp.h>
00066 #endif
00067
00068
00069 IRPLIB_DIAG_PRAGMA_PUSH_ERR(-Wimplicit-function-declaration)
00070
00071 #ifdef __SSE3__
00072 #include <pmmintrin.h>
00073 #endif
00074 #ifdef __SSE2__
00075 #include <xmmintrin.h>
00076 #endif
00077
00078
00079
00080
00081
00082 #define VISIR_BACKGD_START 76
00083 #define VISIR_BACKGD_STOP 172
00084
00085
00091
00092
00093 #define IND(x, y , nx) ((x) + (nx) * (y))
00094
00095
00096
00097
00098
00099
00100 static double visir_great_circle_dist(double, double, double, double);
00101 static double ra_hms2deg(int, int, double);
00102 static double dec_hms2deg(int, int, double);
00103
00104 static const char * visir_get_capa(const cpl_propertylist *);
00105 static double visir_hcycle_background(const irplib_framelist *, int, int);
00106
00107 #ifdef VISIR_MASK_HAS
00108 static cpl_boolean visir_mask_has(const cpl_mask *, cpl_binary, int);
00109 #endif
00110
00114
00120
00121 size_t visir_get_num_threads(cpl_boolean force)
00122 {
00123 long ret = 1;
00124 FILE * f;
00125 if (force == CPL_FALSE && getenv("OMP_NUM_THREADS")) {
00126 char * endptr, * str = getenv("OMP_NUM_THREADS");
00127 int r = (int)strtol(str, &endptr, 10);
00128 return (str == endptr || r < 1) ? 1 : r;
00129 }
00130 #ifdef _OPENMP
00131
00132 ret = omp_get_max_threads();
00133 #endif
00134 #if defined HAVE_SYSCONF && defined _SC_NPROCESSORS_ONLN
00135 ret = sysconf(_SC_NPROCESSORS_ONLN);
00136 #endif
00137
00138 f = fopen("/sys/devices/system/cpu/cpu0/"
00139 "topology/thread_siblings_list", "r");
00140 if (f) {
00141 char buf[80];
00142 if (fgets(buf, 80, f) != NULL) {
00143 int a, b;
00144 buf[79] = 0;
00145 if (sscanf(buf, "%d,%d", &a, &b) == 2) {
00146 ret /= 2;
00147 }
00148 }
00149 fclose(f);
00150 }
00151 return ret < 1 ? 1 : ret;
00152 }
00153
00154
00155
00162
00163 cpl_boolean visir_get_tempdir(char * tmpdir_)
00164 {
00165 cpl_boolean have_tmpdir = CPL_FALSE;
00166 char tmpdir[strlen(tmpdir_) + 1];
00167
00168
00169
00170
00171 for (int i = 0; i < 10 && !have_tmpdir; i++) {
00172 strcpy(tmpdir, tmpdir_);
00173 int fd = mkstemp(tmpdir);
00174 skip_if(fd < 0);
00175 close(fd);
00176 skip_if(unlink(tmpdir));
00177 have_tmpdir = mkdir(tmpdir, O_RDWR | S_IRWXU) == 0;
00178 }
00179
00180 error_if(have_tmpdir != CPL_TRUE, CPL_ERROR_FILE_IO,
00181 "Temporary directory creation failed");
00182
00183 strcpy(tmpdir_, tmpdir);
00184
00185 end_skip;
00186
00187 return have_tmpdir;
00188 }
00189
00190
00195
00196 char * visir_get_cwd(void)
00197 {
00198 size_t n = 4096;
00199 char * buf;
00200 errno = 0;
00201
00202 while (1) {
00203 buf = cpl_malloc(n);
00204 if (getcwd(buf, n) != 0) {
00205 break;
00206 }
00207 else if (errno == ERANGE) {
00208
00209 errno = 0;
00210 n *= 2;
00211 cpl_free(buf);
00212 }
00213 else {
00214 cpl_free(buf);
00215 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00216 "Could not determine current working "
00217 "directory: %s", strerror(errno));
00218 return NULL;
00219 }
00220 }
00221
00222 return buf;
00223 }
00224
00225
00232
00233 void visir_drop_cache(const char * VISIR_ATTR_UNUSED filename,
00234 off_t VISIR_ATTR_UNUSED offset,
00235 off_t VISIR_ATTR_UNUSED length)
00236 {
00237 #if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_DONTNEED
00238 int fd = open(filename, O_RDONLY);
00239 if (fd != -1) {
00240
00241 posix_fadvise(fd, offset, length, POSIX_FADV_DONTNEED);
00242 close(fd);
00243 }
00244 #endif
00245 }
00246
00247
00259
00260 void visir_readahead(const char * VISIR_ATTR_UNUSED filename,
00261 off_t VISIR_ATTR_UNUSED offset, off_t VISIR_ATTR_UNUSED length)
00262 {
00263 #if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_WILLNEED
00264 int fd = open(filename, O_RDONLY);
00265 if (fd != -1) {
00266
00267 posix_fadvise(fd, offset, length, POSIX_FADV_WILLNEED);
00268 close(fd);
00269 }
00270 #endif
00271 }
00272
00273
00278
00279 size_t visir_get_nbytes(const cpl_image * img)
00280 {
00281 return cpl_image_get_size_x(img) *
00282 cpl_image_get_size_y(img) *
00283 cpl_type_get_sizeof(cpl_image_get_type(img));
00284 }
00285
00286
00295
00296 size_t visir_get_nbytes_plist(const cpl_propertylist * self)
00297 {
00298 int naxis = visir_pfits_get_int("NAXIS");
00299 int bitpix = abs(visir_pfits_get_int("BITPIX"));
00300 int pcount = 0;
00301 int gcount = 1;
00302 size_t naxis_bytes = 1;
00303 size_t nbytes;
00304 for (int i = 0; i < naxis; i++) {
00305 char buffer[80];
00306 sprintf(buffer, "NAXIS%d", i + 1);
00307 naxis_bytes *= visir_pfits_get_int(buffer);
00308 }
00309 if (cpl_propertylist_has(self, "XTENSION")) {
00310 pcount = visir_pfits_get_int("PCOUNT");
00311 gcount = visir_pfits_get_int("GCOUNT");
00312 }
00313 if (cpl_error_get_code())
00314 return 0;
00315
00316 nbytes = (bitpix / 8) * gcount * (pcount + naxis_bytes);
00317
00318 nbytes += cpl_propertylist_get_size(self) * 80;
00319 return nbytes;
00320 }
00321
00322
00333
00334 cpl_error_code visir_image_multiply_fast(cpl_image * im1,
00335 const cpl_image * im2)
00336 {
00337 #if defined __SSE3__ || defined __SSE2__
00338 cpl_ensure_code(im1 != NULL, CPL_ERROR_NULL_INPUT);
00339 cpl_ensure_code(im2 != NULL, CPL_ERROR_NULL_INPUT);
00340
00341 if (cpl_image_get_type(im1) == CPL_TYPE_FLOAT_COMPLEX &&
00342 cpl_image_get_type(im2) == CPL_TYPE_FLOAT_COMPLEX) {
00343 const cpl_size nx1 = cpl_image_get_size_x(im1);
00344 const cpl_size ny1 = cpl_image_get_size_y(im1);
00345 const cpl_size nx2 = cpl_image_get_size_x(im2);
00346 const cpl_size ny2 = cpl_image_get_size_y(im2);
00347 const size_t Nt = nx1 * ny1;
00348 const size_t n = (Nt % 2) == 1 ? Nt - 1 : Nt;
00349
00350 float complex * a = cpl_image_get_data(im1);
00351 const float complex * b = cpl_image_get_data_const(im2);
00352
00353 cpl_ensure_code(nx1 == nx2, CPL_ERROR_INCOMPATIBLE_INPUT);
00354 cpl_ensure_code(ny1 == ny2, CPL_ERROR_INCOMPATIBLE_INPUT);
00355 cpl_ensure_code(n < SIZE_MAX - 1, CPL_ERROR_ACCESS_OUT_OF_RANGE);
00356
00357
00358
00359 if (((intptr_t)a % 16) != 0 || ((intptr_t)b % 16) != 0)
00360 return cpl_image_multiply(im1, im2);
00361
00362 #if defined __SSE2__ && !defined __SSE3__
00363 const __m128 neg = (__m128)_mm_set_epi32(0x0u, 0x80000000u, 0x0u, 0x80000000u);
00364 #endif
00365 for (size_t i = 0; i < n; i += 2) {
00366 __m128 ua = _mm_load_ps((float *)&a[i]);
00367 __m128 ub = _mm_load_ps((const float *)&b[i]);
00368
00369 __m128 reala = _mm_shuffle_ps(ua, ua, _MM_SHUFFLE(2, 2, 0, 0));
00370 __m128 imaga = _mm_shuffle_ps(ua, ua, _MM_SHUFFLE(3, 3, 1, 1));
00371 __m128 t1 = _mm_mul_ps(reala, ub);
00372 __m128 sb = _mm_shuffle_ps(ub, ub, _MM_SHUFFLE(2, 3, 0, 1));
00373 __m128 t2 = _mm_mul_ps(imaga, sb);
00374 #if defined __SSE2__ && !defined __SSE3__
00375 t2 = _mm_xor_ps(t2, neg);
00376 __m128 res = _mm_add_ps(t1, t2);
00377 #else
00378 __m128 res = _mm_addsub_ps(t1, t2);
00379 #endif
00380 _mm_store_ps((float *)&a[i], res);
00381 }
00382
00383 if ((Nt) % 2 == 1)
00384 a[Nt - 1] = a[Nt - 1] * b[Nt - 1];
00385
00386
00387 const cpl_mask * bpm1 = cpl_image_get_bpm_const(im1);
00388 const cpl_mask * bpm2 = cpl_image_get_bpm_const(im2);
00389 if (bpm2 != NULL) {
00390 if (bpm1 == NULL)
00391 cpl_image_reject_from_mask(im1, bpm2);
00392 else {
00393 cpl_mask_or(cpl_image_get_bpm(im1), bpm2);
00394 }
00395 }
00396
00397 } else
00398 #endif
00399 cpl_image_multiply(im1, im2);
00400
00401 return CPL_ERROR_NONE;
00402 }
00403
00404
00415
00416 double visir_image_get_mean_fast(const cpl_image * im)
00417 {
00418 if (im == NULL || cpl_image_get_type(im) != CPL_TYPE_FLOAT) {
00419 return cpl_image_get_mean(im);
00420 }
00421 else {
00422 const size_t npix = cpl_image_get_size_x(im) *
00423 cpl_image_get_size_y(im);
00424 const float * data = cpl_image_get_data_float_const(im);
00425 const size_t nbad = cpl_image_count_rejected(im);
00426
00427
00428 double sum1 = 0;
00429 double sum2 = 0;
00430 double sum3 = 0;
00431 double sum4 = 0;
00432 if (nbad == 0) {
00433 size_t i;
00434 for (i = 0; i < npix - (npix % 4u); i+=4) {
00435 sum1 += data[i];
00436 sum2 += data[i + 1];
00437 sum3 += data[i + 2];
00438 sum4 += data[i + 3];
00439 }
00440 for (; i < npix; i++) {
00441 sum1 += data[i];
00442 }
00443 }
00444 else if (nbad == npix) {
00445 return 0.;
00446 }
00447 else {
00448 size_t i;
00449 const cpl_binary * m =
00450 cpl_mask_get_data_const(cpl_image_get_bpm_const(im));
00451 for (i = 0; i < npix - (npix % 4u); i+=4) {
00452 if (!m[i])
00453 sum1 += data[i];
00454 if (!m[i + 1])
00455 sum2 += data[i + 1];
00456 if (!m[i + 2])
00457 sum3 += data[i + 2];
00458 if (!m[i + 3])
00459 sum4 += data[i + 3];
00460 }
00461 for (; i < npix; i++) {
00462 if (!m[i])
00463 sum1 += data[i];
00464 }
00465 }
00466 return (sum1 + sum2 + sum3 + sum4) / (npix - nbad);
00467 }
00468 }
00469
00470
00471
00479
00480 int visir_cmp_frm_fn(const cpl_frame * a, const cpl_frame * b)
00481 {
00482 const char * fna = cpl_frame_get_filename(a);
00483 const char * fnb = cpl_frame_get_filename(b);
00484
00485 return strcmp(fna, fnb);
00486 }
00487
00488
00497
00498 cpl_error_code visir_move_products(cpl_frameset *frames,
00499 const char * dest_, const char * src_)
00500 {
00501 const char * dest = dest_ ? dest_ : ".";
00502 const char * src = src_ ? src_ : ".";
00503
00504 FOR_EACH_FRAMESET(frm, frames) {
00505 if (cpl_frame_get_group(frm) == CPL_FRAME_GROUP_PRODUCT) {
00506 char * buf = cpl_strdup(cpl_frame_get_filename(frm));
00507 char * new_fn = cpl_sprintf("%s/%s", dest, basename(buf));
00508 cpl_free(buf);
00509
00510 buf = cpl_sprintf("mv \"%s/%s\" \"%s\"", src,
00511 cpl_frame_get_filename(frm), new_fn);
00512 if (WEXITSTATUS(system(buf)) != 0) {
00513 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00514 "Could not move %s/%s to %s", src,
00515 cpl_frame_get_filename(frm), new_fn);
00516 cpl_free(buf);
00517 cpl_free(new_fn);
00518 skip_if(0);
00519 }
00520
00521
00522
00523 cpl_free(buf);
00524 cpl_free(new_fn);
00525 skip_if(0);
00526 }
00527
00528 if (cpl_frame_get_group(frm) == CPL_FRAME_GROUP_RAW ||
00529 cpl_frame_get_group(frm) == CPL_FRAME_GROUP_CALIB) {
00530 if (strncmp(cpl_frame_get_filename(frm), "../", 3) != 0) {
00531 continue;
00532 }
00533 char * buf = cpl_strdup(cpl_frame_get_filename(frm));
00534 cpl_frame_set_filename(frm, buf + 3);
00535 cpl_free(buf);
00536 }
00537 }
00538
00539 end_skip;
00540
00541 return cpl_error_get_code();
00542 }
00543
00544
00545
00554
00555 cpl_parameter * visir_parameter_duplicate(const cpl_parameter * p)
00556 {
00557 cpl_parameter * np = NULL;
00558
00559 cpl_ensure(p != NULL, CPL_ERROR_NULL_INPUT, NULL);
00560 cpl_ensure(cpl_parameter_get_class(p) == CPL_PARAMETER_CLASS_VALUE,
00561 CPL_ERROR_UNSUPPORTED_MODE, NULL);
00562
00563 switch (cpl_parameter_get_type(p)) {
00564 case CPL_TYPE_BOOL:
00565 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
00566 cpl_parameter_get_type(p),
00567 cpl_parameter_get_help(p),
00568 cpl_parameter_get_context(p),
00569 cpl_parameter_get_default_bool(p));
00570 cpl_parameter_set_bool(np, cpl_parameter_get_bool(p));
00571 break;
00572
00573 case CPL_TYPE_INT:
00574 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
00575 cpl_parameter_get_type(p),
00576 cpl_parameter_get_help(p),
00577 cpl_parameter_get_context(p),
00578 cpl_parameter_get_default_int(p));
00579 cpl_parameter_set_int(np, cpl_parameter_get_int(p));
00580 break;
00581
00582 case CPL_TYPE_DOUBLE:
00583 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
00584 cpl_parameter_get_type(p),
00585 cpl_parameter_get_help(p),
00586 cpl_parameter_get_context(p),
00587 cpl_parameter_get_default_double(p));
00588 cpl_parameter_set_double(np, cpl_parameter_get_double(p));
00589 break;
00590
00591 case CPL_TYPE_STRING:
00592 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
00593 cpl_parameter_get_type(p),
00594 cpl_parameter_get_help(p),
00595 cpl_parameter_get_context(p),
00596 cpl_parameter_get_default_string(p));
00597 cpl_parameter_set_string(np, cpl_parameter_get_string(p));
00598 break;
00599
00600 default:
00601 cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
00602 "Parameter has unknown type");
00603 break;
00604 }
00605
00606 if (np == NULL)
00607 return NULL;
00608
00609 if (cpl_parameter_get_tag(p))
00610 cpl_parameter_set_tag(np, cpl_parameter_get_tag(p));
00611
00612 {
00613 cpl_parameter_mode modes[] = {CPL_PARAMETER_MODE_CLI,
00614 CPL_PARAMETER_MODE_CFG, CPL_PARAMETER_MODE_ENV};
00615
00616 for (size_t i = 0; i < ARRAY_LEN(modes); i++) {
00617 cpl_parameter_set_alias(np, modes[i],
00618 cpl_parameter_get_alias(p, modes[i]));
00619 if (!cpl_parameter_is_enabled(p, modes[i]))
00620 cpl_parameter_disable(np, modes[i]);
00621 }
00622 }
00623
00624 return np;
00625 }
00626
00627
00628
00639
00640 cpl_error_code visir_copy_parameters(cpl_parameterlist * dest,
00641 const cpl_parameterlist * src)
00642 {
00643 for (const cpl_parameter * p = cpl_parameterlist_get_first_const(src);
00644 p != NULL; p = cpl_parameterlist_get_next_const(src)) {
00645 cpl_parameter * par =
00646 cpl_parameterlist_find(dest, cpl_parameter_get_name(p));
00647
00648 if (!par)
00649 continue;
00650
00651 cpl_type t = cpl_parameter_get_type(par);
00652 if (t == CPL_TYPE_BOOL)
00653 cpl_parameter_set_bool(par, cpl_parameter_get_bool(p));
00654 else if (t == CPL_TYPE_INT)
00655 cpl_parameter_set_int(par, cpl_parameter_get_int(p));
00656 else if (t == CPL_TYPE_DOUBLE)
00657 cpl_parameter_set_double(par, cpl_parameter_get_double(p));
00658 else if (t == CPL_TYPE_STRING)
00659 cpl_parameter_set_string(par, cpl_parameter_get_string(p));
00660 else
00661 bug_if(1);
00662 }
00663
00664 end_skip;
00665
00666 return cpl_error_get_code();
00667 }
00668
00669
00670
00679
00680 cpl_recipe *
00681 visir_init_recipe(const char * name, int (*get_info)(cpl_pluginlist *),
00682 cpl_pluginlist * plugins)
00683 {
00684 cpl_recipe * recipe = cpl_calloc(1, sizeof(cpl_recipe));
00685 get_info(plugins);
00686 cpl_plugin * pl = cpl_pluginlist_find (plugins, name);
00687 cpl_plugin_copy ((cpl_plugin *) & recipe->interface, pl);
00688 return recipe;
00689 }
00690
00691
00692
00703
00704 cpl_error_code
00705 visir_run_recipe(cpl_recipe * recipe,
00706 cpl_frameset * framelist, const cpl_parameterlist * parlist,
00707 cpl_error_code (*set_parlist)(cpl_parameterlist *,
00708 const cpl_parameterlist *))
00709 {
00710 cpl_plugin * pl = &recipe->interface;
00711 cpl_plugin_func plugin_func_init = cpl_plugin_get_init(pl);
00712 cpl_plugin_func plugin_func_exec = cpl_plugin_get_exec(pl);
00713 cpl_plugin_func plugin_func_deinit = cpl_plugin_get_deinit(pl);
00714
00715 skip_if(0);
00716
00717 recipe->frames = framelist;
00718
00719
00720 if (getenv("VISIR_TEST_MODE")) {
00721 char * buf = cpl_sprintf("%s.sof", cpl_plugin_get_name(pl));
00722 FILE * f = fopen(buf, "wt");
00723 cpl_free(buf);
00724 FOR_EACH_FRAMESET(frm, framelist) {
00725 fprintf(f, "%s %s\n", cpl_frame_get_filename(frm), cpl_frame_get_tag(frm));
00726 }
00727 fclose(f);
00728 }
00729
00730
00731 cpl_fits_set_mode(CPL_FITS_RESTART_CACHING);
00732
00733 plugin_func_init(&recipe->interface);
00734 if (set_parlist)
00735 set_parlist(recipe->parameters, parlist);
00736 plugin_func_exec(&recipe->interface);
00737 plugin_func_deinit(&recipe->interface);
00738
00739 end_skip;
00740
00741 cpl_fits_set_mode(CPL_FITS_RESTART_CACHING);
00742
00743 return cpl_error_get_code();
00744 }
00745
00746
00747
00763
00764 cpl_frameset *
00765 visir_prepare_frameset(const cpl_frameset * frameset,
00766 const char ** tagmap, size_t ntags,
00767 cpl_boolean reverse)
00768 {
00769 cpl_frameset * nlist = cpl_frameset_new();
00770 cx_list * _nlist = cx_list_new();
00771 cpl_ensure(ntags % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, nlist);
00772
00773 FOR_EACH_FRAMESET_C(frame, frameset) {
00774 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_PRODUCT) {
00775 cpl_frame * frm = cpl_frame_duplicate(frame);
00776 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
00777 cpl_frame_set_level(frm, CPL_FRAME_LEVEL_NONE);
00778 for (size_t i = 0; i < ntags; i += 2)
00779 if (strcmp(tagmap[i], cpl_frame_get_tag(frm)) == 0)
00780 cpl_frame_set_tag(frm, tagmap[i + 1]);
00781
00782 cx_list_push_back(_nlist, frm);
00783 }
00784 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB)
00785 cx_list_push_back(_nlist, cpl_frame_duplicate(frame));
00786 }
00787
00788 cx_list_sort(_nlist, (cx_compare_func)visir_cmp_frm_fn);
00789 if (reverse) {
00790 cx_list_reverse(_nlist);
00791 }
00792
00793 FOR_EACH(it, _nlist)
00794 cpl_frameset_insert(nlist, cx_list_get(_nlist, it));
00795 cx_list_delete(_nlist);
00796
00797 return nlist;
00798 }
00799
00800
00809
00810 cpl_frameset * visir_remove_modified_calib(cpl_frameset * set)
00811 {
00812 cpl_frameset * cleanset = cpl_frameset_new();
00813 FOR_EACH_FRAMESET(frame, set) {
00814 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB &&
00815 strcmp(cpl_frame_get_tag(frame),
00816 "STATIC_MASK") == 0) {
00817 continue;
00818 }
00819 cpl_frameset_insert(cleanset, cpl_frame_duplicate(frame));
00820 }
00821 cpl_frameset_delete(set);
00822
00823 return cleanset;
00824 }
00825
00826
00827
00836
00837 static cpl_frameset *
00838 visir_wait_for_child(pid_t pid, FILE * rpipe)
00839 {
00840 char * rbuffer = NULL;
00841 int status;
00842 cpl_error_code err;
00843 size_t size;
00844 cpl_frameset * result = NULL;
00845
00846
00847
00848
00849 cpl_ensure(rpipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
00850 skip_if(fread(&err, sizeof(err), 1, rpipe) != 1);
00851 cpl_error_set(cpl_func, err);
00852
00853 skip_if(fread(&size, sizeof(size), 1, rpipe) != 1);
00854
00855 rbuffer = cpl_malloc(size);
00856 skip_if(fread(rbuffer, size, 1, rpipe) != 1);
00857
00858 result = visir_frameset_deserialize(rbuffer, NULL);
00859
00860 end_skip;
00861
00862
00863 if (waitpid(pid, &status, 0) != pid) {
00864 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00865 "%s", strerror(errno));
00866 }
00867 else if (WIFSIGNALED(status)) {
00868 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00869 "Process killed by signal %d", WTERMSIG(status));
00870 }
00871 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
00872 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
00873 "Process failed with code %d",
00874 WEXITSTATUS(status));
00875 }
00876 else
00877 assert(1);
00878
00879 cpl_free(rbuffer);
00880
00881 return result;
00882 }
00883
00884
00892
00893 static void
00894 remove_tempdir(const cpl_parameterlist * parlist, const char* recipename,
00895 const char * tmpdir)
00896 {
00897 const cpl_boolean delete =
00898 irplib_parameterlist_get_bool(parlist, PACKAGE,
00899 recipename, "delete-temp");
00900
00901 if (delete) {
00902 char * cmd = cpl_sprintf("rm -rf \"%s\"", tmpdir);
00903 cpl_msg_info(cpl_func, "Removing temporary directory: %s", tmpdir);
00904 if (WEXITSTATUS(system(cmd)) != 0)
00905 cpl_msg_warning(cpl_func, "Removing temporary "
00906 "directory %s failed", tmpdir);
00907 cpl_free(cmd);
00908 }
00909 else
00910 cpl_msg_info(cpl_func, "Keeping temporary directory: %s", tmpdir);
00911 }
00912
00913
00922
00923 cpl_error_code
00924 visir_tmpdir_exec(const char * recipename, cpl_plugin * plugin,
00925 int (*function)(cpl_frameset *, const cpl_parameterlist *))
00926 {
00927 char tmpdir[strlen(recipename) + 8];
00928 cpl_boolean have_tmpdir = CPL_FALSE;
00929 cpl_errorstate cleanstate = cpl_errorstate_get();
00930 cpl_recipe * recipe = (cpl_recipe *)plugin;
00931 sprintf(tmpdir, "%s_XXXXXX", recipename);
00932
00933 have_tmpdir = visir_get_tempdir(tmpdir);
00934 skip_if(have_tmpdir != CPL_TRUE);
00935
00936 cpl_msg_info(cpl_func, "Working in temporary directory: %s", tmpdir);
00937
00938
00939 if (chdir(tmpdir) != 0) {
00940 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00941 "Could not change to temporary directory %s", tmpdir);
00942 }
00943
00944
00945 FOR_EACH_FRAMESET(frm, recipe->frames) {
00946 if (cpl_frame_get_filename(frm)[0] != '/') {
00947 char * buf = cpl_sprintf("../%s", cpl_frame_get_filename(frm));
00948 cpl_frame_set_filename(frm, buf);
00949 cpl_free(buf);
00950 }
00951 }
00952
00953 cpl_recipedefine_exec(plugin, function);
00954
00955 if (chdir("..") != 0) {
00956 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
00957 "Could not change back to base directory");
00958 }
00959
00960
00961 skip_if(visir_move_products(recipe->frames, ".", tmpdir));
00962
00963 end_skip;
00964
00965 if (have_tmpdir) {
00966 remove_tempdir(recipe->parameters, recipename, tmpdir);
00967 }
00968
00969 if (!cpl_errorstate_is_equal(cleanstate))
00970 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
00971
00972 return cpl_error_get_code();
00973 }
00974
00975
00976
00985
00986 cpl_error_code
00987 visir_forking_exec(const char * recipename, cpl_plugin * plugin,
00988 int (*function)(cpl_frameset *, const cpl_parameterlist *))
00989 {
00990 char tmpdir[strlen(recipename) + 8];
00991 cpl_boolean have_tmpdir = CPL_FALSE;
00992 cpl_errorstate cleanstate = cpl_errorstate_get();
00993 cpl_recipe * recipe = (cpl_recipe *)plugin;
00994 FILE * pipe_stream = NULL;
00995 int pipe_fd[2];
00996 static const int READ = 0, WRITE = 1;
00997 sprintf(tmpdir, "%s_XXXXXX", recipename);
00998
00999
01000 struct sigaction sa, sa_orig;
01001 sa.sa_handler = SIG_IGN;
01002 sigemptyset(&sa.sa_mask);
01003 sa.sa_flags = 0;
01004 skip_if(sigaction(SIGINT, &sa, &sa_orig) != 0);
01005
01006 have_tmpdir = visir_get_tempdir(tmpdir);
01007 skip_if(have_tmpdir != CPL_TRUE);
01008
01009 cpl_msg_info(cpl_func, "Working in temporary directory: %s", tmpdir);
01010
01011 skip_if(pipe(pipe_fd) != 0);
01012
01013 pid_t pid = fork();
01014 if (pid == -1) {
01015 close(pipe_fd[READ]);
01016 close(pipe_fd[WRITE]);
01017 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
01018 "fork failed: %s", strerror(errno));
01019 skip_if(0);
01020 }
01021 else if (pid == 0) {
01022
01023 sigaction(SIGINT, &sa_orig, NULL);
01024
01025
01026 close(pipe_fd[READ]);
01027 pipe_stream = fdopen(pipe_fd[WRITE], "w");
01028
01029
01030 if (!pipe_stream || chdir(tmpdir) != 0) {
01031 close(pipe_fd[WRITE]);
01032 _exit(EXIT_FAILURE);
01033 }
01034
01035
01036 FOR_EACH_FRAMESET(frm, recipe->frames) {
01037 if (cpl_frame_get_filename(frm)[0] != '/') {
01038 char * buf = cpl_sprintf("../%s", cpl_frame_get_filename(frm));
01039 cpl_frame_set_filename(frm, buf);
01040 cpl_free(buf);
01041 }
01042 }
01043
01044 cpl_error_code err = cpl_recipedefine_exec(plugin, function)
01045 ? (int)cpl_error_set_where(cpl_func) : 0;
01046
01047 if (err == CPL_ERROR_NONE) {
01048 assert((void*)recipe == (void*)plugin);
01049 err = visir_send_frameset(pipe_stream, recipe->frames);
01050 }
01051 fclose(pipe_stream);
01052 _exit(err);
01053 }
01054 else {
01055
01056 close(pipe_fd[WRITE]);
01057 pipe_stream = fdopen(pipe_fd[READ], "r");
01058 skip_if(pipe_stream == NULL);
01059
01060 recipe->frames = visir_wait_for_child(pid, pipe_stream);
01061 fclose(pipe_stream);
01062 skip_if(recipe->frames == NULL);
01063
01064
01065 skip_if(visir_move_products(recipe->frames, ".", tmpdir));
01066 }
01067
01068 end_skip;
01069
01070 if (have_tmpdir) {
01071 remove_tempdir(recipe->parameters, recipename, tmpdir);
01072 }
01073
01074 if (!cpl_errorstate_is_equal(cleanstate))
01075 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
01076
01077 return cpl_error_get_code();
01078 }
01079
01080
01088
01089 double visir_utils_get_exptime(const int nnod, const cpl_propertylist * plist)
01090 {
01091
01092
01093 const double dit = visir_pfits_get_dit(plist);
01094
01095 const int ndit = visir_pfits_get_ndit(plist);
01096
01097 const int navrg = visir_pfits_get_navrg(plist);
01098
01099 const int ncycles = visir_pfits_get_chop_ncycles(plist);
01100
01101
01102 const double value = 2 * dit * ndit * nnod * ncycles * navrg;
01103
01104 if (value <= 0) {
01105 cpl_msg_error(cpl_func, "Illegal exposure time "
01106 "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
01107 dit, ndit, ncycles, nnod, value);
01108 skip_if(1);
01109 }
01110
01111 end_skip;
01112 return value;
01113 }
01114
01115
01124
01125 double * visir_utils_get_wls(const irplib_framelist * self)
01126 {
01127
01128 const int size = irplib_framelist_get_size(self);
01129 double * wls = NULL;
01130 int i;
01131
01132
01133 skip_if (0);
01134
01135 skip_if(irplib_framelist_contains(self, VISIR_PFITS_DOUBLE_MONOC_POS,
01136 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
01137
01138
01139 wls = cpl_malloc(size * sizeof(double));
01140
01141
01142 for (i=0; i < size; i++) {
01143 const cpl_propertylist * plist
01144 = irplib_framelist_get_propertylist_const(self, i);
01145
01146 wls[i] = visir_pfits_get_monoc_pos(plist);
01147
01148 skip_if (0);
01149 }
01150
01151 end_skip;
01152
01153 if (cpl_error_get_code()) {
01154 cpl_free(wls);
01155 wls = NULL;
01156 }
01157
01158 return wls;
01159 }
01160
01161
01171
01172 cpl_image * visir_create_disk_intimage(
01173 int nx,
01174 int ny,
01175 int x_pos,
01176 int y_pos,
01177 int radius)
01178 {
01179 cpl_image * intima;
01180 int * pintima;
01181 double dist;
01182 int i, j;
01183
01184
01185 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
01186 pintima = cpl_image_get_data_int(intima);
01187
01188
01189 for (j=0;j<ny ; j++) {
01190 for (i=0;i<nx ; i++) {
01191 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
01192 if (dist < radius*radius) {
01193 pintima[i+j*nx] = 1;
01194 } else {
01195 pintima[i+j*nx] = 0;
01196 }
01197 }
01198 }
01199 return intima;
01200 }
01201
01202
01213
01214 cpl_image * visir_create_ring_intimage(
01215 int nx,
01216 int ny,
01217 int x_pos,
01218 int y_pos,
01219 int radius1,
01220 int radius2)
01221 {
01222 cpl_image * intima;
01223 int * pintima;
01224 double dist;
01225 if (radius1 >= radius2) {
01226 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01227 "Small ring radius %d larger than big "
01228 "ring radius %d", radius1, radius2);
01229 return NULL;
01230 }
01231 if ((nx - x_pos) < radius2 || x_pos < radius2 ||
01232 (ny - y_pos) < radius2 || y_pos < radius2) {
01233 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01234 "Image of size [%d,%d] with object at "
01235 "[%d,%d] too small to create ring mask of "
01236 "radius %d", nx, ny, x_pos, y_pos, radius2);
01237 return NULL;
01238 }
01239
01240
01241 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
01242 pintima = cpl_image_get_data_int(intima);
01243
01244
01245 for (int j=0;j<ny ; j++) {
01246 for (int i=0;i<nx ; i++) {
01247 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
01248 if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
01249 pintima[i+j*nx] = 1;
01250 } else {
01251 pintima[i+j*nx] = 0;
01252 }
01253 }
01254 }
01255 return intima;
01256 }
01257
01258
01269
01270 double visir_image_sigma_clip(const cpl_image * self, double * pstdev)
01271 {
01272 const int dimx = cpl_image_get_size_x(self);
01273 const int dimy = cpl_image_get_size_y(self);
01274 const cpl_type type = cpl_image_get_type(self);
01275
01276
01277 cpl_image * noise = cpl_image_new(dimx, dimy, type);
01278 cpl_mask * bpm = NULL;
01279 cpl_mask * kernel = cpl_mask_new(3, 3);
01280 const int niterations = 5;
01281 const double sigma = 3.0;
01282 const double median_corr = 0.94;
01283 double bgnoise = -1;
01284 int i = -1;
01285
01286
01287 bug_if (0);
01288
01289 bug_if(cpl_mask_not(kernel));
01290 bug_if(cpl_image_filter_mask(noise, self, kernel, CPL_FILTER_MEDIAN,
01291 CPL_BORDER_FILTER));
01292
01293
01294 bug_if (cpl_image_subtract(noise, self));
01295
01296 for (i=0; i < niterations ; i++) {
01297
01298 cpl_stats * stats =
01299 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
01300
01301 const double mean = cpl_stats_get_mean(stats);
01302 const double stdev = cpl_stats_get_stdev(stats);
01303
01304
01305 const double low_thresh = mean - sigma * stdev;
01306 const double high_thresh = mean + sigma * stdev;
01307
01308
01309 cpl_stats_delete(stats);
01310
01311
01312 skip_if (0);
01313
01314
01315 bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
01316
01317 bug_if (0);
01318
01319 bug_if (cpl_mask_not(bpm));
01320
01321 bug_if (cpl_image_reject_from_mask(noise, bpm));
01322
01323 cpl_mask_delete(bpm);
01324 bpm = NULL;
01325
01326 }
01327
01328 if (pstdev != NULL) {
01329
01330
01331 cpl_stats * stats =
01332 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
01333
01334
01335 bgnoise = cpl_stats_get_stdev(stats);
01336 *pstdev = cpl_image_get_median(self) - cpl_stats_get_mean(stats);
01337
01338 cpl_stats_delete(stats);
01339 } else {
01340
01341 bgnoise = cpl_image_get_stdev(noise);
01342 }
01343
01344 bug_if(0);
01345
01346 bgnoise /= median_corr;
01347
01348 end_skip;
01349
01350 if (cpl_error_get_code())
01351 cpl_msg_error(cpl_func, "Computation of background noise using sigma=%g"
01352 " failed in iteration %d of %d", sigma, i+1, niterations);
01353
01354 cpl_mask_delete(kernel);
01355 cpl_mask_delete(bpm);
01356 cpl_image_delete(noise);
01357
01358 return bgnoise;
01359 }
01360
01361
01371
01372 double visir_img_phot_sigma_clip(const cpl_image * self)
01373 {
01374
01375 const double noise = visir_image_sigma_clip(self, NULL);
01376
01377 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
01378
01379 return noise;
01380
01381 }
01382
01383
01401
01402 int visir_star_find(const cpl_vector * v_ra, const cpl_vector * v_dec,
01403 double ra, double dec, double maxdist, double * pdist)
01404 {
01405 const int nra = cpl_vector_get_size(v_ra);
01406 const int ndec = cpl_vector_get_size(v_dec);
01407 double dmin = 0.0;
01408 int minind = 0;
01409 int i;
01410
01411
01412
01413 cpl_ensure(nra > 0, cpl_error_get_code(), -2);
01414 cpl_ensure(ndec > 0, cpl_error_get_code(), -3);
01415
01416
01417
01418
01419 cpl_ensure(nra == ndec, CPL_ERROR_INCOMPATIBLE_INPUT, -4);
01420
01421 cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
01422
01423
01424 for (i=0 ; i < nra ; i++) {
01425 const double rai = cpl_vector_get(v_ra, i);
01426 const double deci = cpl_vector_get(v_dec, i);
01427 const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
01428
01429 cpl_msg_debug(cpl_func, "DISTANCE (RAi,DECi)=(%g,%g) <=> "
01430 "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
01431
01432 if (i == 0 || gdist < dmin) {
01433 minind = i;
01434 dmin = gdist;
01435 }
01436 }
01437
01438 if (pdist != NULL) *pdist = dmin;
01439
01440
01441 if (dmin > maxdist) {
01442 cpl_msg_error(cpl_func, "Nearest standard star (%d of %d) at (RA,DEC)="
01443 "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
01444 1+minind, nra, cpl_vector_get(v_ra, minind),
01445 cpl_vector_get(v_dec, minind), ra, dec, dmin, maxdist);
01446 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
01447 }
01448
01449 return minind;
01450 }
01451
01452
01471
01472 cpl_error_code visir_star_convert(const char * line, int ra_hh, int ra_mm,
01473 double ra_ss, char isign, int dec_hh,
01474 int dec_mm, double dec_ss,
01475 const double * jys, int njys,
01476 double * pra, double * pdec)
01477 {
01478
01479 double sign;
01480 int i;
01481
01482 assert( line );
01483 assert( pra );
01484 assert( pdec );
01485 assert( jys );
01486 assert( njys > 0 );
01487
01488
01489 if (isign == '+')
01490 sign = 1.0;
01491 else if (isign == '-')
01492 sign = -1.0;
01493 else {
01494 cpl_msg_error(cpl_func, "Line has illegal declination-sign character "
01495 "(%c): %s", isign, line);
01496 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01497 }
01498
01499 if (ra_hh < 0) {
01500 cpl_msg_error(cpl_func, "Line has negative RA hh (%d): %s",
01501 ra_hh, line);
01502 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01503 }
01504 if (ra_mm < 0) {
01505 cpl_msg_error(cpl_func, "Line has negative RA mm (%d): %s",
01506 ra_hh, line);
01507 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01508 }
01509 if (ra_mm >= 60) {
01510 cpl_msg_error(cpl_func, "Line has too large RA mm (%d): %s ",
01511 ra_mm, line);
01512 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01513 }
01514 if (ra_ss < 0) {
01515 cpl_msg_error(cpl_func, "Line has negative RA ss (%g): %s",
01516 ra_ss, line);
01517 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01518 }
01519 if (ra_ss >= 60) {
01520 cpl_msg_error(cpl_func, "Line has too large RA ss (%g): %s ",
01521 ra_ss, line);
01522 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01523 }
01524
01525 if (dec_hh < 0) {
01526 cpl_msg_error(cpl_func, "Line has negative DEC hh (%d): %s",
01527 dec_hh, line);
01528 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01529 }
01530 if (dec_mm < 0) {
01531 cpl_msg_error(cpl_func, "Line has negative DEC mm (%d): %s",
01532 dec_hh, line);
01533 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01534 }
01535 if (dec_mm >= 60) {
01536 cpl_msg_error(cpl_func, "Line has too large DEC mm (%d): %s ",
01537 dec_mm, line);
01538 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01539 }
01540 if (dec_ss < 0) {
01541 cpl_msg_error(cpl_func, "Line has negative DEC ss (%g): %s",
01542 dec_ss, line);
01543 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01544 }
01545 if (dec_ss >= 60) {
01546 cpl_msg_error(cpl_func, "Line has too large DEC ss (%g): %s ",
01547 dec_ss, line);
01548 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01549 }
01550
01551 *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
01552 if (*pra >= 360.0) {
01553 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
01554 *pra, line);
01555 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01556 }
01557
01558 *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
01559 if (*pdec > 90.0) {
01560 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
01561 *pdec, line);
01562 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01563 }
01564 if (*pdec < -90.0) {
01565 cpl_msg_error(cpl_func, "Line has too small RA (%g): %s ",
01566 *pdec, line);
01567 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01568 }
01569
01570 for (i=0; i < njys; i++) if (jys[i] <= 0.0) {
01571 cpl_msg_error(cpl_func,"Line has non-positive Jy value (%g) at %d: %s ",
01572 jys[i], i+1, line);
01573 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01574 }
01575
01576 return CPL_ERROR_NONE;
01577
01578 }
01579
01580
01593
01594 cpl_table * visir_table_new_xypos(const cpl_imagelist * images,
01595 const char * label)
01596 {
01597 cpl_errorstate cleanstate = cpl_errorstate_get();
01598 const int nsize = cpl_imagelist_get_size(images);
01599 double psigmas[] = {5, 2, 1, 0.5};
01600 cpl_vector * sigmas = NULL;
01601 cpl_table * self = NULL;
01602 const int nsigmas = sizeof(psigmas)/sizeof(double);
01603 int isflux = 0;
01604 int nfail, i;
01605
01606 cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
01607 cpl_ensure(label, CPL_ERROR_NULL_INPUT, NULL);
01608 cpl_ensure(!strcmp(label, "FLUX") || !strcmp(label, "FWHM"),
01609 CPL_ERROR_UNSUPPORTED_MODE, NULL);
01610
01611 self = cpl_table_new(nsize);
01612
01613 skip_if (cpl_table_new_column(self, "X_POS", CPL_TYPE_DOUBLE));
01614 skip_if (cpl_table_new_column(self, "Y_POS", CPL_TYPE_DOUBLE));
01615
01616 if (!strcmp(label,"FLUX")) {
01617 isflux = 1;
01618 skip_if (cpl_table_new_column(self, label, CPL_TYPE_DOUBLE));
01619 } else {
01620 skip_if (cpl_table_new_column(self, "X_FWHM", CPL_TYPE_DOUBLE));
01621 skip_if (cpl_table_new_column(self, "Y_FWHM", CPL_TYPE_DOUBLE));
01622 }
01623
01624 sigmas = cpl_vector_wrap(4, psigmas);
01625 skip_if (sigmas == NULL);
01626
01627 cpl_msg_info(cpl_func, "Detecting apertures using %d sigma-levels "
01628 "ranging from %g down to %g", nsigmas, psigmas[0],
01629 psigmas[nsigmas-1]);
01630
01631
01632 nfail = 0;
01633 for (i=0 ; i < nsize ; i++) {
01634 const cpl_image * image = cpl_imagelist_get_const(images, i);
01635 cpl_apertures * apert;
01636 cpl_size isigma;
01637
01638
01639 double posx = -1;
01640 double posy = -1;
01641 double fwhmx = -1;
01642 double fwhmy = -1;
01643 double flux = -1;
01644 int iflux;
01645
01646 skip_if (0);
01647
01648
01649 apert = cpl_apertures_extract(image, sigmas, &isigma);
01650
01651 if (apert != NULL && cpl_error_get_code()) {
01652
01653 cpl_msg_error(cpl_func, "cpl_apertures_extract() returned non-NULL "
01654 "while setting the CPL error-state to '%s' at '%s'",
01655 cpl_error_get_message(), cpl_error_get_where());
01656 cpl_msg_debug(cpl_func, "Deleting the spurious aperture list at %p:",
01657 (void*)apert);
01658 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
01659 cpl_apertures_dump(apert, stdout);
01660 cpl_apertures_delete(apert);
01661 apert = NULL;
01662 }
01663
01664 if (apert != NULL &&
01665 !irplib_apertures_find_max_flux(apert, &iflux, 1) &&
01666 cpl_apertures_get_flux(apert, iflux) > 0) {
01667
01668 posx = cpl_apertures_get_centroid_x(apert, iflux);
01669 posy = cpl_apertures_get_centroid_y(apert, iflux);
01670 flux = cpl_apertures_get_flux(apert, iflux);
01671 if (!isflux)
01672 cpl_image_get_fwhm(image, (int)posx, (int)posy, &fwhmx, &fwhmy);
01673
01674 cpl_msg_info(cpl_func, "Detected an aperture with flux=%g at "
01675 "sigma=%g, at position: %g %g", flux,
01676 psigmas[isigma], posx, posy);
01677 }
01678
01679 if (apert == NULL || cpl_error_get_code()) {
01680 visir_error_reset("Aperture detection in image %d of %d failed",
01681 i+1, nsize);
01682 nfail++;
01683 } else if (flux <= 0) {
01684 cpl_msg_warning(cpl_func, "Ignoring %d-pixel aperture %d (out of "
01685 "%d) in file %d of %d with non-positive flux: %g",
01686 (int)cpl_apertures_get_npix(apert, iflux), iflux,
01687 (int)cpl_apertures_get_size(apert), i+1, nsize,
01688 flux);
01689 nfail++;
01690 }
01691
01692 cpl_apertures_delete(apert);
01693 apert = NULL;
01694
01695 skip_if (cpl_table_set_double(self, "X_POS", i, posx));
01696 skip_if (cpl_table_set_double(self, "Y_POS", i, posy));
01697
01698 if (isflux)
01699 skip_if (cpl_table_set_double(self, "FLUX", i, flux));
01700 else {
01701 skip_if (cpl_table_set_double(self, "X_FWHM", i, fwhmx));
01702 skip_if (cpl_table_set_double(self, "Y_FWHM", i, fwhmy));
01703 }
01704
01705 }
01706
01707
01708 if (nfail == nsize) {
01709 cpl_msg_error(cpl_func, "Aperture detection failed in all %d images",
01710 nsize);
01711 visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
01712 skip_if(1);
01713 }
01714
01715 end_skip;
01716
01717 cpl_vector_unwrap(sigmas);
01718
01719 if (self && cpl_error_get_code()) {
01720 cpl_table_delete(self);
01721 self = NULL;
01722 }
01723
01724 return self;
01725 }
01726
01727
01734
01735 int visir_vector_minpos(const cpl_vector * v)
01736 {
01737 const double * x = cpl_vector_get_data_const(v);
01738 const int n = cpl_vector_get_size(v);
01739 int minpos = 0;
01740 int i;
01741
01742 cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
01743
01744 for (i = 1; i < n; i++) if (x[i] < x[minpos]) minpos = i;
01745
01746 return minpos;
01747 }
01748
01749
01764
01765 cpl_error_code visir_bivector_load(cpl_bivector * self, FILE * stream)
01766 {
01767 cpl_vector * v1;
01768 cpl_vector * v2;
01769 int np = 0;
01770 int xsize, ysize;
01771 char line[1024];
01772
01773 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
01774 cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
01775
01776
01777 v1 = cpl_bivector_get_x(self);
01778 v2 = cpl_bivector_get_y(self);
01779
01780 xsize = cpl_vector_get_size(v1);
01781 ysize = cpl_vector_get_size(v2);
01782
01783 while (fgets(line, 1024, stream) != NULL) {
01784 double x, y;
01785 if (line[0] != '#' && sscanf(line, "%lg %lg", &x, &y) == 2) {
01786
01787
01788
01789
01790 if (np == xsize) {
01791 xsize *= 2;
01792 cpl_vector_set_size(v1, xsize);
01793 }
01794 if (np == ysize) {
01795 ysize *= 2;
01796 cpl_vector_set_size(v2, ysize);
01797 }
01798 cpl_vector_set(v1, np, x);
01799 cpl_vector_set(v2, np, y);
01800 np++;
01801 }
01802 }
01803
01804
01805 cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
01806
01807
01808 if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
01809 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
01810 }
01811
01812 return CPL_ERROR_NONE;
01813
01814 }
01815
01816
01829
01830 double visir_star_dist_min(const double * pras, const double * pdecs, int nloc,
01831 int * piloc1, int * piloc2)
01832 {
01833
01834 int i, j;
01835 double dmin = 180;
01836
01837
01838 assert( pras != NULL);
01839 assert( pdecs != NULL);
01840 assert( piloc1 != NULL);
01841 assert( piloc2 != NULL);
01842 assert( nloc > 0 );
01843
01844 for (j = 0; j < nloc; j++) {
01845 for (i = 0; i < j; i++) {
01846 const double dist = visir_great_circle_dist(pras[i], pdecs[i],
01847 pras[j], pdecs[j]);
01848 if (dist < dmin) {
01849 dmin = dist;
01850 *piloc1 = i;
01851 *piloc2 = j;
01852 }
01853 if (dist < VISIR_STAR_MAX_RADIUS)
01854 cpl_msg_warning(cpl_func,"The two stars (%d,%d) have a distance"
01855 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
01856 }
01857 }
01858
01859 return dmin;
01860 }
01861
01862
01863
01877
01878 const char ** visir_framelist_set_tag(irplib_framelist * self,
01879 char * (*pftag)(const cpl_frame *,
01880 const cpl_propertylist *,
01881 int),
01882 int *pntags)
01883 {
01884
01885
01886
01887 const char ** taglist = NULL;
01888 int iframe, size;
01889
01890 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01891 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
01892 cpl_ensure(pftag != NULL, CPL_ERROR_NULL_INPUT, NULL);
01893 cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
01894
01895 size = irplib_framelist_get_size(self);
01896
01897 cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
01898
01899 *pntags = 0;
01900
01901 for (iframe = 0; iframe < size ; iframe++) {
01902 cpl_frame * frame = irplib_framelist_get(self, iframe);
01903 const cpl_propertylist * plist
01904 = irplib_framelist_get_propertylist_const(self, iframe);
01905 char * tag;
01906 const char * newtag;
01907 int i;
01908
01909
01910
01911 cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
01912 cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
01913
01914 tag = (*pftag)(frame, plist, iframe);
01915
01916 cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
01917
01918
01919
01920 (void)cpl_frame_set_tag(frame, tag);
01921 cpl_free(tag);
01922
01923 newtag = cpl_frame_get_tag(frame);
01924
01925 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
01926
01927
01928 for (i=0; i < *pntags; i++)
01929 if (strcmp(newtag, taglist[i]) == 0) break;
01930
01931 if (i == *pntags) {
01932
01933
01934 (*pntags)++;
01935 taglist = (const char **)cpl_realloc(taglist, *pntags *
01936 sizeof(const char *));
01937 taglist[i] = newtag;
01938 }
01939
01940 }
01941
01942 return taglist;
01943
01944 }
01945
01946
01956
01957 cpl_error_code visir_qc_append_background(cpl_propertylist * self,
01958 const irplib_framelist * rawframes,
01959 int icol1, int icol2)
01960 {
01961
01962
01963 const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
01964
01965 skip_if (0);
01966
01967 bug_if (cpl_propertylist_append_double(self, "ESO QC BACKGD MEAN",
01968 bg_mean));
01969
01970 end_skip;
01971
01972 return cpl_error_get_code();
01973
01974 }
01975
01976
01977
01986
01987 cpl_error_code visir_qc_append_capa(cpl_propertylist * self,
01988 const irplib_framelist * rawframes)
01989 {
01990
01991 cpl_errorstate cleanstate = cpl_errorstate_get();
01992 const cpl_propertylist * plist
01993 = irplib_framelist_get_propertylist_const(rawframes, 0);
01994 const char * capa;
01995
01996
01997 bug_if (0);
01998
01999 capa = visir_get_capa(plist);
02000
02001 if (cpl_error_get_code()) {
02002
02003
02004 cpl_msg_info(cpl_func, "Could not determine capa");
02005 cpl_errorstate_set(cleanstate);
02006 } else {
02007 bug_if (cpl_propertylist_append_string(self, "ESO QC CAPA", capa));
02008 }
02009
02010 end_skip;
02011
02012 return cpl_error_get_code();
02013
02014 }
02015
02016
02024
02025 cpl_error_code visir_qc_append_filter(cpl_propertylist * self,
02026 const irplib_framelist * rawframes)
02027 {
02028
02029 const cpl_propertylist * plist
02030 = irplib_framelist_get_propertylist_const(rawframes, 0);
02031 const char * value = visir_pfits_get_filter(plist);
02032
02033
02034 skip_if (0);
02035
02036 bug_if (cpl_propertylist_append_string(self, "ESO QC FILTER", value));
02037
02038 end_skip;
02039
02040 return cpl_error_get_code();
02041
02042 }
02043
02044
02052
02053 cpl_error_code visir_qc_append_exptime(cpl_propertylist * self,
02054 const irplib_framelist * rawframes)
02055 {
02056 const cpl_propertylist * plist
02057 = irplib_framelist_get_propertylist_const(rawframes, 0);
02058
02059
02060 const int nnod = irplib_framelist_get_size(rawframes);
02061
02062 const double value = visir_utils_get_exptime(nnod, plist);
02063
02064 skip_if (0);
02065
02066 bug_if (cpl_propertylist_append_double(self, "ESO QC EXPTIME", value));
02067
02068 end_skip;
02069
02070 return cpl_error_get_code();
02071
02072 }
02073
02076
02087
02088 static double visir_great_circle_dist(double ra1, double dec1,
02089 double ra2, double dec2)
02090 {
02091
02092
02093 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
02094 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
02095
02096 dec1 *= CPL_MATH_RAD_DEG;
02097 dec2 *= CPL_MATH_RAD_DEG;
02098
02099 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
02100 * CPL_MATH_DEG_RAD;
02101
02102 }
02103
02104
02117
02118 static double ra_hms2deg(int hh, int mm, double ss)
02119 {
02120 return 15.0 * dec_hms2deg(hh, mm, ss);
02121 }
02122
02123
02135
02136 static double dec_hms2deg(int dd, int mm, double ss)
02137 {
02138 return ((double)ss/60.0 + (double)mm)/60.0 + dd;
02139 }
02140
02141
02154
02155 static double visir_hcycle_background(const irplib_framelist * rawframes,
02156 int icol1, int icol2)
02157 {
02158 cpl_imagelist * iset = NULL;
02159
02160 const int nfiles = irplib_framelist_get_size(rawframes);
02161 double bgsum = 0;
02162 double bgmean = -1;
02163 int nsum = 0;
02164 int i, j;
02165
02166 skip_if (nfiles < 1);
02167
02168 if (icol1 == 0) icol1 = VISIR_BACKGD_START;
02169 if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
02170
02171 cpl_msg_info(cpl_func, "Computing Half-cycle background level from column %d "
02172 "through %d", icol1, icol2);
02173
02174
02175 for (i=0; i < nfiles; i++) {
02176
02177 iset = visir_load_hcycle(rawframes, i);
02178
02179 skip_if (0);
02180
02181 for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
02182 const double median =
02183 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
02184 VISIR_BACKGD_START, icol1,
02185 VISIR_BACKGD_STOP, icol2);
02186
02187 skip_if (0);
02188
02189 if (median != median) {
02190 const cpl_frame * frame = irplib_framelist_get_const(rawframes,
02191 i);
02192
02193 cpl_msg_error(cpl_func, "Image window (%d, %d, %d, %d) "
02194 "(image %d of %d) in %s (frame %d of %d) "
02195 "has NaN median",
02196 VISIR_BACKGD_START, icol1,
02197 VISIR_BACKGD_STOP, icol2,
02198 j+1, (int)cpl_imagelist_get_size(iset),
02199 cpl_frame_get_filename(frame), i+1, nfiles);
02200 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
02201 skip_if(1);
02202 }
02203 bgsum += median;
02204 }
02205 nsum += j;
02206 cpl_imagelist_delete(iset);
02207 iset = NULL;
02208 }
02209
02210
02211 skip_if (nsum < 1);
02212
02213 bgmean = bgsum / nsum;
02214
02215 end_skip;
02216
02217 cpl_imagelist_delete(iset);
02218
02219
02220 return bgmean - VISIR_HCYCLE_OFFSET;
02221 }
02222
02223
02224
02235
02236 cpl_error_code
02237 visir_get_subpixel_maxpos(const cpl_image * img, cpl_size x, cpl_size y,
02238 double * xsub, double * ysub)
02239 {
02240 int bad;
02241 const cpl_size nx = cpl_image_get_size_x(img);
02242 const cpl_size ny = cpl_image_get_size_y(img);
02243
02244 *xsub = 0;
02245 *ysub = 0;
02246 if (x - 1 > 0 && x + 1 <= nx) {
02247 double sub[] = {
02248 cpl_image_get(img, x - 1, y, &bad),
02249 cpl_image_get(img, x - 0, y, &bad),
02250 cpl_image_get(img, x + 1, y, &bad),
02251 };
02252 if (!bad)
02253 *xsub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
02254 }
02255 if (y - 1 > 0 && y + 1 <= ny) {
02256 double sub[] = {
02257 cpl_image_get(img, x, y - 1, &bad),
02258 cpl_image_get(img, x, y - 0, &bad),
02259 cpl_image_get(img, x, y + 1, &bad),
02260 };
02261 if (!bad)
02262 *ysub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
02263 }
02264
02265 return cpl_error_get_code();
02266 }
02267
02268 static inline unsigned long get_msb(unsigned long a)
02269 {
02270
02271 unsigned long msb = 0;
02272 while (a >>= 1) {
02273 msb++;
02274 }
02275 return msb;
02276 }
02277
02278
02287
02288 size_t visir_get_next_regular(size_t a)
02289 {
02290
02291
02292
02293 if (a <= 6)
02294 return a;
02295
02296 if ((a & (a - 1)) == 0)
02297 return a;
02298
02299 if (5 > SIZE_MAX / a)
02300 return a;
02301
02302 size_t match = SIZE_MAX;
02303 size_t p5 = 1;
02304 while(p5 < a) {
02305 size_t p35 = p5;
02306 while (p35 < a) {
02307
02308 size_t quotient = a % p35 != 0 ? a / p35 + 1 : a / p35;
02309
02310 size_t p2 = 2 << get_msb(quotient - 1);
02311
02312 size_t n = p2 * p35;
02313 if (n == a)
02314 return n;
02315 else if (n < match)
02316 match = n;
02317
02318 p35 *= 3;
02319 if (p35 == a)
02320 return p35;
02321 }
02322 if (p35 < match)
02323 match = p35;
02324 p5 *= 5;
02325 if (p5 == a)
02326 return p5;
02327 }
02328 if (p5 < match)
02329 match = p5;
02330 return match;
02331 }
02332
02333 struct _visir_fftx_cache {
02334 int initialized;
02335 cpl_image * template_fft;
02336 double template_stdev;
02337 };
02338
02339 visir_fftx_cache * visir_new_fftx_cache(void)
02340 {
02341 return cpl_calloc(sizeof(visir_fftx_cache), 1);
02342 }
02343
02344 void visir_delete_fftx_cache(visir_fftx_cache * c)
02345 {
02346 irplib_aligned_free(cpl_image_unwrap(c->template_fft));
02347 cpl_free(c);
02348 }
02349
02350
02366
02367 cpl_error_code
02368 visir_fftxcorrelate(const cpl_image * atemplate, const cpl_image * aimg,
02369 cpl_boolean normalize, double * xshift, double * yshift,
02370 double * max_correlation, visir_fftx_cache * cache)
02371 {
02372 const cpl_size Nxi = cpl_image_get_size_x(aimg);
02373 const cpl_size Nyi = cpl_image_get_size_y(aimg);
02374 const cpl_size Nxt = cpl_image_get_size_x(atemplate);
02375 const cpl_size Nyt = cpl_image_get_size_y(atemplate);
02376
02377 const cpl_size Nxe = visir_get_next_regular(Nxi + Nxt - 1);
02378 const cpl_size Nye = visir_get_next_regular(Nyi + Nyt - 1);
02379 cpl_size txshift, tyshift;
02380 double subx = 0, suby = 0;
02381 cpl_image * img = NULL;
02382 cpl_image * zimg = NULL;
02383 cpl_image * ztemp = NULL;
02384 cpl_image * fft1 = NULL;
02385 cpl_image * fft2 = NULL;
02386 cpl_image * res = NULL;
02387 void * buffer;
02388 double template_stdev;
02389
02390 cpl_fft_mode mode = getenv("VISIR_TEST_MODE") ? 0 : CPL_FFT_FIND_MEASURE;
02391
02392 cpl_ensure_code(atemplate != NULL, CPL_ERROR_NULL_INPUT);
02393 cpl_ensure_code(aimg != NULL, CPL_ERROR_NULL_INPUT);
02394
02395 if (cache == NULL || cache->initialized == 0) {
02396
02397 cpl_image * template = NULL;
02398 if (cpl_image_get_type(atemplate) != CPL_TYPE_FLOAT)
02399 template = cpl_image_cast(atemplate, CPL_TYPE_FLOAT);
02400 else
02401 template = cpl_image_duplicate(atemplate);
02402
02403 cpl_image_fill_rejected(template, 0);
02404 if (normalize)
02405 skip_if(cpl_image_subtract_scalar(template,
02406 visir_image_get_mean_fast(template)));
02407 template_stdev = cpl_image_get_stdev(template);
02408
02409 buffer = irplib_aligned_calloc(32, Nxe * Nye, sizeof(float));
02410 ztemp = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
02411
02412
02413
02414 skip_if(cpl_image_flip(template, 1));
02415 skip_if(cpl_image_flip(template, 3));
02416
02417
02418 skip_if(cpl_image_copy(ztemp, template, 1, 1));
02419 cpl_image_delete(template);
02420
02421 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
02422 sizeof(float complex));
02423 fft2 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX,
02424 buffer);
02425 skip_if(cpl_fft_image(fft2, ztemp, CPL_FFT_FORWARD));
02426 if (cache) {
02427 cache->template_fft = fft2;
02428 cache->template_stdev = template_stdev;
02429 cache->initialized = 1;
02430 }
02431 }
02432 else {
02433 fft2 = cache->template_fft;
02434 template_stdev = cache->template_stdev;
02435 error_if(cpl_image_get_type(fft2) != CPL_TYPE_FLOAT_COMPLEX ||
02436 cpl_image_get_size_x(fft2) != Nxe / 2 + 1 ||
02437 cpl_image_get_size_y(fft2) != Nye, CPL_ERROR_ILLEGAL_INPUT,
02438 "Invalid fourier transformed template");
02439 }
02440
02441
02442
02443 buffer = irplib_aligned_calloc(32, Nxe * Nye, sizeof(float));
02444 zimg = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
02445 if (cpl_image_get_type(aimg) != CPL_TYPE_FLOAT)
02446 img = cpl_image_cast(aimg, CPL_TYPE_FLOAT);
02447 else
02448 img = cpl_image_duplicate(aimg);
02449
02450 skip_if(img == NULL);
02451
02452 cpl_image_fill_rejected(img, 0);
02453
02454 if (normalize)
02455 skip_if(cpl_image_subtract_scalar(img,
02456 visir_image_get_mean_fast(img)));
02457
02458
02459 skip_if(cpl_image_copy(zimg, img, 1, 1));
02460
02461 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
02462 sizeof(float complex));
02463 fft1 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX, buffer);
02464
02465 skip_if(cpl_fft_image(fft1, zimg, CPL_FFT_FORWARD | mode));
02466
02467
02468
02469 skip_if(visir_image_multiply_fast(fft1, fft2));
02470
02471 buffer = irplib_aligned_malloc(32, Nxe * Nye * sizeof(float));
02472 res = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
02473 skip_if(cpl_fft_image(res, fft1, CPL_FFT_BACKWARD | CPL_FFT_NOSCALE |
02474 mode));
02475
02476 skip_if(cpl_image_get_maxpos_window(res, Nxt / 2 , Nyt / 2,
02477 Nxt / 2 + Nxi, Nyt / 2 + Nyi,
02478 &txshift, &tyshift));
02479
02480 if (max_correlation != NULL) {
02481 int rej;
02482 *max_correlation = cpl_image_get(res, txshift, tyshift, &rej);
02483
02484 *max_correlation /= Nxe * Nye;
02485
02486 if (normalize) {
02487 double tstd = template_stdev;
02488 int mx = txshift - Nxt;
02489 int my = tyshift - Nyt;
02490 double istd= cpl_image_get_stdev_window(zimg,
02491 CX_MAX(1, mx + 1),
02492 CX_MAX(1, my + 1),
02493 CX_MIN(Nxe, mx + Nxt),
02494 CX_MIN(Nye, my + Nyt));
02495
02496 if (tstd * istd == 0)
02497 *max_correlation = 0;
02498 else
02499 *max_correlation /= (tstd * istd * Nxt * Nyt);
02500
02501 skip_if(0);
02502 }
02503 }
02504 skip_if(visir_get_subpixel_maxpos(res, txshift, tyshift, &subx, &suby));
02505 if (xshift != NULL) {
02506 *xshift = txshift - Nxt + subx;
02507 }
02508 if (yshift != NULL) {
02509 *yshift = tyshift - Nyt + suby;
02510 }
02511
02512 end_skip;
02513
02514 cpl_image_delete(img);
02515 if (cache == NULL)
02516 irplib_aligned_free(cpl_image_unwrap(fft2));
02517 irplib_aligned_free(cpl_image_unwrap(fft1));
02518 irplib_aligned_free(cpl_image_unwrap(zimg));
02519 irplib_aligned_free(cpl_image_unwrap(ztemp));
02520 irplib_aligned_free(cpl_image_unwrap(res));
02521
02522 return cpl_error_get_code();
02523 }
02524
02525
02526
02542
02543 static cx_list *
02544 get_interpolation_points(size_t x, size_t y,
02545 size_t nx_, size_t ny_, cpl_binary *bpm)
02546 {
02547 ssize_t l = -1, r = -1 , u = -1, d = -1;
02548 ssize_t xl = x;
02549 ssize_t xh = x;
02550 ssize_t yl = y;
02551 ssize_t yh = y;
02552 ssize_t nx = (ssize_t)nx_;
02553 ssize_t ny = (ssize_t)ny_;
02554 cx_list * p = cx_list_new();
02555
02556
02557
02558 while (1) {
02559 xl--;
02560 xh++;
02561 yl--;
02562 yh++;
02563
02564 if (l < 0 && xl >= 0 && bpm[IND(xl, y, nx)] == CPL_BINARY_0)
02565 l = xl;
02566 if (r < 0 && xh < nx && bpm[IND(xh, y, nx)] == CPL_BINARY_0)
02567 r = xh;
02568 if (d < 0 && yl >= 0 && bpm[IND(x, yl, nx)] == CPL_BINARY_0)
02569 d = yl;
02570 if (u < 0 && yh < ny && bpm[IND(x, yh, nx)] == CPL_BINARY_0)
02571 u = yh;
02572
02573
02574
02575 if ((l != -1 && r != -1) || (d != -1 && u != -1) ||
02576 (xl < 0 && xh >= nx && yl < 0 && yh >= ny))
02577 break;
02578 }
02579
02580
02581 if (r >= 0)
02582 cx_list_push_back(p, (cxcptr)(IND(r, y, nx)));
02583 if (l >= 0)
02584 cx_list_push_back(p, (cxcptr)(IND(l, y, nx)));
02585 if (u >= 0)
02586 cx_list_push_back(p, (cxcptr)(IND(x, u, nx)));
02587 if (d >= 0)
02588 cx_list_push_back(p, (cxcptr)(IND(x, d, nx)));
02589 return p;
02590 }
02591
02592
02593
02611
02612 cpl_error_code
02613 visir_interpolate_rejected(cpl_image * img, size_t ** ppoints, size_t * n)
02614 {
02615 cpl_mask * mask = cpl_image_get_bpm(img);
02616 float * data = cpl_image_get_data_float(img);
02617 cpl_binary * bpm = cpl_mask_get_data(mask);
02618 const size_t nx = (size_t)cpl_image_get_size_x(img);
02619 const size_t ny = (size_t)cpl_image_get_size_y(img);
02620
02621
02622 skip_if(data == NULL);
02623
02624 if (ppoints == NULL || *ppoints == NULL) {
02625 size_t i = 0;
02626 cpl_binary * found = memchr(bpm, CPL_BINARY_1,
02627 sizeof(cpl_binary) * nx * ny);
02628
02629 size_t * restrict pbpm = cpl_calloc(cpl_image_count_rejected(img) * 6,
02630 sizeof(size_t));
02631
02632 while (found != NULL) {
02633 const size_t ind = found - bpm;
02634 const size_t y = ind / nx;
02635 const size_t x = ind - y * nx;
02636 cx_list * p = get_interpolation_points(x, y, nx, ny, bpm);
02637 cx_list_iterator it = cx_list_begin(p);
02638 const size_t npix = cx_list_size(p);
02639 double sum = 0;
02640
02641 pbpm[i++] = ind;
02642 pbpm[i++] = npix;
02643 assert(pbpm[i - 1] <= 4);
02644
02645 while (it != cx_list_end(p)) {
02646 const size_t lind = (size_t)cx_list_get(p, it);
02647 pbpm[i++] = lind;
02648 sum += data[lind];
02649 it = cx_list_next(p, it);
02650 }
02651 data[ind] = sum / npix;
02652 cx_list_delete(p);
02653
02654 found = memchr(found + 1, CPL_BINARY_1,
02655 sizeof(cpl_binary) * nx * ny - ind - 1);
02656 }
02657 if (ppoints && n) {
02658 *n = i;
02659 *ppoints = pbpm;
02660 }
02661 else
02662 cpl_free(pbpm);
02663 }
02664 else {
02665 const size_t n_ = *n;
02666 size_t * restrict points = *ppoints;
02667 for (size_t i = 0; i < n_;) {
02668 const size_t ind = points[i++];
02669 const size_t m = points[i++];
02670 double sum = 0;
02671 for (size_t j = 0; j < m; j++) {
02672 const size_t lind = points[i++];
02673 sum += data[lind];
02674 }
02675 data[ind] = sum / m;
02676 }
02677 }
02678
02679 cpl_image_accept_all(img);
02680
02681 end_skip;
02682
02683 return cpl_error_get_code();
02684 }
02685
02686 #ifdef _OPENMP
02687 static const cpl_image *
02688 image_const_row_view_create(const cpl_image * img,
02689 cpl_size ly,
02690 cpl_size uy)
02691 {
02692 const size_t dsz = cpl_type_get_sizeof(cpl_image_get_type(img));
02693 const cpl_size nx = cpl_image_get_size_x(img);
02694 const char * d = cpl_image_get_data_const(img);
02695 size_t offset = (ly - 1) * nx;
02696 cpl_size nny = uy - ly + 1;
02697 cpl_image * wimg = cpl_image_wrap(nx, nny, cpl_image_get_type(img),
02698 (char*)d + offset * dsz);
02699
02700 const cpl_mask * omask = cpl_image_get_bpm_const(img);
02701 if (omask) {
02702 cpl_mask * mask = cpl_mask_wrap(nx, nny,
02703 (cpl_binary*)cpl_mask_get_data_const(omask) + offset);
02704 cpl_mask_delete(cpl_image_set_bpm(wimg, mask));
02705 }
02706
02707 return wimg;
02708 }
02709
02710 static void
02711 image_const_row_view_delete(const cpl_image * img)
02712 {
02713 cpl_mask_unwrap(cpl_image_unset_bpm((cpl_image*)(img)));
02714 cpl_image_unwrap((cpl_image *)img);
02715 }
02716 #endif
02717
02718
02725
02726 cpl_image *
02727 visir_parallel_median_collapse(const cpl_imagelist * l)
02728 {
02729 #ifndef _OPENMP
02730 return cpl_imagelist_collapse_median_create(l);
02731 #else
02732 cpl_ensure(l != NULL, CPL_ERROR_NULL_INPUT, NULL);
02733 cpl_ensure(cpl_imagelist_get_size(l) > 0,
02734 CPL_ERROR_ILLEGAL_INPUT, NULL);
02735
02736 const size_t n = cpl_imagelist_get_size(l);
02737 const cpl_image * img = cpl_imagelist_get_const(l, 0);
02738 const size_t ny = cpl_image_get_size_y(img);
02739 const size_t nx = cpl_image_get_size_x(img);
02740 const size_t nthreads = CX_MIN(visir_get_num_threads(CPL_FALSE), ny);
02741 cpl_image * res = cpl_image_new(nx, ny, cpl_image_get_type(img));
02742
02743 cpl_image_get_bpm(res);
02744
02745 OMP_PRAGMA(omp parallel for num_threads(nthreads))
02746 for (size_t j = 0; j < nthreads; j++) {
02747 size_t ylow = j * (ny / nthreads) + 1;
02748 size_t yhigh = (j + 1) * (ny / nthreads);
02749 if (j == nthreads - 1)
02750 yhigh = ny;
02751
02752 cpl_imagelist * view = cpl_imagelist_new();
02753 for (size_t i = 0; i < n; i++) {
02754 const cpl_image * iview =
02755 image_const_row_view_create(cpl_imagelist_get_const(l, i),
02756 ylow, yhigh);
02757 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
02758 cpl_imagelist_set(view, (cpl_image *)iview, i);
02759 IRPLIB_DIAG_PRAGMA_POP;
02760 }
02761
02762
02763 cpl_image * r = cpl_imagelist_collapse_median_create(view);
02764 cpl_image_copy(res, r, 1, ylow);
02765
02766
02767 cpl_image_delete(r);
02768 for (size_t i = 0; i < n; i++) {
02769 image_const_row_view_delete(cpl_imagelist_get(view, i));
02770 }
02771 cpl_imagelist_unwrap(view);
02772 }
02773
02774 return res;
02775 #endif
02776 }
02777
02778
02779
02785
02786 static const char * visir_get_capa(const cpl_propertylist * plist)
02787 {
02788 const char * capa = "Pb with Capa";
02789 const char * sval;
02790 double mean;
02791
02792
02793 skip_if (0);
02794
02795
02796
02797 sval = visir_pfits_get_insmode(plist);
02798 skip_if (0);
02799
02800
02801 if (!strcmp(sval, "IMG")) {
02802
02803 mean = visir_pfits_get_volt1dcta9(plist);
02804 mean += visir_pfits_get_volt1dctb9(plist);
02805 } else if (!strcmp(sval, "SPC") || !strcmp(sval, "SPCIMG")) {
02806
02807 mean = visir_pfits_get_volt2dcta9(plist);
02808 mean += visir_pfits_get_volt2dctb9(plist);
02809 } else
02810 skip_if (1);
02811
02812 skip_if (0);
02813
02814 mean *= 0.5;
02815
02816
02817 if (mean < 1.0) {
02818 capa = "Large Capa";
02819 } else if (mean > 4.5) {
02820 capa = "Small Capa";
02821 }
02822
02823 end_skip;
02824
02825 return capa;
02826 }
02827
02828 #ifdef VISIR_MASK_HAS
02829
02849
02850 static cpl_boolean visir_mask_has(const cpl_mask * self, cpl_binary value,
02851 int ngood)
02852 {
02853 const cpl_binary * pself = cpl_mask_get_data_const(self);
02854 int size = cpl_mask_get_size_x(self)
02855 * cpl_mask_get_size_y(self);
02856 int i;
02857
02858 cpl_ensure(self, CPL_ERROR_NULL_INPUT, CPL_FALSE);
02859 cpl_ensure(ngood >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
02860 cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
02861 cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
02862 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
02863
02864 for (i = 0; i < ngood; i++) {
02865
02866 const cpl_binary * ppos = memchr(pself, value, (size_t)size);
02867 if (ppos == NULL) break;
02868
02869 size -= 1 + (int)(ppos - pself);
02870 pself = 1 + ppos;
02871 }
02872
02873 return i == ngood ? CPL_TRUE : CPL_FALSE;
02874 }
02875 #endif
02876
02877
02878
02884
02885 size_t visir_upper_bound(const cpl_vector * vec, double val)
02886 {
02887 const double * d = cpl_vector_get_data_const(vec);
02888 long count = cpl_vector_get_size(vec);
02889 long first = 0;
02890 while (count > 0)
02891 {
02892 long step = count / 2;
02893 long it = first + step;
02894 if (!(val < d[it])) {
02895 first = it + 1;
02896 count -= step + 1;
02897 }
02898 else
02899 count = step;
02900 }
02901 return first;
02902 }
02903
02904
02905
02911
02912 size_t visir_lower_bound(const cpl_vector * vec, double val)
02913 {
02914 const double * d = cpl_vector_get_data_const(vec);
02915 long count = cpl_vector_get_size(vec);
02916 long first = 0;
02917 while (count > 0)
02918 {
02919 long step = count / 2;
02920 long it = first + step;
02921 if (d[it] < val) {
02922 first = it + 1;
02923 count -= step + 1;
02924 }
02925 else
02926 count = step;
02927 }
02928 return first;
02929 }
02930
02931
02932
02944
02945 cpl_image * visir_linintp_values(const cpl_image * inp, const cpl_bivector * ref)
02946 {
02947 const double * data = cpl_image_get_data_double_const(inp);
02948 const cpl_vector * rx = cpl_bivector_get_x_const(ref);
02949 const cpl_vector * ry = cpl_bivector_get_y_const(ref);
02950 size_t nref = cpl_bivector_get_size(ref);
02951 size_t nx = cpl_image_get_size_x(inp);
02952 size_t ny = cpl_image_get_size_y(inp);
02953 cpl_image * res = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
02954 double * rdata = cpl_image_get_data_double(res);
02955 cpl_ensure(nref >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
02956
02957 for (size_t y = 0; y < ny; y++) {
02958 for (size_t x = 0; x < nx; x++) {
02959 double val = data[y * nx + x];
02960 intptr_t ilo = visir_lower_bound(rx, val);
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978 if (ilo == 0) {
02979 rdata[y * nx + x] = cpl_vector_get(ry, 0);
02980 cpl_image_reject(res, x + 1, y + 1);
02981 }
02982 else if (ilo == (intptr_t)nref) {
02983 rdata[y * nx + x] = cpl_vector_get(ry, nref - 1);
02984 cpl_image_reject(res, x + 1, y + 1);
02985 }
02986 else {
02987 double rx1 = cpl_vector_get(rx, ilo - 1);
02988 double rx2 = cpl_vector_get(rx, ilo);
02989 double ry1 = cpl_vector_get(ry, ilo - 1);
02990 double ry2 = cpl_vector_get(ry, ilo);
02991 double grad = (ry2 - ry1) / (rx2 - rx1);
02992 double y0 = ry1 - grad * rx1;
02993 rdata[y * nx + x] = grad * val + y0;
02994 }
02995 }
02996 }
02997 return res;
02998 }
02999
03000
03019
03020 cpl_error_code
03021 fit_2d_gauss(const cpl_image * img_, const cpl_image * weights, cpl_size x, cpl_size y,
03022 double est_fwhmx, double est_fwhmy,
03023 double * peak, double * peak_err,
03024 double * major, double * major_err,
03025 double * minor, double * minor_err,
03026 double * angle, double * angle_err)
03027 {
03028 cpl_image * img = cpl_image_cast(img_, CPL_TYPE_DOUBLE);
03029 cpl_size llx = CX_MAX(x - est_fwhmx * 3, 1);
03030 cpl_size lly = CX_MAX(y - est_fwhmy * 3, 1);
03031 cpl_size urx = CX_MIN(x + est_fwhmx * 3, cpl_image_get_size_x(img));
03032 cpl_size ury = CX_MIN(y + est_fwhmy * 3, cpl_image_get_size_y(img));
03033 cpl_array * dpar = cpl_array_new(7, CPL_TYPE_DOUBLE);
03034 cpl_array * epar = cpl_array_new(7, CPL_TYPE_DOUBLE);
03035 cpl_matrix * cov = NULL;
03036 cpl_matrix * phys_cov = NULL;
03037
03038 cpl_array_set_double(dpar, 0, cpl_image_get_median(img));
03039 cpl_array_set_double(dpar, 1, cpl_image_get_flux_window(img, llx, lly,
03040 urx, ury));
03041 cpl_array_set_double(dpar, 2, 0.);
03042 cpl_array_set_double(dpar, 3, x);
03043 cpl_array_set_double(dpar, 4, y);
03044 cpl_array_set_double(dpar, 5, est_fwhmx / 2.355);
03045 cpl_array_set_double(dpar, 6, est_fwhmx / 2.355);
03046
03047 cpl_image * err = cpl_image_new(cpl_image_get_size_x(img),
03048 cpl_image_get_size_y(img),
03049 CPL_TYPE_DOUBLE);
03050 cpl_image_add_scalar(err, 1.);
03051 cpl_image_divide(err, weights);
03052 cpl_image_power(err, 0.5);
03053
03054 skip_if(cpl_fit_image_gaussian(img, err,
03055 x,
03056 y,
03057 urx - llx + 1,
03058 ury - lly + 1,
03059 dpar,
03060 epar,
03061 NULL,
03062 NULL,
03063 NULL,
03064 &cov,
03065 major,
03066 minor,
03067 angle,
03068 &phys_cov
03069 ));
03070
03071
03072
03073
03074 if (peak) {
03075 double * a = cpl_array_get_data_double(dpar);
03076 *peak = a[0] + a[1] /
03077 (CPL_MATH_2PI * a[5] * a[6] * sqrt(1.0 - a[2] * a[2]));
03078 if (isnan(*peak)) {
03079 cpl_msg_warning(cpl_func, "2d gaussfit, could not determine peak");
03080 *peak = -1.;
03081 }
03082 }
03083 if (peak_err) {
03084 double * a = cpl_array_get_data_double(dpar);
03085 double * e = cpl_array_get_data_double(epar);
03086 double A = a[1];
03087 double sigx = a[5];
03088 double sigy = a[6];
03089 double rho = a[2];
03090 double dB = sqrt(e[0]);
03091 double dA = sqrt(e[1]);
03092 double dsigx = sqrt(e[5]);
03093 double dsigy = sqrt(e[6]);
03094 double drho = sqrt(e[2]);
03095 double A2 = A * A;
03096 double rho2 = rho * rho;
03097 double xd = CPL_MATH_PI * CPL_MATH_PI * 4 * sigx * sigx * sigy * sigy;
03098 *peak_err =
03099 sqrt(A2 * drho * drho * rho2 /(xd * pow(-rho2 + 1.0, 3)) +
03100 A2 * dsigx * dsigx /(xd * sigx * sigx * (-rho2 + 1.0)) +
03101 A2 * dsigy * dsigy /(xd * sigy * sigy * (-rho2 + 1.0)) +
03102 dA * dA/(xd * (-rho2 + 1.0)) + dB * dB);
03103 if (isnan(*peak_err)) {
03104 *peak_err = -1.;
03105 }
03106 }
03107 if (major) {
03108 *major *= CPL_MATH_FWHM_SIG;
03109 if (isnan(*major)) {
03110 cpl_msg_warning(cpl_func,
03111 "2d gaussfit, could not determine major axis");
03112 *minor = -1.;
03113 }
03114 }
03115 if (minor) {
03116 *minor *= CPL_MATH_FWHM_SIG;
03117 if (isnan(*minor)) {
03118 cpl_msg_warning(cpl_func,
03119 "2d gaussfit, could not determine minor axis");
03120 *minor = -1.;
03121 }
03122 }
03123 if (major_err) {
03124 *major_err = sqrt(cpl_matrix_get(phys_cov, 1, 1)) * CPL_MATH_FWHM_SIG;
03125 if (isnan(*major_err)) {
03126 *major_err = -1.;
03127 }
03128 }
03129 if (minor_err) {
03130 *minor_err = sqrt(cpl_matrix_get(phys_cov, 2, 2)) * CPL_MATH_FWHM_SIG;
03131 if (isnan(*minor_err)) {
03132 *minor_err = -1.;
03133 }
03134 }
03135 if (angle_err) {
03136 *angle_err = sqrt(cpl_matrix_get(phys_cov, 0, 0));
03137 if (isnan(*angle_err)) {
03138 *angle_err = -1.;
03139 }
03140 }
03141
03142 cleanup:
03143 cpl_array_delete(dpar);
03144 cpl_array_delete(epar);
03145 cpl_image_delete(err);
03146 cpl_image_delete(img);
03147 cpl_matrix_delete(phys_cov);
03148 cpl_matrix_delete(cov);
03149
03150 return cpl_error_get_code();
03151 }
03152
03153
03154
03168
03169 cpl_error_code
03170 fit_1d_gauss(const cpl_vector * xv, const cpl_vector * yv, cpl_vector * dyv,
03171 double * x0, double * x0_err,
03172 double * peak, double * peak_err,
03173 double * sigma_, double * sigma_err)
03174 {
03175 double sigma, area, offset;
03176 cpl_matrix * cov = NULL;
03177 skip_if(cpl_vector_fit_gaussian(xv, NULL,
03178 yv, dyv,
03179 CPL_FIT_CENTROID | CPL_FIT_STDEV |
03180 CPL_FIT_AREA | CPL_FIT_OFFSET,
03181 x0, &sigma, &area, &offset,
03182 NULL, NULL,
03183 &cov));
03184 if (x0 && isnan(*x0)) {
03185 cpl_msg_warning(cpl_func, "1d gaussfit, could not determine mean");
03186 *x0 = -1.;
03187 }
03188 if (x0_err) {
03189 *x0_err = sqrt(cpl_matrix_get(cov, 0, 0));
03190 if (isnan(*x0_err)) {
03191 *x0_err = -1.;
03192 }
03193 }
03194 if (sigma) {
03195 *sigma_ = sigma;
03196 if (isnan(*sigma_)) {
03197 cpl_msg_warning(cpl_func,
03198 "1d gaussfit, could not determine sigma");
03199 *sigma_ = -1.;
03200 }
03201 }
03202 if (peak) {
03203 *peak = area / sqrt(2 * CPL_MATH_PI * sigma * sigma) + offset;
03204 if (isnan(*peak)) {
03205 cpl_msg_warning(cpl_func, "1d gaussfit, could not determine peak");
03206 *peak = -1.;
03207 }
03208 }
03209 if (peak_err) {
03210 double dsig = sqrt(cpl_matrix_get(cov, 1, 1));
03211 double dA = sqrt(cpl_matrix_get(cov, 2, 2));
03212 double dB = sqrt(cpl_matrix_get(cov, 3, 3));
03213 double pi2sig2 = 2 * CPL_MATH_PI * sigma * sigma;
03214 *peak_err = sqrt(dsig * dsig * area * area /
03215 (2 * CPL_MATH_PI * pi2sig2 * sigma * sigma) +
03216 dA * dA / pi2sig2 + dB * dB);
03217 if (isnan(*peak_err)) {
03218 *peak_err = -1.;
03219 }
03220 }
03221 if (sigma_err) {
03222 *sigma_err = sqrt(cpl_matrix_get(cov, 1, 1));
03223 if (isnan(*sigma_err)) {
03224 *sigma_err = -1.;
03225 }
03226 }
03227
03228 cleanup:
03229 cpl_matrix_delete(cov);
03230
03231 return cpl_error_get_code();
03232 }