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);
467 if (cpl_frame_get_group(frm) == CPL_FRAME_GROUP_RAW ||
468 cpl_frame_get_group(frm) == CPL_FRAME_GROUP_CALIB) {
469 if (strncmp(cpl_frame_get_filename(frm),
"../", 3) != 0) {
472 char * buf = cpl_strdup(cpl_frame_get_filename(frm));
473 cpl_frame_set_filename(frm, buf + 3);
480 return cpl_error_get_code();
494 cpl_parameter * visir_parameter_duplicate(
const cpl_parameter * p)
496 cpl_parameter * np = NULL;
498 cpl_ensure(p != NULL, CPL_ERROR_NULL_INPUT, NULL);
499 cpl_ensure(cpl_parameter_get_class(p) == CPL_PARAMETER_CLASS_VALUE,
500 CPL_ERROR_UNSUPPORTED_MODE, NULL);
502 switch (cpl_parameter_get_type(p)) {
504 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
505 cpl_parameter_get_type(p),
506 cpl_parameter_get_help(p),
507 cpl_parameter_get_context(p),
508 cpl_parameter_get_default_bool(p));
509 cpl_parameter_set_bool(np, cpl_parameter_get_bool(p));
513 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
514 cpl_parameter_get_type(p),
515 cpl_parameter_get_help(p),
516 cpl_parameter_get_context(p),
517 cpl_parameter_get_default_int(p));
518 cpl_parameter_set_int(np, cpl_parameter_get_int(p));
521 case CPL_TYPE_DOUBLE:
522 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
523 cpl_parameter_get_type(p),
524 cpl_parameter_get_help(p),
525 cpl_parameter_get_context(p),
526 cpl_parameter_get_default_double(p));
527 cpl_parameter_set_double(np, cpl_parameter_get_double(p));
530 case CPL_TYPE_STRING:
531 np = cpl_parameter_new_value(cpl_parameter_get_name(p),
532 cpl_parameter_get_type(p),
533 cpl_parameter_get_help(p),
534 cpl_parameter_get_context(p),
535 cpl_parameter_get_default_string(p));
536 cpl_parameter_set_string(np, cpl_parameter_get_string(p));
540 cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
541 "Parameter has unknown type");
548 if (cpl_parameter_get_tag(p))
549 cpl_parameter_set_tag(np, cpl_parameter_get_tag(p));
552 cpl_parameter_mode modes[] = {CPL_PARAMETER_MODE_CLI,
553 CPL_PARAMETER_MODE_CFG, CPL_PARAMETER_MODE_ENV};
555 for (
size_t i = 0; i < ARRAY_LEN(modes); i++) {
556 cpl_parameter_set_alias(np, modes[i],
557 cpl_parameter_get_alias(p, modes[i]));
558 if (!cpl_parameter_is_enabled(p, modes[i]))
559 cpl_parameter_disable(np, modes[i]);
579 cpl_error_code visir_copy_parameters(cpl_parameterlist * dest,
580 const cpl_parameterlist * src)
582 for (
const cpl_parameter * p = cpl_parameterlist_get_first_const(src);
583 p != NULL; p = cpl_parameterlist_get_next_const(src)) {
584 cpl_parameter * par =
585 cpl_parameterlist_find(dest, cpl_parameter_get_name(p));
590 cpl_type t = cpl_parameter_get_type(par);
591 if (t == CPL_TYPE_BOOL)
592 cpl_parameter_set_bool(par, cpl_parameter_get_bool(p));
593 else if (t == CPL_TYPE_INT)
594 cpl_parameter_set_int(par, cpl_parameter_get_int(p));
595 else if (t == CPL_TYPE_DOUBLE)
596 cpl_parameter_set_double(par, cpl_parameter_get_double(p));
597 else if (t == CPL_TYPE_STRING)
598 cpl_parameter_set_string(par, cpl_parameter_get_string(p));
605 return cpl_error_get_code();
620 visir_init_recipe(
const char * name,
int (*get_info)(cpl_pluginlist *),
621 cpl_pluginlist * plugins)
623 cpl_recipe * recipe = cpl_calloc(1,
sizeof(cpl_recipe));
625 cpl_plugin * pl = cpl_pluginlist_find (plugins, name);
626 cpl_plugin_copy ((cpl_plugin *) & recipe->interface, pl);
644 visir_run_recipe(cpl_recipe * recipe,
645 cpl_frameset * framelist,
const cpl_parameterlist * parlist,
646 cpl_error_code (*set_parlist)(cpl_parameterlist *,
647 const cpl_parameterlist *))
649 cpl_plugin * pl = &recipe->interface;
650 cpl_plugin_func plugin_func_init = cpl_plugin_get_init(pl);
651 cpl_plugin_func plugin_func_exec = cpl_plugin_get_exec(pl);
652 cpl_plugin_func plugin_func_deinit = cpl_plugin_get_deinit(pl);
656 recipe->frames = framelist;
658 plugin_func_init(&recipe->interface);
660 set_parlist(recipe->parameters, parlist);
661 plugin_func_exec(&recipe->interface);
662 plugin_func_deinit(&recipe->interface);
665 return cpl_error_get_code();
687 visir_prepare_frameset(
const cpl_frameset * frameset,
688 const char ** tagmap,
size_t ntags,
691 cpl_frameset * nlist = cpl_frameset_new();
692 cx_list * _nlist = cx_list_new();
693 cpl_ensure(ntags % 2 == 0, CPL_ERROR_ILLEGAL_INPUT, nlist);
695 FOR_EACH_FRAMESET_C(frame, frameset) {
696 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_PRODUCT) {
697 cpl_frame * frm = cpl_frame_duplicate(frame);
698 cpl_frame_set_group(frm, CPL_FRAME_GROUP_RAW);
699 cpl_frame_set_level(frm, CPL_FRAME_LEVEL_NONE);
700 for (
size_t i = 0; i < ntags; i += 2)
701 if (strcmp(tagmap[i], cpl_frame_get_tag(frm)) == 0)
702 cpl_frame_set_tag(frm, tagmap[i + 1]);
704 cx_list_push_back(_nlist, frm);
706 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB)
707 cx_list_push_back(_nlist, cpl_frame_duplicate(frame));
710 cx_list_sort(_nlist, (cx_compare_func)visir_cmp_frm_fn);
712 cx_list_reverse(_nlist);
716 cpl_frameset_insert(nlist, cx_list_get(_nlist, it));
717 cx_list_delete(_nlist);
732 cpl_frameset * visir_remove_modified_calib(cpl_frameset * set)
734 cpl_frameset * cleanset = cpl_frameset_new();
735 FOR_EACH_FRAMESET(frame, set) {
736 if (cpl_frame_get_group(frame) == CPL_FRAME_GROUP_CALIB &&
737 strcmp(cpl_frame_get_tag(frame),
738 "STATIC_MASK") == 0) {
741 cpl_frameset_insert(cleanset, cpl_frame_duplicate(frame));
743 cpl_frameset_delete(set);
759 static cpl_frameset *
760 visir_wait_for_child(pid_t pid, FILE * rpipe)
762 char * rbuffer = NULL;
766 cpl_frameset * result = NULL;
771 cpl_ensure(rpipe != NULL, CPL_ERROR_NULL_INPUT, NULL);
772 skip_if(fread(&err,
sizeof(err), 1, rpipe) != 1);
773 cpl_error_set(cpl_func, err);
775 skip_if(fread(&size,
sizeof(size), 1, rpipe) != 1);
777 rbuffer = cpl_malloc(size);
778 skip_if(fread(rbuffer, size, 1, rpipe) != 1);
780 result = visir_frameset_deserialize(rbuffer, NULL);
785 if (waitpid(pid, &status, 0) != pid) {
786 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
787 "%s", strerror(errno));
789 else if (WIFSIGNALED(status)) {
790 cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
791 "Process killed by signal %d", WTERMSIG(status));
793 else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
794 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
795 "Process failed with code %d",
796 WEXITSTATUS(status));
816 remove_tempdir(
const cpl_parameterlist * parlist,
const char* recipename,
819 const cpl_boolean
delete =
820 irplib_parameterlist_get_bool(parlist, PACKAGE,
821 recipename,
"delete-temp");
824 char * cmd = cpl_sprintf(
"rm -rf \"%s\"", tmpdir);
825 cpl_msg_info(cpl_func,
"Removing temporary directory: %s", tmpdir);
826 if (WEXITSTATUS(system(cmd)) != 0)
827 cpl_msg_warning(cpl_func,
"Removing temporary "
828 "directory %s failed", tmpdir);
832 cpl_msg_info(cpl_func,
"Keeping temporary directory: %s", tmpdir);
846 visir_tmpdir_exec(
const char * recipename, cpl_plugin * plugin,
847 int (*
function)(cpl_frameset *,
const cpl_parameterlist *))
849 char tmpdir[strlen(recipename) + 8];
850 cpl_boolean have_tmpdir = CPL_FALSE;
851 cpl_errorstate cleanstate = cpl_errorstate_get();
852 cpl_recipe * recipe = (cpl_recipe *)plugin;
853 sprintf(tmpdir,
"%s_XXXXXX", recipename);
855 have_tmpdir = visir_get_tempdir(tmpdir);
856 skip_if(have_tmpdir != CPL_TRUE);
858 cpl_msg_info(cpl_func,
"Working in temporary directory: %s", tmpdir);
861 if (chdir(tmpdir) != 0) {
862 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
863 "Could not change to temporary directory %s", tmpdir);
867 FOR_EACH_FRAMESET(frm, recipe->frames) {
868 if (cpl_frame_get_filename(frm)[0] !=
'/') {
869 char * buf = cpl_sprintf(
"../%s", cpl_frame_get_filename(frm));
870 cpl_frame_set_filename(frm, buf);
875 cpl_error_code err = cpl_recipedefine_exec(plugin,
function)
876 ? (int)cpl_error_set_where(cpl_func) : 0;
878 if (chdir(
"..") != 0) {
879 return cpl_error_set_message(cpl_func, CPL_ERROR_FILE_IO,
880 "Could not change back to base directory");
884 skip_if(visir_move_products(recipe->frames,
".", tmpdir));
889 remove_tempdir(recipe->parameters, recipename, tmpdir);
892 if (!cpl_errorstate_is_equal(cleanstate))
893 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
895 return cpl_error_get_code();
910 visir_forking_exec(
const char * recipename, cpl_plugin * plugin,
911 int (*
function)(cpl_frameset *,
const cpl_parameterlist *))
913 char tmpdir[strlen(recipename) + 8];
914 cpl_boolean have_tmpdir = CPL_FALSE;
915 cpl_errorstate cleanstate = cpl_errorstate_get();
916 cpl_recipe * recipe = (cpl_recipe *)plugin;
917 FILE * pipe_stream = NULL;
919 static const int READ = 0, WRITE = 1;
920 sprintf(tmpdir,
"%s_XXXXXX", recipename);
923 struct sigaction sa, sa_orig;
924 sa.sa_handler = SIG_IGN;
925 sigemptyset(&sa.sa_mask);
927 skip_if(sigaction(SIGINT, &sa, &sa_orig) != 0);
929 have_tmpdir = visir_get_tempdir(tmpdir);
930 skip_if(have_tmpdir != CPL_TRUE);
932 cpl_msg_info(cpl_func,
"Working in temporary directory: %s", tmpdir);
934 skip_if(pipe(pipe_fd) != 0);
938 close(pipe_fd[READ]);
939 close(pipe_fd[WRITE]);
940 cpl_error_set_message(cpl_func, CPL_ERROR_UNSPECIFIED,
941 "fork failed: %s", strerror(errno));
946 sigaction(SIGINT, &sa_orig, NULL);
949 close(pipe_fd[READ]);
950 pipe_stream = fdopen(pipe_fd[WRITE],
"w");
953 if (!pipe_stream || chdir(tmpdir) != 0) {
954 close(pipe_fd[WRITE]);
959 FOR_EACH_FRAMESET(frm, recipe->frames) {
960 if (cpl_frame_get_filename(frm)[0] !=
'/') {
961 char * buf = cpl_sprintf(
"../%s", cpl_frame_get_filename(frm));
962 cpl_frame_set_filename(frm, buf);
967 cpl_error_code err = cpl_recipedefine_exec(plugin,
function)
968 ? (int)cpl_error_set_where(cpl_func) : 0;
970 if (err == CPL_ERROR_NONE) {
971 assert((
void*)recipe == (
void*)plugin);
972 err = visir_send_frameset(pipe_stream, recipe->frames);
979 close(pipe_fd[WRITE]);
980 pipe_stream = fdopen(pipe_fd[READ],
"r");
981 skip_if(pipe_stream == NULL);
983 recipe->frames = visir_wait_for_child(pid, pipe_stream);
985 skip_if(recipe->frames == NULL);
988 skip_if(visir_move_products(recipe->frames,
".", tmpdir));
994 remove_tempdir(recipe->parameters, recipename, tmpdir);
997 if (!cpl_errorstate_is_equal(cleanstate))
998 cpl_errorstate_dump(cleanstate, CPL_FALSE, NULL);
1000 return cpl_error_get_code();
1012 double visir_utils_get_exptime(
const int nnod,
const cpl_propertylist * plist)
1025 const double value = 2 * dit * ndit * nnod * ncycles * navrg;
1028 cpl_msg_error(cpl_func,
"Illegal exposure time "
1029 "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
1030 dit, ndit, ncycles, nnod, value);
1048 double * visir_utils_get_wls(
const irplib_framelist *
self)
1052 double * wls = NULL;
1059 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
1062 wls = cpl_malloc(size *
sizeof(
double));
1065 for (i=0; i < size; i++) {
1066 const cpl_propertylist * plist
1076 if (cpl_error_get_code()) {
1095 cpl_image * visir_create_disk_intimage(
1108 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
1109 pintima = cpl_image_get_data_int(intima);
1112 for (j=0;j<ny ; j++) {
1113 for (i=0;i<nx ; i++) {
1114 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
1115 if (dist < radius*radius) {
1116 pintima[i+j*nx] = 1;
1118 pintima[i+j*nx] = 0;
1137 cpl_image * visir_create_ring_intimage(
1148 if (radius1 >= radius2) {
1149 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1150 "Small ring radius %d larger than big "
1151 "ring radius %d", radius1, radius2);
1154 if ((nx - x_pos) < radius2 || x_pos < radius2 ||
1155 (ny - y_pos) < radius2 || y_pos < radius2) {
1156 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1157 "Image of size [%d,%d] with object at "
1158 "[%d,%d] too small to create ring mask of "
1159 "radius %d", nx, ny, x_pos, y_pos, radius2);
1164 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
1165 pintima = cpl_image_get_data_int(intima);
1168 for (
int j=0;j<ny ; j++) {
1169 for (
int i=0;i<nx ; i++) {
1170 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
1171 if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
1172 pintima[i+j*nx] = 1;
1174 pintima[i+j*nx] = 0;
1193 double visir_image_sigma_clip(
const cpl_image *
self,
double * pstdev)
1195 const int dimx = cpl_image_get_size_x(
self);
1196 const int dimy = cpl_image_get_size_y(
self);
1197 const cpl_type type = cpl_image_get_type(
self);
1200 cpl_image * noise = cpl_image_new(dimx, dimy, type);
1201 cpl_mask * bpm = NULL;
1202 cpl_mask * kernel = cpl_mask_new(3, 3);
1203 const int niterations = 5;
1204 const double sigma = 3.0;
1205 const double median_corr = 0.94;
1206 double bgnoise = -1;
1212 bug_if(cpl_mask_not(kernel));
1213 bug_if(cpl_image_filter_mask(noise,
self, kernel, CPL_FILTER_MEDIAN,
1214 CPL_BORDER_FILTER));
1217 bug_if (cpl_image_subtract(noise,
self));
1219 for (i=0; i < niterations ; i++) {
1222 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
1224 const double mean = cpl_stats_get_mean(stats);
1225 const double stdev = cpl_stats_get_stdev(stats);
1228 const double low_thresh = mean - sigma * stdev;
1229 const double high_thresh = mean + sigma * stdev;
1232 cpl_stats_delete(stats);
1238 bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
1242 bug_if (cpl_mask_not(bpm));
1244 bug_if (cpl_image_reject_from_mask(noise, bpm));
1246 cpl_mask_delete(bpm);
1251 if (pstdev != NULL) {
1255 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
1258 bgnoise = cpl_stats_get_stdev(stats);
1259 *pstdev = cpl_image_get_median(
self) - cpl_stats_get_mean(stats);
1261 cpl_stats_delete(stats);
1264 bgnoise = cpl_image_get_stdev(noise);
1269 bgnoise /= median_corr;
1273 if (cpl_error_get_code())
1274 cpl_msg_error(cpl_func,
"Computation of background noise using sigma=%g"
1275 " failed in iteration %d of %d", sigma, i+1, niterations);
1277 cpl_mask_delete(kernel);
1278 cpl_mask_delete(bpm);
1279 cpl_image_delete(noise);
1295 double visir_img_phot_sigma_clip(
const cpl_image *
self)
1298 const double noise = visir_image_sigma_clip(
self, NULL);
1300 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
1325 int visir_star_find(
const cpl_vector * v_ra,
const cpl_vector * v_dec,
1326 double ra,
double dec,
double maxdist,
double * pdist)
1328 const int nra = cpl_vector_get_size(v_ra);
1329 const int ndec = cpl_vector_get_size(v_dec);
1336 cpl_ensure(nra > 0, cpl_error_get_code(), -2);
1337 cpl_ensure(ndec > 0, cpl_error_get_code(), -3);
1342 cpl_ensure(nra == ndec, CPL_ERROR_INCOMPATIBLE_INPUT, -4);
1344 cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
1347 for (i=0 ; i < nra ; i++) {
1348 const double rai = cpl_vector_get(v_ra, i);
1349 const double deci = cpl_vector_get(v_dec, i);
1350 const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
1352 cpl_msg_debug(cpl_func,
"DISTANCE (RAi,DECi)=(%g,%g) <=> "
1353 "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
1355 if (i == 0 || gdist < dmin) {
1361 if (pdist != NULL) *pdist = dmin;
1364 if (dmin > maxdist) {
1365 cpl_msg_error(cpl_func,
"Nearest standard star (%d of %d) at (RA,DEC)="
1366 "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
1367 1+minind, nra, cpl_vector_get(v_ra, minind),
1368 cpl_vector_get(v_dec, minind), ra, dec, dmin, maxdist);
1369 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
1395 cpl_error_code visir_star_convert(
const char * line,
int ra_hh,
int ra_mm,
1396 double ra_ss,
char isign,
int dec_hh,
1397 int dec_mm,
double dec_ss,
1398 const double * jys,
int njys,
1399 double * pra,
double * pdec)
1414 else if (isign ==
'-')
1417 cpl_msg_error(cpl_func,
"Line has illegal declination-sign character "
1418 "(%c): %s", isign, line);
1419 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1423 cpl_msg_error(cpl_func,
"Line has negative RA hh (%d): %s",
1425 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1428 cpl_msg_error(cpl_func,
"Line has negative RA mm (%d): %s",
1430 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1433 cpl_msg_error(cpl_func,
"Line has too large RA mm (%d): %s ",
1435 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1438 cpl_msg_error(cpl_func,
"Line has negative RA ss (%g): %s",
1440 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1443 cpl_msg_error(cpl_func,
"Line has too large RA ss (%g): %s ",
1445 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1449 cpl_msg_error(cpl_func,
"Line has negative DEC hh (%d): %s",
1451 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1454 cpl_msg_error(cpl_func,
"Line has negative DEC mm (%d): %s",
1456 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1459 cpl_msg_error(cpl_func,
"Line has too large DEC mm (%d): %s ",
1461 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1464 cpl_msg_error(cpl_func,
"Line has negative DEC ss (%g): %s",
1466 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1469 cpl_msg_error(cpl_func,
"Line has too large DEC ss (%g): %s ",
1471 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1474 *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
1475 if (*pra >= 360.0) {
1476 cpl_msg_error(cpl_func,
"Line has too large RA (%g): %s ",
1478 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1481 *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
1483 cpl_msg_error(cpl_func,
"Line has too large RA (%g): %s ",
1485 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1487 if (*pdec < -90.0) {
1488 cpl_msg_error(cpl_func,
"Line has too small RA (%g): %s ",
1490 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1493 for (i=0; i < njys; i++)
if (jys[i] <= 0.0) {
1494 cpl_msg_error(cpl_func,
"Line has non-positive Jy value (%g) at %d: %s ",
1496 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1499 return CPL_ERROR_NONE;
1517 cpl_table * visir_table_new_xypos(
const cpl_imagelist * images,
1520 cpl_errorstate cleanstate = cpl_errorstate_get();
1521 const int nsize = cpl_imagelist_get_size(images);
1522 double psigmas[] = {5, 2, 1, 0.5};
1523 cpl_vector * sigmas = NULL;
1524 cpl_table *
self = NULL;
1525 const int nsigmas =
sizeof(psigmas)/
sizeof(
double);
1529 cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
1530 cpl_ensure(label, CPL_ERROR_NULL_INPUT, NULL);
1531 cpl_ensure(!strcmp(label,
"FLUX") || !strcmp(label,
"FWHM"),
1532 CPL_ERROR_UNSUPPORTED_MODE, NULL);
1534 self = cpl_table_new(nsize);
1536 skip_if (cpl_table_new_column(
self,
"X_POS", CPL_TYPE_DOUBLE));
1537 skip_if (cpl_table_new_column(
self,
"Y_POS", CPL_TYPE_DOUBLE));
1539 if (!strcmp(label,
"FLUX")) {
1541 skip_if (cpl_table_new_column(
self, label, CPL_TYPE_DOUBLE));
1543 skip_if (cpl_table_new_column(
self,
"X_FWHM", CPL_TYPE_DOUBLE));
1544 skip_if (cpl_table_new_column(
self,
"Y_FWHM", CPL_TYPE_DOUBLE));
1547 sigmas = cpl_vector_wrap(4, psigmas);
1548 skip_if (sigmas == NULL);
1550 cpl_msg_info(cpl_func,
"Detecting apertures using %d sigma-levels "
1551 "ranging from %g down to %g", nsigmas, psigmas[0],
1552 psigmas[nsigmas-1]);
1556 for (i=0 ; i < nsize ; i++) {
1557 const cpl_image * image = cpl_imagelist_get_const(images, i);
1558 cpl_apertures * apert;
1572 apert = cpl_apertures_extract(image, sigmas, &isigma);
1574 if (apert != NULL && cpl_error_get_code()) {
1576 cpl_msg_error(cpl_func,
"cpl_apertures_extract() returned non-NULL "
1577 "while setting the CPL error-state to '%s' at '%s'",
1578 cpl_error_get_message(), cpl_error_get_where());
1579 cpl_msg_debug(cpl_func,
"Deleting the spurious aperture list at %p:",
1581 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
1582 cpl_apertures_dump(apert, stdout);
1583 cpl_apertures_delete(apert);
1587 if (apert != NULL &&
1589 cpl_apertures_get_flux(apert, iflux) > 0) {
1591 posx = cpl_apertures_get_centroid_x(apert, iflux);
1592 posy = cpl_apertures_get_centroid_y(apert, iflux);
1593 flux = cpl_apertures_get_flux(apert, iflux);
1595 cpl_image_get_fwhm(image, (
int)posx, (
int)posy, &fwhmx, &fwhmy);
1597 cpl_msg_info(cpl_func,
"Detected an aperture with flux=%g at "
1598 "sigma=%g, at position: %g %g", flux,
1599 psigmas[isigma], posx, posy);
1603 if (apert == NULL || cpl_error_get_code()) {
1604 visir_error_reset(
"Aperture detection in image %d of %d failed",
1607 }
else if (flux <= 0) {
1608 cpl_msg_warning(cpl_func,
"Ignoring %d-pixel aperture %d (out of "
1609 "%d) in file %d of %d with non-positive flux: %g",
1610 (
int)cpl_apertures_get_npix(apert, iflux), iflux,
1611 (
int)cpl_apertures_get_size(apert), i+1, nsize,
1616 cpl_apertures_delete(apert);
1619 skip_if (cpl_table_set_double(
self,
"X_POS", i, posx));
1620 skip_if (cpl_table_set_double(
self,
"Y_POS", i, posy));
1623 skip_if (cpl_table_set_double(
self,
"FLUX", i, flux));
1625 skip_if (cpl_table_set_double(
self,
"X_FWHM", i, fwhmx));
1626 skip_if (cpl_table_set_double(
self,
"Y_FWHM", i, fwhmy));
1632 if (nfail == nsize) {
1633 cpl_msg_error(cpl_func,
"Aperture detection failed in all %d images",
1635 visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
1641 cpl_vector_unwrap(sigmas);
1643 if (
self && cpl_error_get_code()) {
1644 cpl_table_delete(
self);
1659 int visir_vector_minpos(
const cpl_vector * v)
1661 const double * x = cpl_vector_get_data_const(v);
1662 const int n = cpl_vector_get_size(v);
1666 cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
1668 for (i = 1; i < n; i++)
if (x[i] < x[minpos]) minpos = i;
1689 cpl_error_code visir_bivector_load(cpl_bivector *
self, FILE * stream)
1697 cpl_ensure_code(
self, CPL_ERROR_NULL_INPUT);
1698 cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
1701 v1 = cpl_bivector_get_x(
self);
1702 v2 = cpl_bivector_get_y(
self);
1704 xsize = cpl_vector_get_size(v1);
1705 ysize = cpl_vector_get_size(v2);
1707 while (fgets(line, 1024, stream) != NULL) {
1709 if (line[0] !=
'#' && sscanf(line,
"%lg %lg", &x, &y) == 2) {
1716 cpl_vector_set_size(v1, xsize);
1720 cpl_vector_set_size(v2, ysize);
1722 cpl_vector_set(v1, np, x);
1723 cpl_vector_set(v2, np, y);
1729 cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
1732 if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
1733 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
1736 return CPL_ERROR_NONE;
1754 double visir_star_dist_min(
const double * pras,
const double * pdecs,
int nloc,
1755 int * piloc1,
int * piloc2)
1762 assert( pras != NULL);
1763 assert( pdecs != NULL);
1764 assert( piloc1 != NULL);
1765 assert( piloc2 != NULL);
1768 for (j = 0; j < nloc; j++) {
1769 for (i = 0; i < j; i++) {
1770 const double dist = visir_great_circle_dist(pras[i], pdecs[i],
1777 if (dist < VISIR_STAR_MAX_RADIUS)
1778 cpl_msg_warning(cpl_func,
"The two stars (%d,%d) have a distance"
1779 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
1802 const char ** visir_framelist_set_tag(irplib_framelist *
self,
1803 char * (*pftag)(
const cpl_frame *,
1804 const cpl_propertylist *,
1811 const char ** taglist = NULL;
1814 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1815 cpl_ensure(
self != NULL, CPL_ERROR_NULL_INPUT, NULL);
1816 cpl_ensure(pftag != NULL, CPL_ERROR_NULL_INPUT, NULL);
1817 cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
1821 cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
1825 for (iframe = 0; iframe < size ; iframe++) {
1827 const cpl_propertylist * plist
1830 const char * newtag;
1835 cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
1836 cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
1838 tag = (*pftag)(frame, plist, iframe);
1840 cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
1844 (void)cpl_frame_set_tag(frame, tag);
1847 newtag = cpl_frame_get_tag(frame);
1849 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
1852 for (i=0; i < *pntags; i++)
1853 if (strcmp(newtag, taglist[i]) == 0)
break;
1859 taglist = (
const char **)cpl_realloc(taglist, *pntags *
1860 sizeof(
const char *));
1861 taglist[i] = newtag;
1881 cpl_error_code visir_qc_append_background(cpl_propertylist *
self,
1882 const irplib_framelist * rawframes,
1883 int icol1,
int icol2)
1887 const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
1891 bug_if (cpl_propertylist_append_double(
self,
"ESO QC BACKGD MEAN",
1896 return cpl_error_get_code();
1911 cpl_error_code visir_qc_append_capa(cpl_propertylist *
self,
1912 const irplib_framelist * rawframes)
1915 cpl_errorstate cleanstate = cpl_errorstate_get();
1916 const cpl_propertylist * plist
1923 capa = visir_get_capa(plist);
1925 if (cpl_error_get_code()) {
1928 cpl_msg_info(cpl_func,
"Could not determine capa");
1929 cpl_errorstate_set(cleanstate);
1931 bug_if (cpl_propertylist_append_string(
self,
"ESO QC CAPA", capa));
1936 return cpl_error_get_code();
1949 cpl_error_code visir_qc_append_filter(cpl_propertylist *
self,
1950 const irplib_framelist * rawframes)
1953 const cpl_propertylist * plist
1960 bug_if (cpl_propertylist_append_string(
self,
"ESO QC FILTER", value));
1964 return cpl_error_get_code();
1977 cpl_error_code visir_qc_append_exptime(cpl_propertylist *
self,
1978 const irplib_framelist * rawframes)
1980 const cpl_propertylist * plist
1986 const double value = visir_utils_get_exptime(nnod, plist);
1990 bug_if (cpl_propertylist_append_double(
self,
"ESO QC EXPTIME", value));
1994 return cpl_error_get_code();
2012 static double visir_great_circle_dist(
double ra1,
double dec1,
2013 double ra2,
double dec2)
2017 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
2018 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
2020 dec1 *= CPL_MATH_RAD_DEG;
2021 dec2 *= CPL_MATH_RAD_DEG;
2023 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
2042 static double ra_hms2deg(
int hh,
int mm,
double ss)
2044 return 15.0 * dec_hms2deg(hh, mm, ss);
2060 static double dec_hms2deg(
int dd,
int mm,
double ss)
2062 return ((
double)ss/60.0 + (
double)mm)/60.0 + dd;
2079 static double visir_hcycle_background(
const irplib_framelist * rawframes,
2080 int icol1,
int icol2)
2082 cpl_imagelist * iset = NULL;
2091 skip_if (nfiles < 1);
2093 if (icol1 == 0) icol1 = VISIR_BACKGD_START;
2094 if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
2096 cpl_msg_info(cpl_func,
"Computing Half-cycle background level from column %d "
2097 "through %d", icol1, icol2);
2100 for (i=0; i < nfiles; i++) {
2106 for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
2107 const double median =
2108 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
2109 VISIR_BACKGD_START, icol1,
2110 VISIR_BACKGD_STOP, icol2);
2114 if (median != median) {
2118 cpl_msg_error(cpl_func,
"Image window (%d, %d, %d, %d) "
2119 "(image %d of %d) in %s (frame %d of %d) "
2121 VISIR_BACKGD_START, icol1,
2122 VISIR_BACKGD_STOP, icol2,
2123 j+1, (
int)cpl_imagelist_get_size(iset),
2124 cpl_frame_get_filename(frame), i+1, nfiles);
2125 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
2131 cpl_imagelist_delete(iset);
2138 bgmean = bgsum / nsum;
2142 cpl_imagelist_delete(iset);
2145 return bgmean - VISIR_HCYCLE_OFFSET;
2162 visir_get_subpixel_maxpos(
const cpl_image * img, cpl_size x, cpl_size y,
2163 double * xsub,
double * ysub)
2166 const cpl_size nx = cpl_image_get_size_x(img);
2167 const cpl_size ny = cpl_image_get_size_y(img);
2171 if (x - 1 > 0 && x + 1 <= nx) {
2173 cpl_image_get(img, x - 1, y, &bad),
2174 cpl_image_get(img, x - 0, y, &bad),
2175 cpl_image_get(img, x + 1, y, &bad),
2178 *xsub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
2180 if (y - 1 > 0 && y + 1 <= ny) {
2182 cpl_image_get(img, x, y - 1, &bad),
2183 cpl_image_get(img, x, y - 0, &bad),
2184 cpl_image_get(img, x, y + 1, &bad),
2187 *ysub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
2190 return cpl_error_get_code();
2193 static inline unsigned long get_msb(
unsigned long a)
2196 unsigned long msb = 0;
2213 size_t visir_get_next_regular(
size_t a)
2221 if ((a & (a - 1)) == 0)
2224 if (5 > SIZE_MAX / a)
2227 size_t match = SIZE_MAX;
2233 size_t quotient = a % p35 != 0 ? a / p35 + 1 : a / p35;
2235 size_t p2 = 2 << get_msb(quotient - 1);
2237 size_t n = p2 * p35;
2260 cpl_image * template_fft;
2261 double template_stdev;
2271 irplib_aligned_free(cpl_image_unwrap(c->template_fft));
2293 visir_fftxcorrelate(
const cpl_image * atemplate,
const cpl_image * aimg,
2294 cpl_boolean normalize,
double * xshift,
double * yshift,
2297 const cpl_size Nxi = cpl_image_get_size_x(aimg);
2298 const cpl_size Nyi = cpl_image_get_size_y(aimg);
2299 const cpl_size Nxt = cpl_image_get_size_x(atemplate);
2300 const cpl_size Nyt = cpl_image_get_size_y(atemplate);
2302 const cpl_size Nxe = visir_get_next_regular(Nxi + Nxt - 1);
2303 const cpl_size Nye = visir_get_next_regular(Nyi + Nyt - 1);
2304 cpl_size txshift, tyshift;
2305 double subx = 0, suby = 0;
2306 cpl_image * img = NULL;
2307 cpl_image * zimg = NULL;
2308 cpl_image * ztemp = NULL;
2309 cpl_image * fft1 = NULL;
2310 cpl_image * fft2 = NULL;
2311 cpl_image * res = NULL;
2313 double template_stdev;
2315 cpl_fft_mode mode = getenv(
"VISIR_TEST_MODE") ? 0 : CPL_FFT_FIND_MEASURE;
2317 cpl_ensure_code(atemplate != NULL, CPL_ERROR_NULL_INPUT);
2318 cpl_ensure_code(aimg != NULL, CPL_ERROR_NULL_INPUT);
2320 if (cache == NULL || cache->initialized == 0) {
2322 cpl_image *
template = NULL;
2323 if (cpl_image_get_type(atemplate) != CPL_TYPE_FLOAT)
2324 template = cpl_image_cast(atemplate, CPL_TYPE_FLOAT);
2326 template = cpl_image_duplicate(atemplate);
2328 cpl_image_fill_rejected(
template, 0);
2330 skip_if(cpl_image_subtract_scalar(
template,
2331 visir_image_get_mean_fast(
template)));
2332 template_stdev = cpl_image_get_stdev(
template);
2334 buffer = irplib_aligned_calloc(32, Nxe * Nye,
sizeof(
float));
2335 ztemp = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2339 skip_if(cpl_image_flip(
template, 1));
2340 skip_if(cpl_image_flip(
template, 3));
2343 skip_if(cpl_image_copy(ztemp,
template, 1, 1));
2344 cpl_image_delete(
template);
2346 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
2347 sizeof(
float complex));
2348 fft2 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX,
2350 skip_if(cpl_fft_image(fft2, ztemp, CPL_FFT_FORWARD));
2352 cache->template_fft = fft2;
2353 cache->template_stdev = template_stdev;
2354 cache->initialized = 1;
2358 fft2 = cache->template_fft;
2359 template_stdev = cache->template_stdev;
2360 error_if(cpl_image_get_type(fft2) != CPL_TYPE_FLOAT_COMPLEX ||
2361 cpl_image_get_size_x(fft2) != Nxe / 2 + 1 ||
2362 cpl_image_get_size_y(fft2) != Nye, CPL_ERROR_ILLEGAL_INPUT,
2363 "Invalid fourier transformed template");
2368 buffer = irplib_aligned_calloc(32, Nxe * Nye,
sizeof(
float));
2369 zimg = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2370 if (cpl_image_get_type(aimg) != CPL_TYPE_FLOAT)
2371 img = cpl_image_cast(aimg, CPL_TYPE_FLOAT);
2373 img = cpl_image_duplicate(aimg);
2375 skip_if(img == NULL);
2377 cpl_image_fill_rejected(img, 0);
2380 skip_if(cpl_image_subtract_scalar(img,
2381 visir_image_get_mean_fast(img)));
2384 skip_if(cpl_image_copy(zimg, img, 1, 1));
2386 buffer = irplib_aligned_malloc(32, (Nxe / 2 + 1) * Nye *
2387 sizeof(
float complex));
2388 fft1 = cpl_image_wrap(Nxe / 2 + 1, Nye, CPL_TYPE_FLOAT_COMPLEX, buffer);
2390 skip_if(cpl_fft_image(fft1, zimg, CPL_FFT_FORWARD | mode));
2394 skip_if(visir_image_multiply_fast(fft1, fft2));
2396 buffer = irplib_aligned_malloc(32, Nxe * Nye *
sizeof(
float));
2397 res = cpl_image_wrap(Nxe, Nye, CPL_TYPE_FLOAT, buffer);
2398 skip_if(cpl_fft_image(res, fft1, CPL_FFT_BACKWARD | CPL_FFT_NOSCALE |
2401 skip_if(cpl_image_get_maxpos_window(res, Nxt / 2 , Nyt / 2,
2402 Nxt / 2 + Nxi, Nyt / 2 + Nyi,
2403 &txshift, &tyshift));
2405 if (max_correlation != NULL) {
2407 *max_correlation = cpl_image_get(res, txshift, tyshift, &rej);
2409 *max_correlation /= Nxe * Nye;
2412 double tstd = template_stdev;
2413 int mx = txshift - Nxt;
2414 int my = tyshift - Nyt;
2415 double istd= cpl_image_get_stdev_window(zimg,
2418 CX_MIN(Nxe, mx + Nxt),
2419 CX_MIN(Nye, my + Nyt));
2421 if (tstd * istd == 0)
2422 *max_correlation = 0;
2424 *max_correlation /= (tstd * istd * Nxt * Nyt);
2429 skip_if(visir_get_subpixel_maxpos(res, txshift, tyshift, &subx, &suby));
2430 if (xshift != NULL) {
2431 *xshift = txshift - Nxt + subx;
2433 if (yshift != NULL) {
2434 *yshift = tyshift - Nyt + suby;
2439 cpl_image_delete(img);
2441 irplib_aligned_free(cpl_image_unwrap(fft2));
2442 irplib_aligned_free(cpl_image_unwrap(fft1));
2443 irplib_aligned_free(cpl_image_unwrap(zimg));
2444 irplib_aligned_free(cpl_image_unwrap(ztemp));
2445 irplib_aligned_free(cpl_image_unwrap(res));
2447 return cpl_error_get_code();
2469 get_interpolation_points(
size_t x,
size_t y,
2470 size_t nx_,
size_t ny_, cpl_binary *bpm)
2472 ssize_t l = -1, r = -1 , u = -1, d = -1;
2477 ssize_t nx = (ssize_t)nx_;
2478 ssize_t ny = (ssize_t)ny_;
2479 cx_list * p = cx_list_new();
2489 if (l < 0 && xl >= 0 && bpm[IND(xl, y, nx)] == CPL_BINARY_0)
2491 if (r < 0 && xh < nx && bpm[IND(xh, y, nx)] == CPL_BINARY_0)
2493 if (d < 0 && yl >= 0 && bpm[IND(x, yl, nx)] == CPL_BINARY_0)
2495 if (u < 0 && yh < ny && bpm[IND(x, yh, nx)] == CPL_BINARY_0)
2500 if ((l != -1 && r != -1) || (d != -1 && u != -1) ||
2501 (xl < 0 && xh >= nx && yl < 0 && yh >= ny))
2507 cx_list_push_back(p, (cxcptr)(IND(r, y, nx)));
2509 cx_list_push_back(p, (cxcptr)(IND(l, y, nx)));
2511 cx_list_push_back(p, (cxcptr)(IND(x, u, nx)));
2513 cx_list_push_back(p, (cxcptr)(IND(x, d, nx)));
2538 visir_interpolate_rejected(cpl_image * img,
size_t ** ppoints,
size_t * n)
2540 cpl_mask * mask = cpl_image_get_bpm(img);
2541 float * data = cpl_image_get_data_float(img);
2542 cpl_binary * bpm = cpl_mask_get_data(mask);
2543 const size_t nx = (size_t)cpl_image_get_size_x(img);
2544 const size_t ny = (size_t)cpl_image_get_size_y(img);
2547 skip_if(data == NULL);
2549 if (ppoints == NULL || *ppoints == NULL) {
2551 cpl_binary * found = memchr(bpm, CPL_BINARY_1,
2552 sizeof(cpl_binary) * nx * ny);
2554 size_t * restrict pbpm = cpl_calloc(cpl_image_count_rejected(img) * 6,
2557 while (found != NULL) {
2558 const size_t ind = found - bpm;
2559 const size_t y = ind / nx;
2560 const size_t x = ind - y * nx;
2561 cx_list * p = get_interpolation_points(x, y, nx, ny, bpm);
2562 cx_list_iterator it = cx_list_begin(p);
2563 const size_t npix = cx_list_size(p);
2568 assert(pbpm[i - 1] <= 4);
2570 while (it != cx_list_end(p)) {
2571 const size_t lind = (size_t)cx_list_get(p, it);
2574 it = cx_list_next(p, it);
2576 data[ind] = sum / npix;
2579 found = memchr(found + 1, CPL_BINARY_1,
2580 sizeof(cpl_binary) * nx * ny - ind - 1);
2590 const size_t n_ = *n;
2591 size_t * restrict points = *ppoints;
2592 for (
size_t i = 0; i < n_;) {
2593 const size_t ind = points[i++];
2594 const size_t m = points[i++];
2596 for (
size_t j = 0; j < m; j++) {
2597 const size_t lind = points[i++];
2600 data[ind] = sum / m;
2604 cpl_image_accept_all(img);
2608 return cpl_error_get_code();
2611 static const cpl_image *
2612 image_const_row_view_create(
const cpl_image * img,
2616 const size_t dsz = cpl_type_get_sizeof(cpl_image_get_type(img));
2617 const cpl_size nx = cpl_image_get_size_x(img);
2618 const char * d = cpl_image_get_data_const(img);
2619 size_t offset = (ly - 1) * nx;
2620 cpl_size nny = uy - ly + 1;
2621 cpl_image * wimg = cpl_image_wrap(nx, nny, cpl_image_get_type(img),
2622 (
char*)d + offset * dsz);
2624 const cpl_mask * omask = cpl_image_get_bpm_const(img);
2626 cpl_mask * mask = cpl_mask_wrap(nx, nny,
2627 (cpl_binary*)cpl_mask_get_data_const(omask) + offset);
2628 cpl_mask_delete(cpl_image_set_bpm(wimg, mask));
2635 image_const_row_view_delete(
const cpl_image * img)
2637 cpl_mask_unwrap(cpl_image_unset_bpm((cpl_image*)(img)));
2638 cpl_image_unwrap((cpl_image *)img);
2650 visir_parallel_median_collapse(
const cpl_imagelist * l)
2653 return cpl_imagelist_collapse_median_create(l);
2655 cpl_ensure(l != NULL, CPL_ERROR_NULL_INPUT, NULL);
2656 cpl_ensure(cpl_imagelist_get_size(l) > 0,
2657 CPL_ERROR_ILLEGAL_INPUT, NULL);
2659 const size_t n = cpl_imagelist_get_size(l);
2660 const cpl_image * img = cpl_imagelist_get_const(l, 0);
2661 const size_t ny = cpl_image_get_size_y(img);
2662 const size_t nx = cpl_image_get_size_x(img);
2663 const size_t nthreads = CX_MIN(visir_get_num_threads(CPL_FALSE), ny);
2664 cpl_image * res = cpl_image_new(nx, ny, cpl_image_get_type(img));
2666 cpl_image_get_bpm(res);
2668 OMP_PRAGMA(omp parallel
for num_threads(nthreads))
2669 for (
size_t j = 0; j < nthreads; j++) {
2670 size_t ylow = j * (ny / nthreads) + 1;
2671 size_t yhigh = (j + 1) * (ny / nthreads);
2672 if (j == nthreads - 1)
2675 cpl_imagelist * view = cpl_imagelist_new();
2676 for (
size_t i = 0; i < n; i++) {
2677 const cpl_image * img = cpl_imagelist_get_const(l, i);
2678 const cpl_image * iview =
2679 image_const_row_view_create(img, ylow, yhigh);
2680 IRPLIB_DIAG_PRAGMA_PUSH_IGN(-Wcast-qual);
2681 cpl_imagelist_set(view, (cpl_image *)iview, i);
2682 IRPLIB_DIAG_PRAGMA_POP;
2686 cpl_image * r = cpl_imagelist_collapse_median_create(view);
2687 cpl_image_copy(res, r, 1, ylow);
2690 cpl_image_delete(r);
2691 for (
size_t i = 0; i < n; i++) {
2692 cpl_image * img = cpl_imagelist_get(view, i);
2693 image_const_row_view_delete(img);
2695 cpl_imagelist_unwrap(view);
2710 static const char * visir_get_capa(
const cpl_propertylist * plist)
2712 const char * capa =
"Pb with Capa";
2725 if (!strcmp(sval,
"IMG")) {
2729 }
else if (!strcmp(sval,
"SPC") || !strcmp(sval,
"SPCIMG")) {
2742 capa =
"Large Capa";
2743 }
else if (mean > 4.5) {
2744 capa =
"Small Capa";
2752 #ifdef VISIR_MASK_HAS
2774 static cpl_boolean visir_mask_has(
const cpl_mask *
self, cpl_binary value,
2777 const cpl_binary * pself = cpl_mask_get_data_const(
self);
2778 int size = cpl_mask_get_size_x(
self)
2779 * cpl_mask_get_size_y(
self);
2782 cpl_ensure(
self, CPL_ERROR_NULL_INPUT, CPL_FALSE);
2783 cpl_ensure(ngood >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
2784 cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
2785 cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
2786 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
2788 for (i = 0; i < ngood; i++) {
2790 const cpl_binary * ppos = memchr(pself, value, (
size_t)size);
2791 if (ppos == NULL)
break;
2793 size -= 1 + (int)(ppos - pself);
2797 return i == ngood ? CPL_TRUE : CPL_FALSE;
2809 size_t visir_upper_bound(
const cpl_vector * vec,
double val)
2811 const double * d = cpl_vector_get_data_const(vec);
2812 long count = cpl_vector_get_size(vec);
2816 long step = count / 2;
2817 long it = first + step;
2818 if (!(val < d[it])) {
2836 size_t visir_lower_bound(
const cpl_vector * vec,
double val)
2838 const double * d = cpl_vector_get_data_const(vec);
2839 long count = cpl_vector_get_size(vec);
2843 long step = count / 2;
2844 long it = first + step;
2869 cpl_image * visir_linintp_values(
const cpl_image * inp,
const cpl_bivector * ref)
2871 const double * data = cpl_image_get_data_double_const(inp);
2872 const cpl_vector * rx = cpl_bivector_get_x_const(ref);
2873 const cpl_vector * ry = cpl_bivector_get_y_const(ref);
2874 size_t nref = cpl_bivector_get_size(ref);
2875 size_t nx = cpl_image_get_size_x(inp);
2876 size_t ny = cpl_image_get_size_y(inp);
2877 cpl_image * res = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
2878 double * rdata = cpl_image_get_data_double(res);
2879 cpl_ensure(nref >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
2881 for (
size_t y = 0; y < ny; y++) {
2882 for (
size_t x = 0; x < nx; x++) {
2883 double val = data[y * nx + x];
2884 intptr_t ilo = visir_lower_bound(rx, val);
2903 rdata[y * nx + x] = cpl_vector_get(ry, 0);
2904 cpl_image_reject(res, x + 1, y + 1);
2906 else if (ilo == nref) {
2907 rdata[y * nx + x] = cpl_vector_get(ry, nref - 1);
2908 cpl_image_reject(res, x + 1, y + 1);
2911 double rx1 = cpl_vector_get(rx, ilo - 1);
2912 double rx2 = cpl_vector_get(rx, ilo);
2913 double ry1 = cpl_vector_get(ry, ilo - 1);
2914 double ry2 = cpl_vector_get(ry, ilo);
2915 double grad = (ry2 - ry1) / (rx2 - rx1);
2916 double y0 = ry1 - grad * rx1;
2917 rdata[y * nx + x] = grad * val + y0;
2945 fit_2d_gauss(
const cpl_image * img_,
const cpl_image * weights, cpl_size x, cpl_size y,
2946 double est_fwhmx,
double est_fwhmy,
2947 double * peak,
double * peak_err,
2948 double * major,
double * major_err,
2949 double * minor,
double * minor_err,
2950 double * angle,
double * angle_err)
2952 cpl_image * img = cpl_image_cast(img_, CPL_TYPE_DOUBLE);
2953 cpl_size llx = CX_MAX(x - est_fwhmx * 3, 1);
2954 cpl_size lly = CX_MAX(y - est_fwhmy * 3, 1);
2955 cpl_size urx = CX_MIN(x + est_fwhmx * 3, cpl_image_get_size_x(img));
2956 cpl_size ury = CX_MIN(y + est_fwhmy * 3, cpl_image_get_size_y(img));
2957 cpl_array * dpar = cpl_array_new(7, CPL_TYPE_DOUBLE);
2958 cpl_array * epar = cpl_array_new(7, CPL_TYPE_DOUBLE);
2959 cpl_matrix * cov = NULL;
2960 cpl_matrix * phys_cov = NULL;
2962 cpl_array_set_double(dpar, 0, cpl_image_get_median(img));
2963 cpl_array_set_double(dpar, 1, cpl_image_get_flux_window(img, llx, lly,
2965 cpl_array_set_double(dpar, 2, 0.);
2966 cpl_array_set_double(dpar, 3, x);
2967 cpl_array_set_double(dpar, 4, y);
2968 cpl_array_set_double(dpar, 5, est_fwhmx / 2.355);
2969 cpl_array_set_double(dpar, 6, est_fwhmx / 2.355);
2971 cpl_image * err = cpl_image_new(cpl_image_get_size_x(img),
2972 cpl_image_get_size_y(img),
2974 cpl_image_add_scalar(err, 1.);
2975 cpl_image_divide(err, weights);
2976 cpl_image_power(err, 0.5);
2978 skip_if(cpl_fit_image_gaussian(img, err,
2999 double * a = cpl_array_get_data_double(dpar);
3000 *peak = a[0] + a[1] /
3001 (CPL_MATH_2PI * a[5] * a[6] * sqrt(1.0 - a[2] * a[2]));
3003 cpl_msg_warning(cpl_func,
"2d gaussfit, could not determine peak");
3008 double * a = cpl_array_get_data_double(dpar);
3009 double * e = cpl_array_get_data_double(epar);
3015 double dB = sqrt(e[0]);
3016 double dA = sqrt(e[1]);
3017 double dsigx = sqrt(e[5]);
3018 double dsigy = sqrt(e[6]);
3019 double drho = sqrt(e[2]);
3021 double rho2 = rho * rho;
3022 double x = CPL_MATH_PI * CPL_MATH_PI * 4 * sigx * sigx * sigy * sigy;
3024 sqrt(A2 * drho * drho * rho2 /(x * pow(-rho2 + 1.0, 3)) +
3025 A2 * dsigx * dsigx /(x * sigx * sigx * (-rho2 + 1.0)) +
3026 A2 * dsigy * dsigy /(x * sigy * sigy * (-rho2 + 1.0)) +
3027 dA * dA/(x * (-rho2 + 1.0)) + dB * dB);
3028 if (isnan(*peak_err)) {
3033 *major *= CPL_MATH_FWHM_SIG;
3034 if (isnan(*major)) {
3035 cpl_msg_warning(cpl_func,
3036 "2d gaussfit, could not determine major axis");
3041 *minor *= CPL_MATH_FWHM_SIG;
3042 if (isnan(*minor)) {
3043 cpl_msg_warning(cpl_func,
3044 "2d gaussfit, could not determine minor axis");
3049 *major_err = sqrt(cpl_matrix_get(phys_cov, 1, 1)) * CPL_MATH_FWHM_SIG;
3050 if (isnan(*major_err)) {
3055 *minor_err = sqrt(cpl_matrix_get(phys_cov, 2, 2)) * CPL_MATH_FWHM_SIG;
3056 if (isnan(*minor_err)) {
3061 *angle_err = sqrt(cpl_matrix_get(phys_cov, 0, 0));
3062 if (isnan(*angle_err)) {
3068 cpl_array_delete(dpar);
3069 cpl_array_delete(epar);
3070 cpl_image_delete(err);
3071 cpl_image_delete(img);
3072 cpl_matrix_delete(phys_cov);
3073 cpl_matrix_delete(cov);
3075 return cpl_error_get_code();
3095 fit_1d_gauss(
const cpl_vector * xv,
const cpl_vector * yv, cpl_vector * dyv,
3096 double * x0,
double * x0_err,
3097 double * peak,
double * peak_err,
3098 double * sigma_,
double * sigma_err)
3100 double sigma, area, offset;
3101 cpl_matrix * cov = NULL;
3102 skip_if(cpl_vector_fit_gaussian(xv, NULL,
3104 CPL_FIT_CENTROID | CPL_FIT_STDEV |
3105 CPL_FIT_AREA | CPL_FIT_OFFSET,
3106 x0, &sigma, &area, &offset,
3109 if (x0 && isnan(*x0)) {
3110 cpl_msg_warning(cpl_func,
"1d gaussfit, could not determine mean");
3114 *x0_err = sqrt(cpl_matrix_get(cov, 0, 0));
3115 if (isnan(*x0_err)) {
3121 if (isnan(*sigma_)) {
3122 cpl_msg_warning(cpl_func,
3123 "1d gaussfit, could not determine sigma");
3128 *peak = area / sqrt(2 * CPL_MATH_PI * sigma * sigma) + offset;
3130 cpl_msg_warning(cpl_func,
"1d gaussfit, could not determine peak");
3135 double dsig = sqrt(cpl_matrix_get(cov, 1, 1));
3136 double dA = sqrt(cpl_matrix_get(cov, 2, 2));
3137 double dB = sqrt(cpl_matrix_get(cov, 3, 3));
3138 double pi2sig2 = 2 * CPL_MATH_PI * sigma * sigma;
3139 *peak_err = sqrt(dsig * dsig * area * area /
3140 (2 * CPL_MATH_PI * pi2sig2 * sigma * sigma) +
3141 dA * dA / pi2sig2 + dB * dB);
3142 if (isnan(*peak_err)) {
3147 *sigma_err = sqrt(cpl_matrix_get(cov, 1, 1));
3148 if (isnan(*sigma_err)) {
3154 cpl_matrix_delete(cov);
3156 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.