37 #include "naco_pfits.h"
43 #include <gsl/gsl_multimin.h>
60 static int naco_vector_get_maxpos_window(
const cpl_vector *,
int,
int);
63 static int vector_index_compare(
const void *,
const void *);
66 static cpl_error_code naco_framelist_get_state(
const irplib_framelist *,
69 const cpl_propertylist *);
97 const cpl_vector * goffset,
99 const cpl_imagelist *
self)
102 cpl_image * d2d = NULL;
103 cpl_image * dspat1d = NULL;
104 cpl_vector * vspat1dp = NULL;
105 cpl_vector * vspat1di = NULL;
106 cpl_vector * vxc = NULL;
107 const int nsize = cpl_imagelist_get_size(
self);
108 const int maxerr = 20;
109 int gleni, glenprev = 0;
112 const int nz = (do_wave ? cpl_image_get_size_y : cpl_image_get_size_x)
113 (cpl_imagelist_get_const(
self, 0));
114 const char dirch = do_wave ?
'Y' :
'X';
115 const int direc = do_wave ? 1 : 0;
116 int ii, i, iprev = 0;
120 bug_if(
self == NULL);
122 bug_if(offset == NULL);
123 bug_if(goffset == NULL);
124 bug_if(cpl_vector_get_size(offset) != nsize);
125 bug_if(cpl_vector_get_size(goffset) != nsize);
128 for (ii = 0; ii < nsize; ii++) {
131 cpl_msg_info(cpl_func,
"%c-offset(%d:%d): %g", dirch, ii, i,
132 cpl_vector_get(goffset, i));
136 vxc = cpl_vector_new(maxerr);
139 for (ii = 0; ii < nsize; ii++) {
143 int irealfirst, ireallast;
146 double doff, dnewoff;
150 gleni = (int)round(cpl_vector_get(goffset, i));
153 d2d = cpl_image_cast(cpl_imagelist_get_const(
self, i), CPL_TYPE_DOUBLE);
156 dspat1d = cpl_image_collapse_create(d2d, direc);
158 cpl_image_delete(d2d);
161 cpl_vector_delete(vspat1di);
162 vspat1di = cpl_vector_wrap(nz, cpl_image_get_data_double(dspat1d));
163 (void)cpl_image_unwrap(dspat1d);
168 cpl_plot_vector(
"set grid;",
"t '1D-Profile i' w linespoints",
"",
179 halfoff = maxerr + abs(gleni - glenprev);
180 if (halfoff > nz-1) halfoff = nz - 1;
181 maxoff = 2 * halfoff + 1;
183 bug_if(cpl_vector_set_size(vxc, maxoff));
185 ixc0 = cpl_vector_correlate(vxc, vspat1di, vspat1dp);
189 irealfirst = halfoff - (glenprev - gleni) - maxerr;
190 ireallast = halfoff - (glenprev - gleni) + maxerr;
192 ixc = naco_vector_get_maxpos_window(vxc, irealfirst, ireallast);
196 cpl_msg_warning(cpl_func,
"%c-False maximum(%d:%d): %d <+. %d. "
197 "0 <= %d => %d < %d", dirch, ii, i, ixc0, ixc,
198 irealfirst, ireallast, maxoff);
201 ioff = ixc - halfoff;
202 doff = cpl_vector_get(goffset, i) - cpl_vector_get(goffset, iprev);
204 xci = cpl_vector_get(vxc, ixc);
206 if (xci < xcmin) xcmin = xci;
208 if (ioff != (
int)round(doff)) {
209 cpl_msg_warning(cpl_func,
"%c-XC(%d)=%g changes offset: %g - %g = "
210 "%g => %d = %d - %d", dirch, i, xci,
211 cpl_vector_get(goffset, i),
212 cpl_vector_get(goffset, iprev), doff, ioff,
214 dnewoff = (double)-ioff;
216 cpl_msg_info(cpl_func,
"%c-XC(%d)=%g confirms offset: %g - %g = %g "
217 "<=> %d = %d - %d", dirch, i, xci,
218 cpl_vector_get(goffset, i),
219 cpl_vector_get(goffset, iprev), doff, ioff,
224 bug_if(cpl_vector_set(offset, i, dnewoff));
227 cpl_plot_vector(
"set grid;",
"t 'Cross-correlation' w linespoints",
233 cpl_msg_info(cpl_func,
"Minimum 1D-spatial XC for %d sets: %g",
238 cpl_image_delete(d2d);
239 (void)cpl_image_unwrap(dspat1d);
240 cpl_vector_delete(vspat1dp);
241 cpl_vector_delete(vspat1di);
242 cpl_vector_delete(vxc);
244 return cpl_error_get_code();
259 cpl_image * copy = NULL;
260 int n = cpl_imagelist_get_size(
self);
263 bug_if(
self == NULL);
268 for (i=0; i < n; i += 2) {
269 cpl_image * first = cpl_imagelist_get(
self, i);
270 cpl_image * second = cpl_imagelist_get(
self, i+1);
272 bug_if(cpl_image_subtract(first, second));
274 copy = cpl_image_multiply_scalar_create(first, -1.0);
276 bug_if(cpl_imagelist_set(
self, copy, i+1));
283 cpl_image_delete(copy);
285 return cpl_error_get_code();
303 cpl_image * BA = NULL;
304 const int n = cpl_imagelist_get_size(
self);
308 bug_if(
self == NULL);
310 for (i=0; i < n; i++) {
311 const cpl_image * AB = cpl_imagelist_get(
self, i);
313 BA = cpl_image_multiply_scalar_create(AB, -1.0);
315 bug_if(cpl_imagelist_set(
self, BA, n+i));
322 cpl_image_delete(BA);
324 return cpl_error_get_code();
343 cpl_imagelist * copy = cpl_imagelist_new();
344 cpl_image * image = NULL;
345 cpl_image * im_neg = NULL;
346 int j = cpl_imagelist_get_size(
self);
350 skip_if(
self == NULL);
354 for (; j >= 0; j--, i++) {
355 bug_if(cpl_imagelist_set(copy, cpl_imagelist_unset(
self, j), i));
364 for (; i >= 0; i--, j += 2) {
365 image = cpl_imagelist_unset(copy, i);
368 im_neg = cpl_image_duplicate(image);
369 bug_if(cpl_image_threshold(im_neg, -FLT_MAX, 0.0, 0.0, 0.0));
370 bug_if(cpl_image_multiply_scalar(im_neg, -1.0));
374 bug_if(cpl_image_threshold(image, 0.0, FLT_MAX, 0.0, 0.0));
376 bug_if(cpl_imagelist_set(
self, image, j));
379 bug_if(cpl_imagelist_set(
self, im_neg, j+1));
386 cpl_image_delete(image);
387 cpl_image_delete(im_neg);
388 cpl_imagelist_delete(copy);
390 return CPL_ERROR_NONE;
413 const char * specmode;
414 const char * slitname;
419 bug_if(
self == NULL);
420 bug_if(plist == NULL);
423 specmode = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SPECMODE);
424 skip_if(cpl_error_get_code());
426 slitname = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SLITNAME);
427 skip_if(cpl_error_get_code());
429 dit = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_DIT);
430 skip_if(cpl_error_get_code());
432 wlen = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_CWLEN);
433 skip_if(cpl_error_get_code());
435 tag = cpl_sprintf(
"%s:%s:%.5f:%.5f", specmode, slitname, wlen, dit);
440 if (cpl_error_get_code()) {
483 const irplib_framelist * onofflist,
484 const cpl_propertylist * onoffkeys)
486 cpl_image * img_off = NULL;
487 cpl_image * diff = NULL;
492 skip_if (
self == NULL);
493 skip_if (onofflist == NULL);
495 skip_if(cpl_imagelist_get_size(
self) != 0);
503 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
507 for (ioff = 0, ion = 0, ndiff = 0; ioff < nfiles && ion < nfiles;
510 cpl_boolean need_on = CPL_TRUE;
512 const cpl_frame * frame;
517 for (; ioff < nfiles; ioff++) {
520 skip_if(naco_framelist_get_state(onofflist, ioff, CPL_FALSE,
521 &is_off, onoffkeys));
525 }
else if (need_on && ioff >= ion) {
533 if (ioff == nfiles)
break;
537 if (ion == ioff) ion++;
538 for (; ion < nfiles; ion++) {
542 skip_if(naco_framelist_get_state(onofflist, ion, CPL_TRUE,
551 if (ion == nfiles)
break;
555 name = cpl_frame_get_filename(frame);
559 diff = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
560 error_if(diff == NULL, cpl_error_get_code(),
561 "Could not load on-image from %s", name);
564 name = cpl_frame_get_filename(frame);
568 img_off = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
569 error_if(img_off == NULL, cpl_error_get_code(),
570 "Could not load off-image from %s", name);
572 error_if(cpl_image_subtract(diff, img_off), cpl_error_get_code(),
573 "Could not subtract frame %d from %d", ioff, ion);
575 cpl_image_delete(img_off);
578 bug_if(cpl_imagelist_set(
self, diff, ndiff));
584 bug_if(cpl_imagelist_get_size(
self) != ndiff);
586 error_if(ndiff == 0 && ion == nfiles, CPL_ERROR_DATA_NOT_FOUND,
587 "The %d frame(s) contain(s) no on-frames", nfiles);
588 error_if(ndiff == 0 && ioff == nfiles, CPL_ERROR_DATA_NOT_FOUND,
589 "The %d frame(s) contain(s) no off-frames", nfiles);
591 if (2 * ndiff < nfiles) {
592 cpl_msg_warning(cpl_func,
"The %d frames contains only %d pairs of "
593 "on/off-frames, ignoring the rest", nfiles, ndiff);
596 bug_if(cpl_imagelist_get_size(
self) < 1);
600 cpl_image_delete(img_off);
601 cpl_image_delete(diff);
603 return cpl_error_get_code();
627 cpl_error_code naco_framelist_get_state(
const irplib_framelist *
self,
630 cpl_boolean * pis_ok,
631 const cpl_propertylist * onoffkeys)
634 cpl_boolean state = CPL_FALSE;
635 const cpl_propertylist * plist
637 const int nonoffkeys = cpl_propertylist_get_size(onoffkeys);
639 cpl_boolean onoffkeys_has_one_on = CPL_FALSE;
642 bug_if (
self == NULL);
645 bug_if (pis_ok == NULL);
646 bug_if (onoffkeys == NULL);
647 bug_if (plist == NULL);
649 for (i=0; i < nonoffkeys; i++) {
650 const cpl_property * prop = cpl_propertylist_get_const(onoffkeys, i);
651 const char * name = cpl_property_get_name(prop);
652 const int ireq = cpl_property_get_int(prop);
653 const cpl_type statetype = cpl_propertylist_get_type(plist, name);
654 cpl_boolean state_is_on;
656 error_if(0, cpl_error_get_code(),
"On/off property number %d, %s",
657 1+i, name ? name :
"<NULL>");
661 state_is_on = cpl_propertylist_get_char(plist, name) > 0
662 ? CPL_TRUE : CPL_FALSE;
665 state_is_on = cpl_propertylist_get_bool(plist, name);
668 state_is_on = cpl_propertylist_get_int(plist, name) > 0
669 ? CPL_TRUE : CPL_FALSE;
672 state_is_on = cpl_propertylist_get_long(plist, name) > 0
673 ? CPL_TRUE : CPL_FALSE;
676 state_is_on = cpl_propertylist_get_float(plist, name) > 0.0
677 ? CPL_TRUE : CPL_FALSE;
679 case CPL_TYPE_DOUBLE:
680 state_is_on = cpl_propertylist_get_double(plist, name) > 0.0
681 ? CPL_TRUE : CPL_FALSE;
684 cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
689 if (ireq == 0)
break;
690 onoffkeys_has_one_on = CPL_TRUE;
691 }
else if (ireq > 0) {
694 }
else if (state_is_on) {
699 if (i == nonoffkeys) {
702 state = onoffkeys_has_one_on;
713 return cpl_error_get_code();
728 static int vector_index_compare(
const void * a,
const void * b)
746 static int naco_vector_get_maxpos_window(
const cpl_vector * v,
int i0,
int i1)
750 double vmax = cpl_vector_get(v, imax);
752 cpl_ensure(v != NULL, CPL_ERROR_NULL_INPUT, -1);
753 cpl_ensure(0 <= i0, CPL_ERROR_ILLEGAL_INPUT, -2);
754 cpl_ensure(i0 <= i1, CPL_ERROR_ILLEGAL_INPUT, -3);
755 cpl_ensure(i1 < cpl_vector_get_size(v), CPL_ERROR_ILLEGAL_INPUT, -4);
757 for (i = i0; i <= i1; i++) if (cpl_vector_get(v, i) > vmax) {
759 vmax = cpl_vector_get(v, imax);
cpl_error_code naco_vector_correlate_imagelist_1d(cpl_vector *offset, const cpl_vector *goffset, cpl_boolean do_wave, const cpl_imagelist *self)
Use 1D cross-correlation to recompute the offsets in one direction.
char * naco_spc_make_tag(const cpl_frame *self, const cpl_propertylist *plist, int dummy)
Create a string suitable for frame comparison in spectroscopy.
cpl_error_code naco_imagelist_add_split(cpl_imagelist *self)
Readd all the pairs, preserving the number of images.
cpl_error_code naco_imagelist_split(cpl_imagelist *self)
Split the images in an imagelist into positive and negative images.
const cpl_propertylist * irplib_framelist_get_propertylist_const(const irplib_framelist *self, int pos)
Get the propertylist of the specified frame in the framelist.
cpl_error_code naco_imagelist_append_invert(cpl_imagelist *self)
Fo each image append also its inverted.
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.
cpl_error_code naco_imagelist_load_diff(cpl_imagelist *self, const irplib_framelist *onofflist, const cpl_propertylist *onoffkeys)
Fill the list of difference images from on/off frames.
int irplib_framelist_get_size(const irplib_framelist *self)
Get the size of a framelist.