26 #if !defined _XOPEN_SOURCE
27 #define _XOPEN_SOURCE 500
34 #include "visir_utils.h"
36 #include "irplib_utils.h"
38 #include "visir_inputs.h"
39 #include "visir_pfits.h"
40 #define visir_pfits_get_int(KEY) irplib_pfits_get_int(self, KEY)
41 #include "visir_spc_distortion.h"
42 #include "visir_cpl_compat.h"
45 #include <sys/types.h>
59 #include <sys/types.h>
65 IRPLIB_DIAG_PRAGMA_PUSH_ERR(-Wimplicit-
function-declaration)
68 #include <pmmintrin.h>
71 #include <xmmintrin.h>
78 #define VISIR_BACKGD_START 76
79 #define VISIR_BACKGD_STOP 172
89 #define IND(x, y , nx) ((x) + (nx) * (y))
96 static double visir_great_circle_dist(
double,
double,
double,
double);
97 static double ra_hms2deg(
int,
int,
double);
98 static double dec_hms2deg(
int,
int,
double);
100 static const char * visir_get_capa(
const cpl_propertylist *);
101 static double visir_hcycle_background(
const irplib_framelist *,
int,
int);
103 #ifdef VISIR_MASK_HAS
104 static cpl_boolean visir_mask_has(
const cpl_mask *, cpl_binary,
int);
117 size_t visir_get_num_threads(cpl_boolean force)
119 if (force == CPL_FALSE && getenv(
"OMP_NUM_THREADS")) {
120 char * endptr, * str = getenv(
"OMP_NUM_THREADS");
121 int r = (int)strtol(str, &endptr, 10);
122 return (str == endptr || r < 1) ? 1 : r;
124 #if defined HAVE_SYSCONF && defined _SC_NPROCESSORS_ONLN
125 long ret = sysconf(_SC_NPROCESSORS_ONLN);
126 return ret < 1 ? 1 : ret;
141 cpl_boolean visir_get_tempdir(
char * tmpdir_)
143 cpl_boolean have_tmpdir = CPL_FALSE;
144 char tmpdir[strlen(tmpdir_) + 1];
149 for (
int i = 0; i < 10 && !have_tmpdir; i++) {
150 strcpy(tmpdir, tmpdir_);
151 skip_if(mkstemp(tmpdir) < 0);
152 skip_if(unlink(tmpdir));
153 have_tmpdir = mkdir(tmpdir, O_RDWR | S_IRWXU) == 0;
156 error_if(have_tmpdir != CPL_TRUE, CPL_ERROR_FILE_IO,
157 "Temporary directory creation failed");
159 strcpy(tmpdir_, tmpdir);
175 void visir_drop_cache(
const char * filename, off_t offset, off_t length)
177 #if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_DONTNEED
178 int fd = open(filename, O_RDONLY);
181 posix_fadvise(fd, offset, length, POSIX_FADV_DONTNEED);
200 void visir_readahead(
const char * filename, off_t offset, off_t length)
202 #if defined HAVE_POSIX_FADVISE && defined POSIX_FADV_WILLNEED
203 int fd = open(filename, O_RDONLY);
206 posix_fadvise(fd, offset, length, POSIX_FADV_WILLNEED);
218 size_t visir_get_nbytes(
const cpl_image * img)
220 return cpl_image_get_size_x(img) *
221 cpl_image_get_size_y(img) *
222 cpl_type_get_sizeof(cpl_image_get_type(img));
235 size_t visir_get_nbytes_plist(
const cpl_propertylist *
self)
237 int naxis = visir_pfits_get_int(
"NAXIS");
238 int bitpix = abs(visir_pfits_get_int(
"BITPIX"));
241 size_t naxis_bytes = 1;
243 for (
int i = 0; i < naxis; i++) {
245 sprintf(buffer,
"NAXIS%d", i + 1);
246 naxis_bytes *= visir_pfits_get_int(buffer);
248 if (cpl_propertylist_has(
self,
"XTENSION")) {
249 pcount = visir_pfits_get_int(
"PCOUNT");
250 gcount = visir_pfits_get_int(
"GCOUNT");
252 if (cpl_error_get_code())
255 nbytes = (bitpix / 8) * gcount * (pcount + naxis_bytes);
257 nbytes += cpl_propertylist_get_size(
self) * 80;
273 cpl_error_code visir_image_multiply_fast(cpl_image * im1,
274 const cpl_image * im2)
276 #if defined __SSE3__ || defined __SSE2__
277 cpl_ensure_code(im1 != NULL, CPL_ERROR_NULL_INPUT);
278 cpl_ensure_code(im2 != NULL, CPL_ERROR_NULL_INPUT);
280 if (cpl_image_get_type(im1) == CPL_TYPE_FLOAT_COMPLEX &&
281 cpl_image_get_type(im2) == CPL_TYPE_FLOAT_COMPLEX) {
282 const cpl_size nx1 = cpl_image_get_size_x(im1);
283 const cpl_size ny1 = cpl_image_get_size_y(im1);
284 const cpl_size nx2 = cpl_image_get_size_x(im2);
285 const cpl_size ny2 = cpl_image_get_size_y(im2);
286 const size_t Nt = nx1 * ny1;
287 const size_t n = (Nt % 2) == 1 ? Nt - 1 : Nt;
289 float complex * a = cpl_image_get_data(im1);
290 const float complex * b = cpl_image_get_data_const(im2);
292 cpl_ensure_code(nx1 == nx2, CPL_ERROR_INCOMPATIBLE_INPUT);
293 cpl_ensure_code(ny1 == ny2, CPL_ERROR_INCOMPATIBLE_INPUT);
294 cpl_ensure_code(n < SIZE_MAX - 1, CPL_ERROR_ACCESS_OUT_OF_RANGE);
298 if (((intptr_t)a % 16) != 0 || ((intptr_t)b % 16) != 0)
299 return cpl_image_multiply(im1, im2);
301 #if defined __SSE2__ && !defined __SSE3__
302 const __m128 neg = (__m128)_mm_set_epi32(0x0u, 0x80000000u, 0x0u, 0x80000000u);
304 for (
size_t i = 0; i < n; i += 2) {
305 __m128 ua = _mm_load_ps((
float *)&a[i]);
306 __m128 ub = _mm_load_ps((
const float *)&b[i]);
308 __m128 reala = _mm_shuffle_ps(ua, ua, _MM_SHUFFLE(2, 2, 0, 0));
309 __m128 imaga = _mm_shuffle_ps(ua, ua, _MM_SHUFFLE(3, 3, 1, 1));
310 __m128 t1 = _mm_mul_ps(reala, ub);
311 __m128 sb = _mm_shuffle_ps(ub, ub, _MM_SHUFFLE(2, 3, 0, 1));
312 __m128 t2 = _mm_mul_ps(imaga, sb);
313 #if defined __SSE2__ && !defined __SSE3__
314 t2 = _mm_xor_ps(t2, neg);
315 __m128 res = _mm_add_ps(t1, t2);
317 __m128 res = _mm_addsub_ps(t1, t2);
319 _mm_store_ps((
float *)&a[i], res);
323 a[Nt - 1] = a[Nt - 1] * b[Nt - 1];
326 const cpl_mask * bpm1 = cpl_image_get_bpm_const(im1);
327 const cpl_mask * bpm2 = cpl_image_get_bpm_const(im2);
330 cpl_image_reject_from_mask(im1, bpm2);
332 cpl_mask_or(cpl_image_get_bpm(im1), bpm2);
338 cpl_image_multiply(im1, im2);
340 return CPL_ERROR_NONE;
355 double visir_image_get_mean_fast(
const cpl_image * im)
357 if (im == NULL || cpl_image_get_type(im) != CPL_TYPE_FLOAT) {
358 return cpl_image_get_mean(im);
361 const size_t npix = cpl_image_get_size_x(im) *
362 cpl_image_get_size_y(im);
363 const float * data = cpl_image_get_data_float_const(im);
364 const size_t nbad = cpl_image_count_rejected(im);
373 for (i = 0; i < npix - (npix % 4u); i+=4) {
379 for (; i < npix; i++) {
383 else if (nbad == npix) {
388 const cpl_binary * m =
389 cpl_mask_get_data_const(cpl_image_get_bpm_const(im));
390 for (i = 0; i < npix - (npix % 4u); i+=4) {
400 for (; i < npix; i++) {
405 return (sum1 + sum2 + sum3 + sum4) / (npix - nbad);
419 int visir_cmp_frm_fn(
const cpl_frame * a,
const cpl_frame * b)
421 const char * fna = cpl_frame_get_filename(a);
422 const char * fnb = cpl_frame_get_filename(b);
424 return strcmp(fna, fnb);
437 cpl_error_code visir_move_products(cpl_frameset *frames,
438 const char * dest_,
const char * src_)
440 const char * dest = dest_ ? dest_ :
".";
441 const char * src = src_ ? src_ :
".";
443 FOR_EACH_FRAMESET(frm, frames) {
444 if (cpl_frame_get_group(frm) == CPL_FRAME_GROUP_PRODUCT) {
445 char * buf = cpl_strdup(cpl_frame_get_filename(frm));
446 char * new_fn = cpl_sprintf(
"%s/%s", dest, basename(buf));
449 buf = cpl_sprintf(
"mv \"%s/%s\" \"%s\"", src,
450 cpl_frame_get_filename(frm), new_fn);
451 if (WEXITSTATUS(system(buf)) != 0) {
452 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
453 "Could not move %s/%s to %s", src,
454 cpl_frame_get_filename(frm), new_fn);
470 return cpl_error_get_code();
484 cpl_parameter * visir_parameter_duplicate(
const cpl_parameter * p)
486 cpl_parameter * np = NULL;
488 cpl_ensure(p != NULL, CPL_ERROR_NULL_INPUT, NULL);
489 cpl_ensure(cpl_parameter_get_class(p) == CPL_PARAMETER_CLASS_VALUE,
490 CPL_ERROR_UNSUPPORTED_MODE, NULL);
492 switch (cpl_parameter_get_type(p)) {
494 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
495 cpl_parameter_get_type(p),
496 cpl_parameter_get_help(p),
497 cpl_parameter_get_context(p),
498 cpl_parameter_get_default_bool(p));
499 cpl_parameter_set_bool(np, cpl_parameter_get_bool(p));
503 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
504 cpl_parameter_get_type(p),
505 cpl_parameter_get_help(p),
506 cpl_parameter_get_context(p),
507 cpl_parameter_get_default_int(p));
508 cpl_parameter_set_int(np, cpl_parameter_get_int(p));
511 case CPL_TYPE_DOUBLE:
512 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
513 cpl_parameter_get_type(p),
514 cpl_parameter_get_help(p),
515 cpl_parameter_get_context(p),
516 cpl_parameter_get_default_double(p));
517 cpl_parameter_set_double(np, cpl_parameter_get_double(p));
520 case CPL_TYPE_STRING:
521 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
522 cpl_parameter_get_type(p),
523 cpl_parameter_get_help(p),
524 cpl_parameter_get_context(p),
525 cpl_parameter_get_default_string(p));
526 cpl_parameter_set_string(np, cpl_parameter_get_string(p));
530 cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
531 "Parameter has unknown type");
538 if (cpl_parameter_get_tag(p))
539 cpl_parameter_set_tag(np, cpl_parameter_get_tag(p));
542 cpl_parameter_mode modes[] = {CPL_PARAMETER_MODE_CLI,
543 CPL_PARAMETER_MODE_CFG, CPL_PARAMETER_MODE_ENV};
545 for (
size_t i = 0; i < ARRAY_LEN(modes); i++) {
546 cpl_parameter_set_alias(np, modes[i],
547 cpl_parameter_get_alias(p, modes[i]));
548 if (!cpl_parameter_is_enabled(p, modes[i]))
549 cpl_parameter_disable(np, modes[i]);
569 cpl_error_code visir_copy_parameters(cpl_parameterlist * dest,
570 const cpl_parameterlist * src)
572 for (
const cpl_parameter * p = cpl_parameterlist_get_first_const(src);
573 p != NULL; p = cpl_parameterlist_get_next_const(src)) {
574 cpl_parameter * par =
575 cpl_parameterlist_find(dest, cpl_parameter_get_name(p));
580 cpl_type t = cpl_parameter_get_type(par);
581 if (t == CPL_TYPE_BOOL)
582 cpl_parameter_set_bool(par, cpl_parameter_get_bool(p));
583 else if (t == CPL_TYPE_INT)
584 cpl_parameter_set_int(par, cpl_parameter_get_int(p));
585 else if (t == CPL_TYPE_DOUBLE)
586 cpl_parameter_set_double(par, cpl_parameter_get_double(p));
587 else if (t == CPL_TYPE_STRING)
588 cpl_parameter_set_string(par, cpl_parameter_get_string(p));
595 return cpl_error_get_code();
610 visir_init_recipe(
const char * name,
int (*get_info)(cpl_pluginlist *),
611 cpl_pluginlist * plugins)
613 cpl_recipe * recipe = cpl_calloc(1,
sizeof(cpl_recipe));
615 cpl_plugin * pl = cpl_pluginlist_find (plugins, name);
616 cpl_plugin_copy ((cpl_plugin *) & recipe->interface, pl);
634 visir_run_recipe(cpl_recipe * recipe,
635 cpl_frameset * framelist,
const cpl_parameterlist * parlist,
636 cpl_error_code (*set_parlist)(cpl_parameterlist *,
637 const cpl_parameterlist *))
639 cpl_plugin * pl = &recipe->interface;
640 cpl_plugin_func plugin_func_init = cpl_plugin_get_init(pl);
641 cpl_plugin_func plugin_func_exec = cpl_plugin_get_exec(pl);
642 cpl_plugin_func plugin_func_deinit = cpl_plugin_get_deinit(pl);
646 recipe->frames = framelist;
648 plugin_func_init(&recipe->interface);
650 set_parlist(recipe->parameters, parlist);
651 plugin_func_exec(&recipe->interface);
652 plugin_func_deinit(&recipe->interface);
655 return cpl_error_get_code();
677 visir_prepare_frameset(
const cpl_frameset * frameset,
678 const char ** tagmap,
size_t ntags,
681 cpl_frameset * nlist = cpl_frameset_new();
682 cx_list * _nlist = cx_list_new();
683 cpl_ensure(ntags % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, nlist);
685 FOR_EACH_FRAMESET_C(frame, frameset) {
686 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_PRODUCT) {
687 cpl_frame * frm = cpl_frame_duplicate(frame);
688 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
689 cpl_frame_set_level(frm, CPL_FRAME_LEVEL_NONE);
690 for (
size_t i = 0; i < ntags; i += 2)
691 if (strcmp(tagmap[i], cpl_frame_get_tag(frm)) == 0)
692 cpl_frame_set_tag(frm, tagmap[i + 1]);
694 cx_list_push_back(_nlist, frm);
696 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB)
697 cx_list_push_back(_nlist, cpl_frame_duplicate(frame));
700 cx_list_sort(_nlist, (cx_compare_func)visir_cmp_frm_fn);
702 cx_list_reverse(_nlist);
706 cpl_frameset_insert(nlist, cx_list_get(_nlist, it));
707 cx_list_delete(_nlist);
722 cpl_frameset * visir_remove_modified_calib(cpl_frameset * set)
724 cpl_frameset * cleanset = cpl_frameset_new();
725 FOR_EACH_FRAMESET(frame, set) {
726 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB &&
727 strcmp(cpl_frame_get_tag(frame),
728 "STATIC_MASK") == 0) {
731 cpl_frameset_insert(cleanset, cpl_frame_duplicate(frame));
733 cpl_frameset_delete(set);
749 static cpl_frameset *
750 visir_wait_for_child(pid_t pid, FILE * rpipe)
752 char * rbuffer = NULL;
756 cpl_frameset * result = NULL;
761 cpl_ensure(rpipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
762 skip_if(fread(&err,
sizeof(err), 1, rpipe) != 1);
763 cpl_error_set(cpl_func, err);
765 skip_if(fread(&size,
sizeof(size), 1, rpipe) != 1);
767 rbuffer = cpl_malloc(size);
768 skip_if(fread(rbuffer, size, 1, rpipe) != 1);
770 result = visir_frameset_deserialize(rbuffer, NULL);
775 if (waitpid(pid, &status, 0) != pid) {
776 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
777 "%s", strerror(errno));
779 else if (WIFSIGNALED(status)) {
780 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
781 "Process killed by signal %d", WTERMSIG(status));
783 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
784 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
785 "Process failed with code %d",
786 WEXITSTATUS(status));
806 remove_tempdir(
const cpl_parameterlist * parlist,
const char* recipename,
809 const cpl_boolean
delete =
810 irplib_parameterlist_get_bool(parlist, PACKAGE,
811 recipename,
"delete-temp");
814 char * cmd = cpl_sprintf(
"rm -rf \"%s\"", tmpdir);
815 cpl_msg_info(cpl_func,
"Removing temporary directory: %s", tmpdir);
816 if (WEXITSTATUS(system(cmd)) != 0)
817 cpl_msg_warning(cpl_func,
"Removing temporary "
818 "directory %s failed", tmpdir);
822 cpl_msg_info(cpl_func,
"Keeping temporary directory: %s", tmpdir);
836 visir_tmpdir_exec(
const char * recipename, cpl_plugin * plugin,
837 int (*
function)(cpl_frameset *,
const cpl_parameterlist *))
839 char tmpdir[strlen(recipename) + 8];
840 cpl_boolean have_tmpdir = CPL_FALSE;
841 cpl_errorstate cleanstate = cpl_errorstate_get();
842 cpl_recipe * recipe = (cpl_recipe *)plugin;
843 sprintf(tmpdir,
"%s_XXXXXX", recipename);
845 have_tmpdir = visir_get_tempdir(tmpdir);
846 skip_if(have_tmpdir != CPL_TRUE);
848 cpl_msg_info(cpl_func,
"Working in temporary directory: %s", tmpdir);
851 if (chdir(tmpdir) != 0) {
852 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
853 "Could not change to temporary directory %s", tmpdir);
857 FOR_EACH_FRAMESET(frm, recipe->frames) {
858 if (cpl_frame_get_filename(frm)[0] !=
'/') {
859 char * buf = cpl_sprintf(
"../%s", cpl_frame_get_filename(frm));
860 cpl_frame_set_filename(frm, buf);
865 cpl_error_code err = cpl_recipedefine_exec(plugin,
function)
866 ? (int)cpl_error_set_where(cpl_func) : 0;
868 if (chdir(
"..") != 0) {
869 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
870 "Could not change back to base directory");
874 skip_if(visir_move_products(recipe->frames,
".", tmpdir));
879 remove_tempdir(recipe->parameters, recipename, tmpdir);
882 if (!cpl_errorstate_is_equal(cleanstate))
883 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
885 return cpl_error_get_code();
900 visir_forking_exec(
const char * recipename, cpl_plugin * plugin,
901 int (*
function)(cpl_frameset *,
const cpl_parameterlist *))
903 char tmpdir[strlen(recipename) + 8];
904 cpl_boolean have_tmpdir = CPL_FALSE;
905 cpl_errorstate cleanstate = cpl_errorstate_get();
906 cpl_recipe * recipe = (cpl_recipe *)plugin;
907 FILE * pipe_stream = NULL;
909 static const int READ = 0, WRITE = 1;
910 sprintf(tmpdir,
"%s_XXXXXX", recipename);
913 struct sigaction sa, sa_orig;
914 sa.sa_handler = SIG_IGN;
915 sigemptyset(&sa.sa_mask);
917 skip_if(sigaction(SIGINT, &sa, &sa_orig) != 0);
919 have_tmpdir = visir_get_tempdir(tmpdir);
920 skip_if(have_tmpdir != CPL_TRUE);
922 cpl_msg_info(cpl_func,
"Working in temporary directory: %s", tmpdir);
924 skip_if(pipe(pipe_fd) != 0);
928 close(pipe_fd[READ]);
929 close(pipe_fd[WRITE]);
930 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
931 "fork failed: %s", strerror(errno));
936 sigaction(SIGINT, &sa_orig, NULL);
939 close(pipe_fd[READ]);
940 pipe_stream = fdopen(pipe_fd[WRITE],
"w");
943 if (!pipe_stream || chdir(tmpdir) != 0) {
944 close(pipe_fd[WRITE]);
949 FOR_EACH_FRAMESET(frm, recipe->frames) {
950 if (cpl_frame_get_filename(frm)[0] !=
'/') {
951 char * buf = cpl_sprintf(
"../%s", cpl_frame_get_filename(frm));
952 cpl_frame_set_filename(frm, buf);
957 cpl_error_code err = cpl_recipedefine_exec(plugin,
function)
958 ? (int)cpl_error_set_where(cpl_func) : 0;
960 if (err == CPL_ERROR_NONE) {
961 assert((
void*)recipe == (
void*)plugin);
962 err = visir_send_frameset(pipe_stream, recipe->frames);
969 close(pipe_fd[WRITE]);
970 pipe_stream = fdopen(pipe_fd[READ],
"r");
971 skip_if(pipe_stream == NULL);
973 recipe->frames = visir_wait_for_child(pid, pipe_stream);
975 skip_if(recipe->frames == NULL);
978 skip_if(visir_move_products(recipe->frames,
".", tmpdir));
984 remove_tempdir(recipe->parameters, recipename, tmpdir);
987 if (!cpl_errorstate_is_equal(cleanstate))
988 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
990 return cpl_error_get_code();
1002 double visir_utils_get_exptime(
const int nnod,
const cpl_propertylist * plist)
1015 const double value = 2 * dit * ndit * nnod * ncycles * navrg;
1018 cpl_msg_error(cpl_func,
"Illegal exposure time "
1019 "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
1020 dit, ndit, ncycles, nnod, value);
1038 double * visir_utils_get_wls(
const irplib_framelist *
self)
1042 double * wls = NULL;
1049 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
1052 wls = cpl_malloc(size *
sizeof(
double));
1055 for (i=0; i < size; i++) {
1056 const cpl_propertylist * plist
1066 if (cpl_error_get_code()) {
1085 cpl_image * visir_create_disk_intimage(
1098 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
1099 pintima = cpl_image_get_data_int(intima);
1102 for (j=0;j<ny ; j++) {
1103 for (i=0;i<nx ; i++) {
1104 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
1105 if (dist < radius*radius) {
1106 pintima[i+j*nx] = 1;
1108 pintima[i+j*nx] = 0;
1127 cpl_image * visir_create_ring_intimage(
1138 if (radius1 >= radius2) {
1139 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1140 "Small ring radius %d larger than big "
1141 "ring radius %d", radius1, radius2);
1144 if ((nx - x_pos) < radius2 || x_pos < radius2 ||
1145 (ny - y_pos) < radius2 || y_pos < radius2) {
1146 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1147 "Image of size [%d,%d] with object at "
1148 "[%d,%d] too small to create ring mask of "
1149 "radius %d", nx, ny, x_pos, y_pos, radius2);
1154 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
1155 pintima = cpl_image_get_data_int(intima);
1158 for (
int j=0;j<ny ; j++) {
1159 for (
int i=0;i<nx ; i++) {
1160 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
1161 if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
1162 pintima[i+j*nx] = 1;
1164 pintima[i+j*nx] = 0;
1183 double visir_image_sigma_clip(
const cpl_image *
self,
double * pstdev)
1185 const int dimx = cpl_image_get_size_x(
self);
1186 const int dimy = cpl_image_get_size_y(
self);
1187 const cpl_type type = cpl_image_get_type(
self);
1190 cpl_image * noise = cpl_image_new(dimx, dimy, type);
1191 cpl_mask * bpm = NULL;
1192 cpl_mask * kernel = cpl_mask_new(3, 3);
1193 const int niterations = 5;
1194 const double sigma = 3.0;
1195 const double median_corr = 0.94;
1196 double bgnoise = -1;
1202 bug_if(cpl_mask_not(kernel));
1203 bug_if(cpl_image_filter_mask(noise,
self, kernel, CPL_FILTER_MEDIAN,
1204 CPL_BORDER_FILTER));
1207 bug_if (cpl_image_subtract(noise,
self));
1209 for (i=0; i < niterations ; i++) {
1212 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
1214 const double mean = cpl_stats_get_mean(stats);
1215 const double stdev = cpl_stats_get_stdev(stats);
1218 const double low_thresh = mean - sigma * stdev;
1219 const double high_thresh = mean + sigma * stdev;
1222 cpl_stats_delete(stats);
1228 bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
1232 bug_if (cpl_mask_not(bpm));
1234 bug_if (cpl_image_reject_from_mask(noise, bpm));
1236 cpl_mask_delete(bpm);
1241 if (pstdev != NULL) {
1245 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
1248 bgnoise = cpl_stats_get_stdev(stats);
1249 *pstdev = cpl_image_get_median(
self) - cpl_stats_get_mean(stats);
1251 cpl_stats_delete(stats);
1254 bgnoise = cpl_image_get_stdev(noise);
1259 bgnoise /= median_corr;
1263 if (cpl_error_get_code())
1264 cpl_msg_error(cpl_func,
"Computation of background noise using sigma=%g"
1265 " failed in iteration %d of %d", sigma, i+1, niterations);
1267 cpl_mask_delete(kernel);
1268 cpl_mask_delete(bpm);
1269 cpl_image_delete(noise);
1285 double visir_img_phot_sigma_clip(
const cpl_image *
self)
1288 const double noise = visir_image_sigma_clip(
self, NULL);
1290 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
1315 int visir_star_find(
const cpl_vector * v_ra,
const cpl_vector * v_dec,
1316 double ra,
double dec,
double maxdist,
double * pdist)
1318 const int nra = cpl_vector_get_size(v_ra);
1319 const int ndec = cpl_vector_get_size(v_dec);
1326 cpl_ensure(nra > 0, cpl_error_get_code(), -2);
1327 cpl_ensure(ndec > 0, cpl_error_get_code(), -3);
1332 cpl_ensure(nra == ndec, CPL_ERROR_INCOMPATIBLE_INPUT, -4);
1334 cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
1337 for (i=0 ; i < nra ; i++) {
1338 const double rai = cpl_vector_get(v_ra, i);
1339 const double deci = cpl_vector_get(v_dec, i);
1340 const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
1342 cpl_msg_debug(cpl_func,
"DISTANCE (RAi,DECi)=(%g,%g) <=> "
1343 "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
1345 if (i == 0 || gdist < dmin) {
1351 if (pdist != NULL) *pdist = dmin;
1354 if (dmin > maxdist) {
1355 cpl_msg_error(cpl_func,
"Nearest standard star (%d of %d) at (RA,DEC)="
1356 "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
1357 1+minind, nra, cpl_vector_get(v_ra, minind),
1358 cpl_vector_get(v_dec, minind), ra, dec, dmin, maxdist);
1359 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
1385 cpl_error_code visir_star_convert(
const char * line,
int ra_hh,
int ra_mm,
1386 double ra_ss,
char isign,
int dec_hh,
1387 int dec_mm,
double dec_ss,
1388 const double * jys,
int njys,
1389 double * pra,
double * pdec)
1404 else if (isign ==
'-')
1407 cpl_msg_error(cpl_func,
"Line has illegal declination-sign character "
1408 "(%c): %s", isign, line);
1409 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1413 cpl_msg_error(cpl_func,
"Line has negative RA hh (%d): %s",
1415 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1418 cpl_msg_error(cpl_func,
"Line has negative RA mm (%d): %s",
1420 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1423 cpl_msg_error(cpl_func,
"Line has too large RA mm (%d): %s ",
1425 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1428 cpl_msg_error(cpl_func,
"Line has negative RA ss (%g): %s",
1430 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1433 cpl_msg_error(cpl_func,
"Line has too large RA ss (%g): %s ",
1435 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1439 cpl_msg_error(cpl_func,
"Line has negative DEC hh (%d): %s",
1441 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1444 cpl_msg_error(cpl_func,
"Line has negative DEC mm (%d): %s",
1446 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1449 cpl_msg_error(cpl_func,
"Line has too large DEC mm (%d): %s ",
1451 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1454 cpl_msg_error(cpl_func,
"Line has negative DEC ss (%g): %s",
1456 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1459 cpl_msg_error(cpl_func,
"Line has too large DEC ss (%g): %s ",
1461 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1464 *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
1465 if (*pra >= 360.0) {
1466 cpl_msg_error(cpl_func,
"Line has too large RA (%g): %s ",
1468 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1471 *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
1473 cpl_msg_error(cpl_func,
"Line has too large RA (%g): %s ",
1475 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1477 if (*pdec < -90.0) {
1478 cpl_msg_error(cpl_func,
"Line has too small RA (%g): %s ",
1480 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1483 for (i=0; i < njys; i++)
if (jys[i] <= 0.0) {
1484 cpl_msg_error(cpl_func,
"Line has non-positive Jy value (%g) at %d: %s ",
1486 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1489 return CPL_ERROR_NONE;
1507 cpl_table * visir_table_new_xypos(
const cpl_imagelist * images,
1510 cpl_errorstate cleanstate = cpl_errorstate_get();
1511 const int nsize = cpl_imagelist_get_size(images);
1512 double psigmas[] = {5, 2, 1, 0.5};
1513 cpl_vector * sigmas = NULL;
1514 cpl_table *
self = NULL;
1515 const int nsigmas =
sizeof(psigmas)/
sizeof(
double);
1519 cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
1520 cpl_ensure(label, CPL_ERROR_NULL_INPUT, NULL);
1521 cpl_ensure(!strcmp(label,
"FLUX") || !strcmp(label,
"FWHM"),
1522 CPL_ERROR_UNSUPPORTED_MODE, NULL);
1524 self = cpl_table_new(nsize);
1526 skip_if (cpl_table_new_column(
self,
"X_POS", CPL_TYPE_DOUBLE));
1527 skip_if (cpl_table_new_column(
self,
"Y_POS", CPL_TYPE_DOUBLE));
1529 if (!strcmp(label,
"FLUX")) {
1531 skip_if (cpl_table_new_column(
self, label, CPL_TYPE_DOUBLE));
1533 skip_if (cpl_table_new_column(
self,
"X_FWHM", CPL_TYPE_DOUBLE));
1534 skip_if (cpl_table_new_column(
self,
"Y_FWHM", CPL_TYPE_DOUBLE));
1537 sigmas = cpl_vector_wrap(4, psigmas);
1538 skip_if (sigmas == NULL);
1540 cpl_msg_info(cpl_func,
"Detecting apertures using %d sigma-levels "
1541 "ranging from %g down to %g", nsigmas, psigmas[0],
1542 psigmas[nsigmas-1]);
1546 for (i=0 ; i < nsize ; i++) {
1547 const cpl_image * image = cpl_imagelist_get_const(images, i);
1548 cpl_apertures * apert;
1562 apert = cpl_apertures_extract(image, sigmas, &isigma);
1564 if (apert != NULL && cpl_error_get_code()) {
1566 cpl_msg_error(cpl_func,
"cpl_apertures_extract() returned non-NULL "
1567 "while setting the CPL error-state to '%s' at '%s'",
1568 cpl_error_get_message(), cpl_error_get_where());
1569 cpl_msg_debug(cpl_func,
"Deleting the spurious aperture list at %p:",
1571 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
1572 cpl_apertures_dump(apert, stdout);
1573 cpl_apertures_delete(apert);
1577 if (apert != NULL &&
1579 cpl_apertures_get_flux(apert, iflux) > 0) {
1581 posx = cpl_apertures_get_centroid_x(apert, iflux);
1582 posy = cpl_apertures_get_centroid_y(apert, iflux);
1583 flux = cpl_apertures_get_flux(apert, iflux);
1585 cpl_image_get_fwhm(image, (
int)posx, (
int)posy, &fwhmx, &fwhmy);
1587 cpl_msg_info(cpl_func,
"Detected an aperture with flux=%g at "
1588 "sigma=%g, at position: %g %g", flux,
1589 psigmas[isigma], posx, posy);
1593 if (apert == NULL || cpl_error_get_code()) {
1594 visir_error_reset(
"Aperture detection in image %d of %d failed",
1597 }
else if (flux <= 0) {
1598 cpl_msg_warning(cpl_func,
"Ignoring %d-pixel aperture %d (out of "
1599 "%d) in file %d of %d with non-positive flux: %g",
1600 (
int)cpl_apertures_get_npix(apert, iflux), iflux,
1601 (
int)cpl_apertures_get_size(apert), i+1, nsize,
1606 cpl_apertures_delete(apert);
1609 skip_if (cpl_table_set_double(
self,
"X_POS", i, posx));
1610 skip_if (cpl_table_set_double(
self,
"Y_POS", i, posy));
1613 skip_if (cpl_table_set_double(
self,
"FLUX", i, flux));
1615 skip_if (cpl_table_set_double(
self,
"X_FWHM", i, fwhmx));
1616 skip_if (cpl_table_set_double(
self,
"Y_FWHM", i, fwhmy));
1622 if (nfail == nsize) {
1623 cpl_msg_error(cpl_func,
"Aperture detection failed in all %d images",
1625 visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
1631 cpl_vector_unwrap(sigmas);
1633 if (
self && cpl_error_get_code()) {
1634 cpl_table_delete(
self);
1649 int visir_vector_minpos(
const cpl_vector * v)
1651 const double * x = cpl_vector_get_data_const(v);
1652 const int n = cpl_vector_get_size(v);
1656 cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
1658 for (i = 1; i < n; i++)
if (x[i] < x[minpos]) minpos = i;
1679 cpl_error_code visir_bivector_load(cpl_bivector *
self, FILE * stream)
1687 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
1688 cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
1691 v1 = cpl_bivector_get_x(
self);
1692 v2 = cpl_bivector_get_y(
self);
1694 xsize = cpl_vector_get_size(v1);
1695 ysize = cpl_vector_get_size(v2);
1697 while (fgets(line, 1024, stream) != NULL) {
1699 if (line[0] !=
'#' && sscanf(line,
"%lg %lg", &x, &y) == 2) {
1706 cpl_vector_set_size(v1, xsize);
1710 cpl_vector_set_size(v2, ysize);
1712 cpl_vector_set(v1, np, x);
1713 cpl_vector_set(v2, np, y);
1719 cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
1722 if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
1723 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1726 return CPL_ERROR_NONE;
1744 double visir_star_dist_min(
const double * pras,
const double * pdecs,
int nloc,
1745 int * piloc1,
int * piloc2)
1752 assert( pras != NULL);
1753 assert( pdecs != NULL);
1754 assert( piloc1 != NULL);
1755 assert( piloc2 != NULL);
1758 for (j = 0; j < nloc; j++) {
1759 for (i = 0; i < j; i++) {
1760 const double dist = visir_great_circle_dist(pras[i], pdecs[i],
1767 if (dist < VISIR_STAR_MAX_RADIUS)
1768 cpl_msg_warning(cpl_func,
"The two stars (%d,%d) have a distance"
1769 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
1792 const char ** visir_framelist_set_tag(irplib_framelist *
self,
1793 char * (*pftag)(
const cpl_frame *,
1794 const cpl_propertylist *,
1801 const char ** taglist = NULL;
1804 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1805 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1806 cpl_ensure(pftag != NULL, CPL_ERROR_NULL_INPUT, NULL);
1807 cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
1811 cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
1815 for (iframe = 0; iframe < size ; iframe++) {
1817 const cpl_propertylist * plist
1820 const char * newtag;
1825 cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
1826 cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
1828 tag = (*pftag)(frame, plist, iframe);
1830 cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
1834 (void)cpl_frame_set_tag(frame, tag);
1837 newtag = cpl_frame_get_tag(frame);
1839 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1842 for (i=0; i < *pntags; i++)
1843 if (strcmp(newtag, taglist[i]) == 0)
break;
1849 taglist = (
const char **)cpl_realloc(taglist, *pntags *
1850 sizeof(
const char *));
1851 taglist[i] = newtag;
1871 cpl_error_code visir_qc_append_background(cpl_propertylist *
self,
1872 const irplib_framelist * rawframes,
1873 int icol1,
int icol2)
1877 const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
1881 bug_if (cpl_propertylist_append_double(
self,
"ESO QC BACKGD MEAN",
1886 return cpl_error_get_code();
1901 cpl_error_code visir_qc_append_capa(cpl_propertylist *
self,
1902 const irplib_framelist * rawframes)
1905 cpl_errorstate cleanstate = cpl_errorstate_get();
1906 const cpl_propertylist * plist
1913 capa = visir_get_capa(plist);
1915 if (cpl_error_get_code()) {
1918 cpl_msg_info(cpl_func,
"Could not determine capa");
1919 cpl_errorstate_set(cleanstate);
1921 bug_if (cpl_propertylist_append_string(
self,
"ESO QC CAPA", capa));
1926 return cpl_error_get_code();
1939 cpl_error_code visir_qc_append_filter(cpl_propertylist *
self,
1940 const irplib_framelist * rawframes)
1943 const cpl_propertylist * plist
1950 bug_if (cpl_propertylist_append_string(
self,
"ESO QC FILTER", value));
1954 return cpl_error_get_code();
1967 cpl_error_code visir_qc_append_exptime(cpl_propertylist *
self,
1968 const irplib_framelist * rawframes)
1970 const cpl_propertylist * plist
1976 const double value = visir_utils_get_exptime(nnod, plist);
1980 bug_if (cpl_propertylist_append_double(
self,
"ESO QC EXPTIME", value));
1984 return cpl_error_get_code();
2002 static double visir_great_circle_dist(
double ra1,
double dec1,
2003 double ra2,
double dec2)
2007 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
2008 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
2010 dec1 *= CPL_MATH_RAD_DEG;
2011 dec2 *= CPL_MATH_RAD_DEG;
2013 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
2032 static double ra_hms2deg(
int hh,
int mm,
double ss)
2034 return 15.0 * dec_hms2deg(hh, mm, ss);
2050 static double dec_hms2deg(
int dd,
int mm,
double ss)
2052 return ((
double)ss/60.0 + (
double)mm)/60.0 + dd;
2069 static double visir_hcycle_background(
const irplib_framelist * rawframes,
2070 int icol1,
int icol2)
2072 cpl_imagelist * iset = NULL;
2081 skip_if (nfiles < 1);
2083 if (icol1 == 0) icol1 = VISIR_BACKGD_START;
2084 if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
2086 cpl_msg_info(cpl_func,
"Computing Half-cycle background level from column %d "
2087 "through %d", icol1, icol2);
2090 for (i=0; i < nfiles; i++) {
2096 for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
2097 const double median =
2098 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
2099 VISIR_BACKGD_START, icol1,
2100 VISIR_BACKGD_STOP, icol2);
2104 if (median != median) {
2108 cpl_msg_error(cpl_func,
"Image window (%d, %d, %d, %d) "
2109 "(image %d of %d) in %s (frame %d of %d) "
2111 VISIR_BACKGD_START, icol1,
2112 VISIR_BACKGD_STOP, icol2,
2113 j+1, (
int)cpl_imagelist_get_size(iset),
2114 cpl_frame_get_filename(frame), i+1, nfiles);
2115 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
2121 cpl_imagelist_delete(iset);
2128 bgmean = bgsum / nsum;
2132 cpl_imagelist_delete(iset);
2135 return bgmean - VISIR_HCYCLE_OFFSET;
2152 visir_get_subpixel_maxpos(
const cpl_image * img, cpl_size x, cpl_size y,
2153 double * xsub,
double * ysub)
2156 const cpl_size nx = cpl_image_get_size_x(img);
2157 const cpl_size ny = cpl_image_get_size_y(img);
2161 if (x - 1 > 0 && x + 1 <= nx) {
2163 cpl_image_get(img, x - 1, y, &bad),
2164 cpl_image_get(img, x - 0, y, &bad),
2165 cpl_image_get(img, x + 1, y, &bad),
2168 *xsub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
2170 if (y - 1 > 0 && y + 1 <= ny) {
2172 cpl_image_get(img, x, y - 1, &bad),
2173 cpl_image_get(img, x, y - 0, &bad),
2174 cpl_image_get(img, x, y + 1, &bad),
2177 *ysub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
2180 return cpl_error_get_code();
2183 static inline unsigned long get_msb(
unsigned long a)
2186 unsigned long msb = 0;
2203 size_t visir_get_next_regular(
size_t a)
2211 if ((a & (a - 1)) == 0)
2214 if (5 > SIZE_MAX / a)
2217 size_t match = SIZE_MAX;
2223 size_t quotient = a % p35 != 0 ? a / p35 + 1 : a / p35;
2225 size_t p2 = 2 << get_msb(quotient - 1);
2227 size_t n = p2 * p35;
2250 cpl_image * template_fft;
2251 double template_stdev;
2261 irplib_aligned_free(cpl_image_unwrap(c->template_fft));
2283 visir_fftxcorrelate(
const cpl_image * atemplate,
const cpl_image * aimg,
2284 cpl_boolean normalize,
double * xshift,
double * yshift,
2287 const cpl_size Nxi = cpl_image_get_size_x(aimg);
2288 const cpl_size Nyi = cpl_image_get_size_y(aimg);
2289 const cpl_size Nxt = cpl_image_get_size_x(atemplate);
2290 const cpl_size Nyt = cpl_image_get_size_y(atemplate);
2292 const cpl_size Nxe = visir_get_next_regular(Nxi + Nxt - 1);
2293 const cpl_size Nye = visir_get_next_regular(Nyi + Nyt - 1);
2294 cpl_size txshift, tyshift;
2295 double subx = 0, suby = 0;
2296 cpl_image * img = NULL;
2297 cpl_image * zimg = NULL;
2298 cpl_image * ztemp = NULL;
2299 cpl_image * fft1 = NULL;
2300 cpl_image * fft2 = NULL;
2301 cpl_image * res = NULL;
2303 double template_stdev;
2305 cpl_fft_mode mode = getenv(
"VISIR_TEST_MODE") ? 0 : CPL_FFT_FIND_MEASURE;
2307 cpl_ensure_code(atemplate != NULL, CPL_ERROR_NULL_INPUT);
2308 cpl_ensure_code(aimg != NULL, CPL_ERROR_NULL_INPUT);
2310 if (cache == NULL || cache->initialized == 0) {
2312 cpl_image *
template = NULL;
2313 if (cpl_image_get_type(atemplate) != CPL_TYPE_FLOAT)
2314 template = cpl_image_cast(atemplate, CPL_TYPE_FLOAT);
2316 template = cpl_image_duplicate(atemplate);
2318 cpl_image_fill_rejected(
template, 0);
2320 skip_if(cpl_image_subtract_scalar(
template,
2321 visir_image_get_mean_fast(
template)));
2322 template_stdev = cpl_image_get_stdev(
template);
2324 buffer = irplib_aligned_calloc(32, Nxe * Nye,
sizeof(
float));
2325 ztemp = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2329 skip_if(cpl_image_flip(
template, 1));
2330 skip_if(cpl_image_flip(
template, 3));
2333 skip_if(cpl_image_copy(ztemp,
template, 1, 1));
2334 cpl_image_delete(
template);
2336 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
2337 sizeof(
float complex));
2338 fft2 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX,
2340 skip_if(cpl_fft_image(fft2, ztemp, CPL_FFT_FORWARD));
2342 cache->template_fft = fft2;
2343 cache->template_stdev = template_stdev;
2344 cache->initialized = 1;
2348 fft2 = cache->template_fft;
2349 template_stdev = cache->template_stdev;
2350 error_if(cpl_image_get_type(fft2) != CPL_TYPE_FLOAT_COMPLEX ||
2351 cpl_image_get_size_x(fft2) != Nxe / 2 + 1 ||
2352 cpl_image_get_size_y(fft2) != Nye, CPL_ERROR_ILLEGAL_INPUT,
2353 "Invalid fourier transformed template");
2358 buffer = irplib_aligned_calloc(32, Nxe * Nye,
sizeof(
float));
2359 zimg = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2360 if (cpl_image_get_type(aimg) != CPL_TYPE_FLOAT)
2361 img = cpl_image_cast(aimg, CPL_TYPE_FLOAT);
2363 img = cpl_image_duplicate(aimg);
2365 skip_if(img == NULL);
2367 cpl_image_fill_rejected(img, 0);
2370 skip_if(cpl_image_subtract_scalar(img,
2371 visir_image_get_mean_fast(img)));
2374 skip_if(cpl_image_copy(zimg, img, 1, 1));
2376 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
2377 sizeof(
float complex));
2378 fft1 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX, buffer);
2380 skip_if(cpl_fft_image(fft1, zimg, CPL_FFT_FORWARD | mode));
2384 skip_if(visir_image_multiply_fast(fft1, fft2));
2386 buffer = irplib_aligned_malloc(32, Nxe * Nye *
sizeof(
float));
2387 res = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2388 skip_if(cpl_fft_image(res, fft1, CPL_FFT_BACKWARD | CPL_FFT_NOSCALE |
2391 skip_if(cpl_image_get_maxpos_window(res, Nxt / 2 , Nyt / 2,
2392 Nxt / 2 + Nxi, Nyt / 2 + Nyi,
2393 &txshift, &tyshift));
2395 if (max_correlation != NULL) {
2397 *max_correlation = cpl_image_get(res, txshift, tyshift, &rej);
2399 *max_correlation /= Nxe * Nye;
2402 double tstd = template_stdev;
2403 int mx = txshift - Nxt;
2404 int my = tyshift - Nyt;
2405 double istd= cpl_image_get_stdev_window(zimg,
2408 CX_MIN(Nxe, mx + Nxt),
2409 CX_MIN(Nye, my + Nyt));
2411 if (tstd * istd == 0)
2412 *max_correlation = 0;
2414 *max_correlation /= (tstd * istd * Nxt * Nyt);
2419 skip_if(visir_get_subpixel_maxpos(res, txshift, tyshift, &subx, &suby));
2420 if (xshift != NULL) {
2421 *xshift = txshift - Nxt + subx;
2423 if (yshift != NULL) {
2424 *yshift = tyshift - Nyt + suby;
2429 cpl_image_delete(img);
2431 irplib_aligned_free(cpl_image_unwrap(fft2));
2432 irplib_aligned_free(cpl_image_unwrap(fft1));
2433 irplib_aligned_free(cpl_image_unwrap(zimg));
2434 irplib_aligned_free(cpl_image_unwrap(ztemp));
2435 irplib_aligned_free(cpl_image_unwrap(res));
2437 return cpl_error_get_code();
2459 get_interpolation_points(
size_t x,
size_t y,
2460 size_t nx_,
size_t ny_, cpl_binary *bpm)
2462 ssize_t l = -1, r = -1 , u = -1, d = -1;
2467 ssize_t nx = (ssize_t)nx_;
2468 ssize_t ny = (ssize_t)ny_;
2469 cx_list * p = cx_list_new();
2479 if (l < 0 && xl >= 0 && bpm[IND(xl, y, nx)] == CPL_BINARY_0)
2481 if (r < 0 && xh < nx && bpm[IND(xh, y, nx)] == CPL_BINARY_0)
2483 if (d < 0 && yl >= 0 && bpm[IND(x, yl, nx)] == CPL_BINARY_0)
2485 if (u < 0 && yh < ny && bpm[IND(x, yh, nx)] == CPL_BINARY_0)
2490 if ((l != -1 && r != -1) || (d != -1 && u != -1) ||
2491 (xl < 0 && xh >= nx && yl < 0 && yh >= ny))
2497 cx_list_push_back(p, (cxcptr)(IND(r, y, nx)));
2499 cx_list_push_back(p, (cxcptr)(IND(l, y, nx)));
2501 cx_list_push_back(p, (cxcptr)(IND(x, u, nx)));
2503 cx_list_push_back(p, (cxcptr)(IND(x, d, nx)));
2528 visir_interpolate_rejected(cpl_image * img,
size_t ** ppoints,
size_t * n)
2530 cpl_mask * mask = cpl_image_get_bpm(img);
2531 float * data = cpl_image_get_data_float(img);
2532 cpl_binary * bpm = cpl_mask_get_data(mask);
2533 const size_t nx = (size_t)cpl_image_get_size_x(img);
2534 const size_t ny = (size_t)cpl_image_get_size_y(img);
2537 skip_if(data == NULL);
2539 if (ppoints == NULL || *ppoints == NULL) {
2541 cpl_binary * found = memchr(bpm, CPL_BINARY_1,
2542 sizeof(cpl_binary) * nx * ny);
2544 size_t * restrict pbpm = cpl_calloc(cpl_image_count_rejected(img) * 6,
2547 while (found != NULL) {
2548 const size_t ind = found - bpm;
2549 const size_t y = ind / nx;
2550 const size_t x = ind - y * nx;
2551 cx_list * p = get_interpolation_points(x, y, nx, ny, bpm);
2552 cx_list_iterator it = cx_list_begin(p);
2553 const size_t npix = cx_list_size(p);
2558 assert(pbpm[i - 1] <= 4);
2560 while (it != cx_list_end(p)) {
2561 const size_t lind = (size_t)cx_list_get(p, it);
2564 it = cx_list_next(p, it);
2566 data[ind] = sum / npix;
2569 found = memchr(found + 1, CPL_BINARY_1,
2570 sizeof(cpl_binary) * nx * ny - ind - 1);
2580 const size_t n_ = *n;
2581 size_t * restrict points = *ppoints;
2582 for (
size_t i = 0; i < n_;) {
2583 const size_t ind = points[i++];
2584 const size_t m = points[i++];
2586 for (
size_t j = 0; j < m; j++) {
2587 const size_t lind = points[i++];
2590 data[ind] = sum / m;
2594 cpl_image_accept_all(img);
2598 return cpl_error_get_code();
2601 static const cpl_image *
2602 image_const_row_view_create(
const cpl_image * img,
2606 const size_t dsz = cpl_type_get_sizeof(cpl_image_get_type(img));
2607 const cpl_size nx = cpl_image_get_size_x(img);
2608 const char * d = cpl_image_get_data_const(img);
2609 size_t offset = (ly - 1) * nx;
2610 cpl_size nny = uy - ly + 1;
2611 cpl_image * wimg = cpl_image_wrap(nx, nny, cpl_image_get_type(img),
2612 (
char*)d + offset * dsz);
2614 const cpl_mask * omask = cpl_image_get_bpm_const(img);
2616 cpl_mask * mask = cpl_mask_wrap(nx, nny,
2617 (cpl_binary*)cpl_mask_get_data_const(omask) + offset);
2618 cpl_mask_delete(cpl_image_set_bpm(wimg, mask));
2625 image_const_row_view_delete(
const cpl_image * img)
2627 cpl_mask_unwrap(cpl_image_unset_bpm((cpl_image*)(img)));
2628 cpl_image_unwrap((cpl_image *)img);
2640 visir_parallel_median_collapse(
const cpl_imagelist * l)
2643 return cpl_imagelist_collapse_median_create(l);
2645 cpl_ensure(l != NULL, CPL_ERROR_NULL_INPUT, NULL);
2646 cpl_ensure(cpl_imagelist_get_size(l) > 0,
2647 CPL_ERROR_ILLEGAL_INPUT, NULL);
2649 const size_t n = cpl_imagelist_get_size(l);
2650 const cpl_image * img = cpl_imagelist_get_const(l, 0);
2651 const size_t ny = cpl_image_get_size_y(img);
2652 const size_t nx = cpl_image_get_size_x(img);
2653 const size_t nthreads = CX_MIN(visir_get_num_threads(CPL_FALSE), ny);
2654 cpl_image * res = cpl_image_new(nx, ny, cpl_image_get_type(img));
2656 cpl_image_get_bpm(res);
2658 OMP_PRAGMA(omp parallel
for num_threads(nthreads))
2659 for (
size_t j = 0; j < nthreads; j++) {
2660 size_t ylow = j * (ny / nthreads) + 1;
2661 size_t yhigh = (j + 1) * (ny / nthreads);
2662 if (j == nthreads - 1)
2665 cpl_imagelist * view = cpl_imagelist_new();
2666 for (
size_t i = 0; i < n; i++) {
2667 const cpl_image * img = cpl_imagelist_get_const(l, i);
2668 const cpl_image * iview =
2669 image_const_row_view_create(img, ylow, yhigh);
2670 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2671 cpl_imagelist_set(view, (cpl_image *)iview, i);
2672 IRPLIB_DIAG_PRAGMA_POP;
2676 cpl_image * r = cpl_imagelist_collapse_median_create(view);
2677 cpl_image_copy(res, r, 1, ylow);
2680 cpl_image_delete(r);
2681 for (
size_t i = 0; i < n; i++) {
2682 cpl_image * img = cpl_imagelist_get(view, i);
2683 image_const_row_view_delete(img);
2685 cpl_imagelist_unwrap(view);
2700 static const char * visir_get_capa(
const cpl_propertylist * plist)
2702 const char * capa =
"Pb with Capa";
2715 if (!strcmp(sval,
"IMG")) {
2719 }
else if (!strcmp(sval,
"SPC") || !strcmp(sval,
"SPCIMG")) {
2732 capa =
"Large Capa";
2733 }
else if (mean > 4.5) {
2734 capa =
"Small Capa";
2742 #ifdef VISIR_MASK_HAS
2764 static cpl_boolean visir_mask_has(
const cpl_mask *
self, cpl_binary value,
2767 const cpl_binary * pself = cpl_mask_get_data_const(
self);
2768 int size = cpl_mask_get_size_x(
self)
2769 * cpl_mask_get_size_y(
self);
2772 cpl_ensure(
self, CPL_ERROR_NULL_INPUT, CPL_FALSE);
2773 cpl_ensure(ngood >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
2774 cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
2775 cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
2776 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
2778 for (i = 0; i < ngood; i++) {
2780 const cpl_binary * ppos = memchr(pself, value, (
size_t)size);
2781 if (ppos == NULL)
break;
2783 size -= 1 + (int)(ppos - pself);
2787 return i == ngood ? CPL_TRUE : CPL_FALSE;
2799 size_t visir_upper_bound(
const cpl_vector * vec,
double val)
2801 const double * d = cpl_vector_get_data_const(vec);
2802 long count = cpl_vector_get_size(vec);
2806 long step = count / 2;
2807 long it = first + step;
2808 if (!(val < d[it])) {
2826 size_t visir_lower_bound(
const cpl_vector * vec,
double val)
2828 const double * d = cpl_vector_get_data_const(vec);
2829 long count = cpl_vector_get_size(vec);
2833 long step = count / 2;
2834 long it = first + step;
2859 cpl_image * visir_linintp_values(
const cpl_image * inp,
const cpl_bivector * ref)
2861 const double * data = cpl_image_get_data_double_const(inp);
2862 const cpl_vector * rx = cpl_bivector_get_x_const(ref);
2863 const cpl_vector * ry = cpl_bivector_get_y_const(ref);
2864 size_t nref = cpl_bivector_get_size(ref);
2865 size_t nx = cpl_image_get_size_x(inp);
2866 size_t ny = cpl_image_get_size_y(inp);
2867 cpl_image * res = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
2868 double * rdata = cpl_image_get_data_double(res);
2869 cpl_ensure(nref >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
2871 for (
size_t y = 0; y < ny; y++) {
2872 for (
size_t x = 0; x < nx; x++) {
2873 double val = data[y * nx + x];
2874 intptr_t ilo = visir_lower_bound(rx, val);
2893 rdata[y * nx + x] = cpl_vector_get(ry, 0);
2894 cpl_image_reject(res, x + 1, y + 1);
2896 else if (ilo == nref) {
2897 rdata[y * nx + x] = cpl_vector_get(ry, nref - 1);
2898 cpl_image_reject(res, x + 1, y + 1);
2901 double rx1 = cpl_vector_get(rx, ilo - 1);
2902 double rx2 = cpl_vector_get(rx, ilo);
2903 double ry1 = cpl_vector_get(ry, ilo - 1);
2904 double ry2 = cpl_vector_get(ry, ilo);
2905 double grad = (ry2 - ry1) / (rx2 - rx1);
2906 double y0 = ry1 - grad * rx1;
2907 rdata[y * nx + x] = grad * val + y0;
2935 fit_2d_gauss(
const cpl_image * img_,
const cpl_image * weights, cpl_size x, cpl_size y,
2936 double est_fwhmx,
double est_fwhmy,
2937 double * peak,
double * peak_err,
2938 double * major,
double * major_err,
2939 double * minor,
double * minor_err,
2940 double * angle,
double * angle_err)
2942 cpl_image * img = cpl_image_cast(img_, CPL_TYPE_DOUBLE);
2943 cpl_size llx = CX_MAX(x - est_fwhmx * 3, 1);
2944 cpl_size lly = CX_MAX(y - est_fwhmy * 3, 1);
2945 cpl_size urx = CX_MIN(x + est_fwhmx * 3, cpl_image_get_size_x(img));
2946 cpl_size ury = CX_MIN(y + est_fwhmy * 3, cpl_image_get_size_y(img));
2947 cpl_array * dpar = cpl_array_new(7, CPL_TYPE_DOUBLE);
2948 cpl_array * epar = cpl_array_new(7, CPL_TYPE_DOUBLE);
2949 cpl_matrix * cov = NULL;
2950 cpl_matrix * phys_cov = NULL;
2952 cpl_array_set_double(dpar, 0, cpl_image_get_median(img));
2953 cpl_array_set_double(dpar, 1, cpl_image_get_flux_window(img, llx, lly,
2955 cpl_array_set_double(dpar, 2, 0.);
2956 cpl_array_set_double(dpar, 3, x);
2957 cpl_array_set_double(dpar, 4, y);
2958 cpl_array_set_double(dpar, 5, est_fwhmx / 2.355);
2959 cpl_array_set_double(dpar, 6, est_fwhmx / 2.355);
2961 cpl_image * err = cpl_image_new(cpl_image_get_size_x(img),
2962 cpl_image_get_size_y(img),
2964 cpl_image_add_scalar(err, 1.);
2965 cpl_image_divide(err, weights);
2966 cpl_image_power(err, 0.5);
2968 skip_if(cpl_fit_image_gaussian(img, err,
2989 double * a = cpl_array_get_data_double(dpar);
2990 *peak = a[0] + a[1] /
2991 (CPL_MATH_2PI * a[5] * a[6] * sqrt(1.0 - a[2] * a[2]));
2993 cpl_msg_warning(cpl_func,
"2d gaussfit, could not determine peak");
2998 double * a = cpl_array_get_data_double(dpar);
2999 double * e = cpl_array_get_data_double(epar);
3005 double dB = sqrt(e[0]);
3006 double dA = sqrt(e[1]);
3007 double dsigx = sqrt(e[5]);
3008 double dsigy = sqrt(e[6]);
3009 double drho = sqrt(e[2]);
3011 double rho2 = rho * rho;
3012 double x = CPL_MATH_PI * CPL_MATH_PI * 4 * sigx * sigx * sigy * sigy;
3014 sqrt(A2 * drho * drho * rho2 /(x * pow(-rho2 + 1.0, 3)) +
3015 A2 * dsigx * dsigx /(x * sigx * sigx * (-rho2 + 1.0)) +
3016 A2 * dsigy * dsigy /(x * sigy * sigy * (-rho2 + 1.0)) +
3017 dA * dA/(x * (-rho2 + 1.0)) + dB * dB);
3018 if (isnan(*peak_err)) {
3023 *major *= CPL_MATH_FWHM_SIG;
3024 if (isnan(*major)) {
3025 cpl_msg_warning(cpl_func,
3026 "2d gaussfit, could not determine major axis");
3031 *minor *= CPL_MATH_FWHM_SIG;
3032 if (isnan(*minor)) {
3033 cpl_msg_warning(cpl_func,
3034 "2d gaussfit, could not determine minor axis");
3039 *major_err = sqrt(cpl_matrix_get(phys_cov, 1, 1)) * CPL_MATH_FWHM_SIG;
3040 if (isnan(*major_err)) {
3045 *minor_err = sqrt(cpl_matrix_get(phys_cov, 2, 2)) * CPL_MATH_FWHM_SIG;
3046 if (isnan(*minor_err)) {
3051 *angle_err = sqrt(cpl_matrix_get(phys_cov, 0, 0));
3052 if (isnan(*angle_err)) {
3058 cpl_array_delete(dpar);
3059 cpl_array_delete(epar);
3060 cpl_image_delete(err);
3061 cpl_image_delete(img);
3062 cpl_matrix_delete(phys_cov);
3063 cpl_matrix_delete(cov);
3065 return cpl_error_get_code();
3085 fit_1d_gauss(
const cpl_vector * xv,
const cpl_vector * yv, cpl_vector * dyv,
3086 double * x0,
double * x0_err,
3087 double * peak,
double * peak_err,
3088 double * sigma_,
double * sigma_err)
3090 double sigma, area, offset;
3091 cpl_matrix * cov = NULL;
3092 skip_if(cpl_vector_fit_gaussian(xv, NULL,
3094 CPL_FIT_CENTROID | CPL_FIT_STDEV |
3095 CPL_FIT_AREA | CPL_FIT_OFFSET,
3096 x0, &sigma, &area, &offset,
3099 if (x0 && isnan(*x0)) {
3100 cpl_msg_warning(cpl_func,
"1d gaussfit, could not determine mean");
3104 *x0_err = sqrt(cpl_matrix_get(cov, 0, 0));
3105 if (isnan(*x0_err)) {
3111 if (isnan(*sigma_)) {
3112 cpl_msg_warning(cpl_func,
3113 "1d gaussfit, could not determine sigma");
3118 *peak = area / sqrt(2 * CPL_MATH_PI * sigma * sigma) + offset;
3120 cpl_msg_warning(cpl_func,
"1d gaussfit, could not determine peak");
3125 double dsig = sqrt(cpl_matrix_get(cov, 1, 1));
3126 double dA = sqrt(cpl_matrix_get(cov, 2, 2));
3127 double dB = sqrt(cpl_matrix_get(cov, 3, 3));
3128 double pi2sig2 = 2 * CPL_MATH_PI * sigma * sigma;
3129 *peak_err = sqrt(dsig * dsig * area * area /
3130 (2 * CPL_MATH_PI * pi2sig2 * sigma * sigma) +
3131 dA * dA / pi2sig2 + dB * dB);
3132 if (isnan(*peak_err)) {
3137 *sigma_err = sqrt(cpl_matrix_get(cov, 1, 1));
3138 if (isnan(*sigma_err)) {
3144 cpl_matrix_delete(cov);
3146 return cpl_error_get_code();
double visir_pfits_get_volt1dcta9(const cpl_propertylist *self)
The VOLT1.DCTA9.
double visir_pfits_get_volt1dctb9(const cpl_propertylist *self)
The VOLT1.DCTB9.
double visir_pfits_get_volt2dcta9(const cpl_propertylist *self)
The VOLT2.DCTA9.
int visir_pfits_get_navrg(const cpl_propertylist *self)
The NAVRG.
cpl_error_code irplib_apertures_find_max_flux(const cpl_apertures *self, int *ind, int nfind)
Find the aperture(s) with the greatest flux.
const char * visir_pfits_get_filter(const cpl_propertylist *self)
The filter.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
int visir_pfits_get_chop_ncycles(const cpl_propertylist *self)
The number of chopping cycles.
int visir_pfits_get_ndit(const cpl_propertylist *self)
The NDIT keyword.
double visir_pfits_get_volt2dctb9(const cpl_propertylist *self)
The VOLT2.DCTB9.
cpl_frame * irplib_framelist_get(irplib_framelist *self, int pos)
Get the specified frame from the framelist.
const char * visir_pfits_get_insmode(const cpl_propertylist *self)
The mode.
double visir_pfits_get_monoc_pos(const cpl_propertylist *self)
The INS.MONOC1.POS.
double visir_pfits_get_dit(const cpl_propertylist *self)
The DIT.
const cpl_frame * irplib_framelist_get_const(const irplib_framelist *self, int pos)
Get the specified frame from the framelist.
cpl_error_code irplib_framelist_contains(const irplib_framelist *self, const char *key, cpl_type type, cpl_boolean is_equal, double fp_tol)
Verify that a property is present for all frames.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.