00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <string.h>
00037 #include <math.h>
00038 #include <cpl.h>
00039
00040 #ifdef HAVE_GSL
00041 #include <gsl/gsl_multimin.h>
00042 #endif
00043
00044 #include "naco_spc.h"
00045 #include "naco_pfits.h"
00046
00047
00048
00049
00050 typedef struct {
00051 double x;
00052 int index;
00053 } vector_index;
00054
00055
00056
00057
00058
00059
00060 static int naco_vector_get_maxpos_window(const cpl_vector *, int, int);
00061
00062 #if 0
00063 static int vector_index_compare(const void *, const void *);
00064 #endif
00065
00066 static cpl_error_code naco_framelist_get_state(const irplib_framelist *,
00067 int, cpl_boolean,
00068 cpl_boolean *,
00069 const cpl_propertylist *);
00070
00071
00075
00076
00079
00095
00096 cpl_error_code naco_vector_correlate_imagelist_1d(cpl_vector * offset,
00097 const cpl_vector * goffset,
00098 cpl_boolean do_wave,
00099 const cpl_imagelist * self)
00100 {
00101
00102 cpl_image * d2d = NULL;
00103 cpl_image * dspat1d = NULL;
00104 cpl_vector * vspat1dp = NULL;
00105 cpl_vector * vspat1di = NULL;
00106 cpl_vector * vxc = NULL;
00107 const int nsize = cpl_imagelist_get_size(self);
00108 const int maxerr = 20;
00109 int gleni, glenprev = 0;
00110
00111
00112 const int nz = (do_wave ? cpl_image_get_size_y : cpl_image_get_size_x)
00113 (cpl_imagelist_get_const(self, 0));
00114 const char dirch = do_wave ? 'Y' : 'X';
00115 const int direc = do_wave ? 1 : 0;
00116 int ii, i, iprev = 0;
00117 double xcmin = 1.0;
00118
00119
00120 bug_if(self == NULL);
00121
00122 bug_if(offset == NULL);
00123 bug_if(goffset == NULL);
00124 bug_if(cpl_vector_get_size(offset) != nsize);
00125 bug_if(cpl_vector_get_size(goffset) != nsize);
00126
00127
00128 for (ii = 0; ii < nsize; ii++) {
00129 i = ii;
00130
00131 cpl_msg_info(cpl_func, "%c-offset(%d:%d): %g", dirch, ii, i,
00132 cpl_vector_get(goffset, i));
00133
00134 }
00135
00136 vxc = cpl_vector_new(maxerr);
00137
00138
00139 for (ii = 0; ii < nsize; ii++) {
00140
00141 int maxoff, halfoff;
00142 int ixc, ixc0;
00143 int irealfirst, ireallast;
00144 int ioff;
00145 double xci;
00146 double doff, dnewoff;
00147
00148 i = ii;
00149
00150 gleni = (int)round(cpl_vector_get(goffset, i));
00151
00152
00153 d2d = cpl_image_cast(cpl_imagelist_get_const(self, i), CPL_TYPE_DOUBLE);
00154
00155
00156 dspat1d = cpl_image_collapse_create(d2d, direc);
00157
00158 cpl_image_delete(d2d);
00159 d2d = NULL;
00160
00161 cpl_vector_delete(vspat1di);
00162 vspat1di = cpl_vector_wrap(nz, cpl_image_get_data_double(dspat1d));
00163 (void)cpl_image_unwrap(dspat1d);
00164 dspat1d = NULL;
00165 bug_if(0);
00166
00167 #if 0
00168 cpl_plot_vector("set grid;", "t '1D-Profile i' w linespoints", "",
00169 vspat1di);
00170 #endif
00171 if (ii == 0) {
00172 vspat1dp = vspat1di;
00173 vspat1di = NULL;
00174 glenprev = gleni;
00175 iprev = i;
00176 continue;
00177 }
00178
00179 halfoff = maxerr + abs(gleni - glenprev);
00180 if (halfoff > nz-1) halfoff = nz - 1;
00181 maxoff = 2 * halfoff + 1;
00182
00183 bug_if(cpl_vector_set_size(vxc, maxoff));
00184
00185 ixc0 = cpl_vector_correlate(vxc, vspat1di, vspat1dp);
00186 bug_if(0);
00187
00188
00189 irealfirst = halfoff - (glenprev - gleni) - maxerr;
00190 ireallast = halfoff - (glenprev - gleni) + maxerr;
00191
00192 ixc = naco_vector_get_maxpos_window(vxc, irealfirst, ireallast);
00193 bug_if(0);
00194
00195 if (ixc != ixc0) {
00196 cpl_msg_warning(cpl_func, "%c-False maximum(%d:%d): %d <+. %d. "
00197 "0 <= %d => %d < %d", dirch, ii, i, ixc0, ixc,
00198 irealfirst, ireallast, maxoff);
00199 }
00200
00201 ioff = ixc - halfoff;
00202 doff = cpl_vector_get(goffset, i) - cpl_vector_get(goffset, iprev);
00203
00204 xci = cpl_vector_get(vxc, ixc);
00205
00206 if (xci < xcmin) xcmin = xci;
00207
00208 if (ioff != (int)round(doff)) {
00209 cpl_msg_warning(cpl_func, "%c-XC(%d)=%g changes offset: %g - %g = "
00210 "%g => %d = %d - %d", dirch, i, xci,
00211 cpl_vector_get(goffset, i),
00212 cpl_vector_get(goffset, iprev), doff, ioff,
00213 gleni, glenprev);
00214 dnewoff = (double)-ioff;
00215 } else {
00216 cpl_msg_info(cpl_func, "%c-XC(%d)=%g confirms offset: %g - %g = %g "
00217 "<=> %d = %d - %d", dirch, i, xci,
00218 cpl_vector_get(goffset, i),
00219 cpl_vector_get(goffset, iprev), doff, ioff,
00220 gleni, glenprev);
00221 dnewoff = -doff;
00222 }
00223 bug_if(0);
00224 bug_if(cpl_vector_set(offset, i, dnewoff));
00225
00226 #if 0
00227 cpl_plot_vector("set grid;", "t 'Cross-correlation' w linespoints",
00228 "", vxc);
00229
00230 #endif
00231 }
00232
00233 cpl_msg_info(cpl_func, "Minimum 1D-spatial XC for %d sets: %g",
00234 nsize, xcmin);
00235
00236 end_skip;
00237
00238 cpl_image_delete(d2d);
00239 (void)cpl_image_unwrap(dspat1d);
00240 cpl_vector_delete(vspat1dp);
00241 cpl_vector_delete(vspat1di);
00242 cpl_vector_delete(vxc);
00243
00244 return cpl_error_get_code();
00245 }
00246
00247
00255
00256 cpl_error_code naco_imagelist_add_split(cpl_imagelist * self)
00257 {
00258
00259 cpl_image * copy = NULL;
00260 int n = cpl_imagelist_get_size(self);
00261 int i;
00262
00263 bug_if(self == NULL);
00264
00265 bug_if(n&1);
00266
00267
00268 for (i=0; i < n; i += 2) {
00269 cpl_image * first = cpl_imagelist_get(self, i);
00270 cpl_image * second = cpl_imagelist_get(self, i+1);
00271
00272 bug_if(cpl_image_subtract(first, second));
00273
00274 copy = cpl_image_multiply_scalar_create(first, -1.0);
00275
00276 bug_if(cpl_imagelist_set(self, copy, i+1));
00277 copy = NULL;
00278
00279 }
00280
00281 end_skip;
00282
00283 cpl_image_delete(copy);
00284
00285 return cpl_error_get_code();
00286
00287 }
00288
00289
00290
00291
00299
00300 cpl_error_code naco_imagelist_append_invert(cpl_imagelist * self)
00301 {
00302
00303 cpl_image * BA = NULL;
00304 const int n = cpl_imagelist_get_size(self);
00305 int i;
00306
00307
00308 bug_if(self == NULL);
00309
00310 for (i=0; i < n; i++) {
00311 const cpl_image * AB = cpl_imagelist_get(self, i);
00312
00313 BA = cpl_image_multiply_scalar_create(AB, -1.0);
00314
00315 bug_if(cpl_imagelist_set(self, BA, n+i));
00316 BA = NULL;
00317
00318 }
00319
00320 end_skip;
00321
00322 cpl_image_delete(BA);
00323
00324 return cpl_error_get_code();
00325
00326 }
00327
00328
00329
00339
00340 cpl_error_code naco_imagelist_split(cpl_imagelist * self)
00341 {
00342
00343 cpl_imagelist * copy = cpl_imagelist_new();
00344 cpl_image * image = NULL;
00345 cpl_image * im_neg = NULL;
00346 int j = cpl_imagelist_get_size(self);
00347 int i = 0;
00348
00349
00350 skip_if(self == NULL);
00351
00352
00353 j--;
00354 for (; j >= 0; j--, i++) {
00355 bug_if(cpl_imagelist_set(copy, cpl_imagelist_unset(self, j), i));
00356 }
00357
00358 j++;
00359 i--;
00360
00361 bug_if(j != 0);
00362
00363
00364 for (; i >= 0; i--, j += 2) {
00365 image = cpl_imagelist_unset(copy, i);
00366
00367
00368 im_neg = cpl_image_duplicate(image);
00369 bug_if(cpl_image_threshold(im_neg, -FLT_MAX, 0.0, 0.0, 0.0));
00370 bug_if(cpl_image_multiply_scalar(im_neg, -1.0));
00371
00372
00373
00374 bug_if(cpl_image_threshold(image, 0.0, FLT_MAX, 0.0, 0.0));
00375
00376 bug_if(cpl_imagelist_set(self, image, j));
00377 image = NULL;
00378
00379 bug_if(cpl_imagelist_set(self, im_neg, j+1));
00380 im_neg = NULL;
00381
00382 }
00383
00384 end_skip;
00385
00386 cpl_image_delete(image);
00387 cpl_image_delete(im_neg);
00388 cpl_imagelist_delete(copy);
00389
00390 return CPL_ERROR_NONE;
00391
00392 }
00393
00394
00406
00407 char * naco_spc_make_tag(const cpl_frame* self, const cpl_propertylist * plist,
00408 int dummy)
00409 {
00410
00411 char * tag = NULL;
00412 double wlen, dit;
00413 const char * specmode;
00414 const char * slitname;
00415
00416
00417 bug_if (0);
00418
00419 bug_if(self == NULL);
00420 bug_if(plist == NULL);
00421 bug_if(dummy < 0);
00422
00423 specmode = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SPECMODE);
00424 skip_if(cpl_error_get_code());
00425
00426 slitname = irplib_pfits_get_string(plist, NACO_PFITS_STRING_SLITNAME);
00427 skip_if(cpl_error_get_code());
00428
00429 dit = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_DIT);
00430 skip_if(cpl_error_get_code());
00431
00432 wlen = irplib_pfits_get_double(plist, NACO_PFITS_DOUBLE_CWLEN);
00433 skip_if(cpl_error_get_code());
00434
00435 tag = cpl_sprintf("%s:%s:%.5f:%.5f", specmode, slitname, wlen, dit);
00436 bug_if(tag == NULL);
00437
00438 end_skip;
00439
00440 if (cpl_error_get_code()) {
00441 cpl_free(tag);
00442 tag = NULL;
00443 }
00444
00445 return tag;
00446
00447 }
00448
00449
00450
00481
00482 cpl_error_code naco_imagelist_load_diff(cpl_imagelist * self,
00483 const irplib_framelist * onofflist,
00484 const cpl_propertylist * onoffkeys)
00485 {
00486 cpl_image * img_off = NULL;
00487 cpl_image * diff = NULL;
00488 int nfiles, ndiff;
00489 int ion, ioff;
00490
00491 skip_if (0);
00492 skip_if (self == NULL);
00493 skip_if (onofflist == NULL);
00494
00495 skip_if(cpl_imagelist_get_size(self) != 0);
00496
00497 skip_if (irplib_framelist_contains(onofflist, "NAXIS1", CPL_TYPE_INT,
00498 CPL_TRUE, 0.0));
00499 skip_if (irplib_framelist_contains(onofflist, "NAXIS2", CPL_TYPE_INT,
00500 CPL_TRUE, 0.0));
00501
00502 skip_if (irplib_framelist_contains(onofflist, NACO_PFITS_DOUBLE_DIT,
00503 CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00504
00505 nfiles = irplib_framelist_get_size(onofflist);
00506
00507 for (ioff = 0, ion = 0, ndiff = 0; ioff < nfiles && ion < nfiles;
00508 ioff++, ion++) {
00509
00510 cpl_boolean need_on = CPL_TRUE;
00511
00512 const cpl_frame * frame;
00513 const char * name;
00514
00515
00516
00517 for (; ioff < nfiles; ioff++) {
00518 cpl_boolean is_off;
00519
00520 skip_if(naco_framelist_get_state(onofflist, ioff, CPL_FALSE,
00521 &is_off, onoffkeys));
00522
00523 if (is_off) {
00524 break;
00525 } else if (need_on && ioff >= ion) {
00526 ion = ioff;
00527 need_on = CPL_FALSE;
00528 }
00529 }
00530
00531 bug_if(0);
00532
00533 if (ioff == nfiles) break;
00534
00535 if (need_on) {
00536
00537 if (ion == ioff) ion++;
00538 for (; ion < nfiles; ion++) {
00539
00540 cpl_boolean is_on;
00541
00542 skip_if(naco_framelist_get_state(onofflist, ion, CPL_TRUE,
00543 &is_on, onoffkeys));
00544
00545 if (is_on) break;
00546
00547 }
00548
00549 bug_if(0);
00550
00551 if (ion == nfiles) break;
00552 }
00553
00554 frame = irplib_framelist_get_const(onofflist, ion);
00555 name = cpl_frame_get_filename(frame);
00556
00557 bug_if(0);
00558
00559 diff = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00560 error_if(diff == NULL, cpl_error_get_code(),
00561 "Could not load on-image from %s", name);
00562
00563 frame = irplib_framelist_get_const(onofflist, ioff);
00564 name = cpl_frame_get_filename(frame);
00565
00566 bug_if(0);
00567
00568 img_off = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0);
00569 error_if(img_off == NULL, cpl_error_get_code(),
00570 "Could not load off-image from %s", name);
00571
00572 error_if(cpl_image_subtract(diff, img_off), cpl_error_get_code(),
00573 "Could not subtract frame %d from %d", ioff, ion);
00574
00575 cpl_image_delete(img_off);
00576 img_off = NULL;
00577
00578 bug_if(cpl_imagelist_set(self, diff, ndiff));
00579 diff = NULL;
00580
00581 ndiff++;
00582 }
00583
00584 bug_if(cpl_imagelist_get_size(self) != ndiff);
00585
00586 error_if(ndiff == 0 && ion == nfiles, CPL_ERROR_DATA_NOT_FOUND,
00587 "The %d frame(s) contain(s) no on-frames", nfiles);
00588 error_if(ndiff == 0 && ioff == nfiles, CPL_ERROR_DATA_NOT_FOUND,
00589 "The %d frame(s) contain(s) no off-frames", nfiles);
00590
00591 if (2 * ndiff < nfiles) {
00592 cpl_msg_warning(cpl_func, "The %d frames contains only %d pairs of "
00593 "on/off-frames, ignoring the rest", nfiles, ndiff);
00594 }
00595
00596 bug_if(cpl_imagelist_get_size(self) < 1);
00597
00598 end_skip;
00599
00600 cpl_image_delete(img_off);
00601 cpl_image_delete(diff);
00602
00603 return cpl_error_get_code();
00604 }
00605
00606
00611
00625
00626 static
00627 cpl_error_code naco_framelist_get_state(const irplib_framelist * self,
00628 int iframe,
00629 cpl_boolean is_on,
00630 cpl_boolean * pis_ok,
00631 const cpl_propertylist * onoffkeys)
00632 {
00633
00634 cpl_boolean state = CPL_FALSE;
00635 const cpl_propertylist * plist
00636 = irplib_framelist_get_propertylist_const(self, iframe);
00637 const int nonoffkeys = cpl_propertylist_get_size(onoffkeys);
00638 int i;
00639 cpl_boolean onoffkeys_has_one_on = CPL_FALSE;
00640
00641 bug_if (0);
00642 bug_if (self == NULL);
00643 bug_if (iframe < 0);
00644 bug_if (iframe >= irplib_framelist_get_size(self));
00645 bug_if (pis_ok == NULL);
00646 bug_if (onoffkeys == NULL);
00647 bug_if (plist == NULL);
00648
00649 for (i=0; i < nonoffkeys; i++) {
00650 const cpl_property * prop = cpl_propertylist_get_const(onoffkeys, i);
00651 const char * name = cpl_property_get_name(prop);
00652 const int ireq = cpl_property_get_int(prop);
00653 const cpl_type statetype = cpl_propertylist_get_type(plist, name);
00654 cpl_boolean state_is_on;
00655
00656 error_if(0, cpl_error_get_code(), "On/off property number %d, %s",
00657 1+i, name ? name : "<NULL>");
00658
00659 switch (statetype) {
00660 case CPL_TYPE_CHAR:
00661 state_is_on = cpl_propertylist_get_char(plist, name) > 0
00662 ? CPL_TRUE : CPL_FALSE;
00663 break;
00664 case CPL_TYPE_BOOL:
00665 state_is_on = cpl_propertylist_get_bool(plist, name);
00666 break;
00667 case CPL_TYPE_INT:
00668 state_is_on = cpl_propertylist_get_int(plist, name) > 0
00669 ? CPL_TRUE : CPL_FALSE;
00670 break;
00671 case CPL_TYPE_LONG:
00672 state_is_on = cpl_propertylist_get_long(plist, name) > 0
00673 ? CPL_TRUE : CPL_FALSE;
00674 break;
00675 case CPL_TYPE_FLOAT:
00676 state_is_on = cpl_propertylist_get_float(plist, name) > 0.0
00677 ? CPL_TRUE : CPL_FALSE;
00678 break;
00679 case CPL_TYPE_DOUBLE:
00680 state_is_on = cpl_propertylist_get_double(plist, name) > 0.0
00681 ? CPL_TRUE : CPL_FALSE;
00682 break;
00683 default:
00684 cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
00685 }
00686
00687 if (is_on) {
00688 if (state_is_on) {
00689 if (ireq == 0) break;
00690 onoffkeys_has_one_on = CPL_TRUE;
00691 } else if (ireq > 0) {
00692 break;
00693 }
00694 } else if (state_is_on) {
00695 break;
00696 }
00697 }
00698
00699 if (i == nonoffkeys) {
00700 if (is_on) {
00701
00702 state = onoffkeys_has_one_on;
00703 } else {
00704
00705 state = CPL_TRUE;
00706 }
00707 }
00708
00709 *pis_ok = state;
00710
00711 end_skip;
00712
00713 return cpl_error_get_code();
00714 }
00715
00716 #if 0
00717
00727
00728 static int vector_index_compare(const void * a, const void * b)
00729 {
00730 return
00731 ( (const vector_index*)a)->x < ((const vector_index*)b)->x ? -1 :
00732 (((const vector_index*)a)->x > ((const vector_index*)b)->x ? 1 : 0);
00733 }
00734
00735 #endif
00736
00745
00746 static int naco_vector_get_maxpos_window(const cpl_vector * v, int i0, int i1)
00747 {
00748 int i = i0;
00749 int imax = i0;
00750 double vmax = cpl_vector_get(v, imax);
00751
00752 cpl_ensure(v != NULL, CPL_ERROR_NULL_INPUT, -1);
00753 cpl_ensure(0 <= i0, CPL_ERROR_ILLEGAL_INPUT, -2);
00754 cpl_ensure(i0 <= i1, CPL_ERROR_ILLEGAL_INPUT, -3);
00755 cpl_ensure(i1 < cpl_vector_get_size(v), CPL_ERROR_ILLEGAL_INPUT, -4);
00756
00757 for (i = i0; i <= i1; i++) if (cpl_vector_get(v, i) > vmax) {
00758 imax = i;
00759 vmax = cpl_vector_get(v, imax);
00760 }
00761
00762 return imax;
00763 }
00764