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