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
00037 #include <cpl.h>
00038
00039 #ifndef CPL_SIZE_FORMAT
00040 #define CPL_SIZE_FORMAT "d"
00041 #define cpl_size int
00042 #endif
00043
00044
00045 #include "irplib_wavecal_impl.h"
00046
00047
00048 #include "irplib_utils.h"
00049
00050 #include <string.h>
00051 #include <math.h>
00052
00053 #ifdef HAVE_GSL
00054 #include <gsl/gsl_multimin.h>
00055 #endif
00056
00057
00058
00059
00060
00061 typedef struct {
00062
00063 const cpl_vector * observed;
00064 cpl_polynomial * disp1d;
00065 cpl_vector * spectrum;
00066 irplib_base_spectrum_model * param;
00067 cpl_error_code (* filler)(cpl_vector *, const cpl_polynomial *,
00068 irplib_base_spectrum_model *);
00069 cpl_vector * vxc;
00070 double xc;
00071 int maxxc;
00072 double mxc;
00073 cpl_polynomial * mdisp;
00074 int ishift;
00075
00076 } irplib_multimin;
00077
00078
00079
00080
00081
00082 #ifndef inline
00083 #define inline
00084 #endif
00085
00086 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
00087 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
00088
00089
00090
00091
00092
00093 #ifdef HAVE_GSL
00094 static double irplib_gsl_correlation(const gsl_vector *, void *);
00095 #endif
00096
00097 static cpl_error_code
00098 irplib_polynomial_find_1d_from_correlation_(cpl_polynomial *, int,
00099 const cpl_vector *,
00100 irplib_base_spectrum_model *,
00101 cpl_error_code (*)
00102 (cpl_vector *,
00103 const cpl_polynomial *,
00104 irplib_base_spectrum_model *),
00105 double, double, int, int,
00106 double *, cpl_boolean *);
00107
00108
00109
00113
00114
00118
00126
00127 int irplib_bivector_count_positive(const cpl_bivector * self,
00128 double x_min,
00129 double x_max)
00130 {
00131
00132 const int nself = cpl_bivector_get_size(self);
00133 const double * px = cpl_bivector_get_x_data_const(self);
00134 const double * py = cpl_bivector_get_y_data_const(self);
00135 int npos = 0;
00136 int i = 0;
00137
00138 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, -1);
00139 cpl_ensure(x_min <= x_max, CPL_ERROR_ILLEGAL_INPUT, -2);
00140
00141
00142 while (i < nself && px[i] < x_min) i++;
00143 while (i < nself && px[i] < x_max)
00144 if (py[i++] > 0) npos++;
00145
00146 return npos;
00147 }
00148
00149
00159
00160 cpl_error_code irplib_polynomial_fit_2d_dispersion(cpl_polynomial * self,
00161 const cpl_image * imgwave,
00162 int fitdeg, double * presid)
00163 {
00164
00165 const int nx = cpl_image_get_size_x(imgwave);
00166 const int ny = cpl_image_get_size_y(imgwave);
00167 const int nbad = cpl_image_count_rejected(imgwave);
00168 const int nsamp = nx * ny - nbad;
00169 cpl_matrix * xy_pos;
00170 double * xdata;
00171 double * ydata;
00172 cpl_vector * wlen;
00173 double * dwlen;
00174 const cpl_size nfitdeg = (cpl_size)fitdeg;
00175 int i, j;
00176 int k = 0;
00177
00178 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00179 cpl_ensure_code(imgwave != NULL, CPL_ERROR_NULL_INPUT);
00180 cpl_ensure_code(presid != NULL, CPL_ERROR_NULL_INPUT);
00181 cpl_ensure_code(fitdeg > 0, CPL_ERROR_ILLEGAL_INPUT);
00182
00183 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 2,
00184 CPL_ERROR_ILLEGAL_INPUT);
00185
00186 xy_pos = cpl_matrix_new(2, nsamp);
00187 xdata = cpl_matrix_get_data(xy_pos);
00188 ydata = xdata + nsamp;
00189
00190 dwlen = (double*)cpl_malloc(nsamp * sizeof(double));
00191 wlen = cpl_vector_wrap(nsamp, dwlen);
00192
00193 for (i=1; i <= nx; i++) {
00194 for (j=1; j <= ny; j++) {
00195 int is_bad;
00196 const double value = cpl_image_get(imgwave, i, j, &is_bad);
00197 if (!is_bad) {
00198 xdata[k] = i;
00199 ydata[k] = j;
00200 dwlen[k] = value;
00201 k++;
00202 }
00203 }
00204 }
00205
00206 cpl_msg_info(cpl_func, "Fitting 2D polynomial to %d X %d image, ignoring "
00207 "%d poorly calibrated pixels", nx, ny, nbad);
00208
00209 if (cpl_polynomial_fit(self, xy_pos, NULL, wlen, NULL, CPL_FALSE, NULL,
00210 &nfitdeg) == CPL_ERROR_NONE && presid != NULL) {
00211 cpl_vector_fill_polynomial_fit_residual(wlen, wlen, NULL, self, xy_pos,
00212 NULL);
00213 *presid = cpl_vector_product(wlen, wlen)/nsamp;
00214 }
00215 cpl_matrix_delete(xy_pos);
00216 cpl_vector_delete(wlen);
00217
00218 cpl_ensure_code(k == nsamp, CPL_ERROR_UNSPECIFIED);
00219
00220 return CPL_ERROR_NONE;
00221 }
00222
00223
00224
00242
00243 cpl_error_code
00244 irplib_polynomial_find_1d_from_correlation(cpl_polynomial * self,
00245 int maxdeg,
00246 const cpl_vector * obs,
00247 irplib_base_spectrum_model * model,
00248 cpl_error_code (* filler)
00249 (cpl_vector *,
00250 const cpl_polynomial *,
00251 irplib_base_spectrum_model *),
00252 double pixtol,
00253 double pixstep,
00254 int hsize,
00255 int maxite,
00256 double * pxc)
00257 {
00258 cpl_boolean restart = CPL_FALSE;
00259 const cpl_error_code error = irplib_polynomial_find_1d_from_correlation_
00260 (self, maxdeg, obs, model, filler, pixtol, pixstep, hsize, maxite, pxc,
00261 &restart);
00262
00263 return error ? cpl_error_set_where(cpl_func) :
00264 (restart ? cpl_error_set(cpl_func, CPL_ERROR_CONTINUE)
00265 : CPL_ERROR_NONE);
00266 }
00267
00268
00289
00290 static cpl_error_code
00291 irplib_polynomial_find_1d_from_correlation_(cpl_polynomial * self,
00292 int maxdeg,
00293 const cpl_vector * obs,
00294 irplib_base_spectrum_model * model,
00295 cpl_error_code (* filler)
00296 (cpl_vector *,
00297 const cpl_polynomial *,
00298 irplib_base_spectrum_model *),
00299 double pixtol,
00300 double pixstep,
00301 int hsize,
00302 int maxite,
00303 double * pxc,
00304 cpl_boolean * prestart)
00305 {
00306
00307 #ifdef HAVE_GSL
00308 const gsl_multimin_fminimizer_type * T = gsl_multimin_fminimizer_nmsimplex;
00309 gsl_multimin_fminimizer * minimizer;
00310 gsl_multimin_function my_func;
00311 irplib_multimin data;
00312 gsl_vector * dispgsl;
00313 gsl_vector * stepsize;
00314 gsl_vector * dispprev;
00315 int status = GSL_CONTINUE;
00316 const int nobs = cpl_vector_get_size(obs);
00317 const cpl_size nfit = maxdeg + 1;
00318 cpl_errorstate prestate = cpl_errorstate_get();
00319
00320 const double wlstep =
00321 cpl_polynomial_eval_1d_diff(self, 0.5 * (nobs + pixstep),
00322 0.5 * (nobs - pixstep), NULL);
00323 double wlstepi = wlstep;
00324 double size;
00325 int iter;
00326 cpl_size i;
00327
00328 #endif
00329
00330 cpl_ensure_code(prestart != NULL, CPL_ERROR_NULL_INPUT);
00331 *prestart = CPL_FALSE;
00332 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00333 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00334 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00335 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00336 cpl_ensure_code(pxc != NULL, CPL_ERROR_NULL_INPUT);
00337
00338 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00339 CPL_ERROR_ILLEGAL_INPUT);
00340
00341 cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
00342 CPL_ERROR_ILLEGAL_INPUT);
00343
00344 cpl_ensure_code(maxdeg >= 0, CPL_ERROR_ILLEGAL_INPUT);
00345 cpl_ensure_code(pixtol > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00346 cpl_ensure_code(pixstep > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00347 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
00348 cpl_ensure_code(maxite >= 0, CPL_ERROR_ILLEGAL_INPUT);
00349
00350 #ifndef HAVE_GSL
00351 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
00352 "GSL is not available");
00353 #else
00354
00355 minimizer = gsl_multimin_fminimizer_alloc(T, (size_t)nfit);
00356
00357 cpl_ensure_code(minimizer != NULL, CPL_ERROR_ILLEGAL_OUTPUT);
00358
00359 dispgsl = gsl_vector_alloc((size_t)nfit);
00360 stepsize = gsl_vector_alloc((size_t)nfit);
00361 dispprev = gsl_vector_alloc((size_t)nfit);
00362
00363 for (i=0; i < nfit; i++) {
00364 const double value = cpl_polynomial_get_coeff(self, &i);
00365 gsl_vector_set(dispgsl, (size_t)i, value);
00366 gsl_vector_set(stepsize, (size_t)i, wlstepi);
00367 wlstepi /= (double)nobs;
00368 }
00369
00370 my_func.n = nfit;
00371 my_func.f = &irplib_gsl_correlation;
00372 my_func.params = (void *)(&data);
00373
00374 data.observed = obs;
00375 data.disp1d = self;
00376 data.spectrum = cpl_vector_new(nobs + 2 * hsize);
00377 data.vxc = cpl_vector_new(1 + 2 * hsize);
00378 data.param = model;
00379 data.filler = filler;
00380 data.maxxc = 0;
00381 data.ishift = 0;
00382 data.mxc = -1.0;
00383 data.mdisp = NULL;
00384
00385 gsl_multimin_fminimizer_set (minimizer, &my_func, dispgsl, stepsize);
00386
00387 for (iter = 0; status == GSL_CONTINUE && iter < maxite; iter++) {
00388
00389 const double fprev = minimizer->fval;
00390
00391 gsl_vector_memcpy(dispprev, minimizer->x);
00392 status = gsl_multimin_fminimizer_iterate(minimizer);
00393
00394 if (status || !cpl_errorstate_is_equal(prestate)) break;
00395
00396 size = gsl_multimin_fminimizer_size (minimizer);
00397 status = gsl_multimin_test_size (size, pixtol);
00398
00399 if (status == GSL_SUCCESS) {
00400 cpl_msg_debug(cpl_func, "converged to minimum at");
00401
00402 if (nfit == 0) {
00403 cpl_msg_debug(cpl_func, "%5d %g df() = %g size = %g",
00404 iter,
00405 gsl_vector_get (minimizer->x, 0)
00406 - gsl_vector_get (dispprev, 0),
00407 minimizer->fval - fprev, size);
00408 } else if (nfit == 1) {
00409 cpl_msg_debug(cpl_func, "%5d %g %g df() = %g size = %g",
00410 iter,
00411 gsl_vector_get (minimizer->x, 0)
00412 - gsl_vector_get (dispprev, 0),
00413 gsl_vector_get (minimizer->x, 1)
00414 - gsl_vector_get (dispprev, 1),
00415 minimizer->fval - fprev, size);
00416 } else {
00417 cpl_msg_debug(cpl_func, "%5d %g %g %g df() = %g size = %g",
00418 iter,
00419 gsl_vector_get (minimizer->x, 0)
00420 - gsl_vector_get (dispprev, 0),
00421 gsl_vector_get (minimizer->x, 1)
00422 - gsl_vector_get (dispprev, 1),
00423 gsl_vector_get (minimizer->x, 2)
00424 - gsl_vector_get (dispprev, 2),
00425 minimizer->fval - fprev, size);
00426 }
00427 }
00428 }
00429
00430 if (status == GSL_SUCCESS && cpl_errorstate_is_equal(prestate)) {
00431 if (data.mxc > -minimizer->fval) {
00432 *pxc = data.mxc;
00433 cpl_msg_warning(cpl_func, "Local maximum: %g(%d) > %g",
00434 data.mxc, data.ishift, -minimizer->fval);
00435 cpl_polynomial_shift_1d(data.mdisp, 0, (double)data.ishift);
00436 cpl_polynomial_copy(self, data.mdisp);
00437 *prestart = CPL_TRUE;
00438 } else {
00439 *pxc = -minimizer->fval;
00440 for (i=0; i < nfit; i++) {
00441 const double value = gsl_vector_get(minimizer->x, i);
00442 cpl_polynomial_set_coeff(self, &i, value);
00443 }
00444 }
00445 }
00446
00447 cpl_vector_delete(data.spectrum);
00448 cpl_vector_delete(data.vxc);
00449 cpl_polynomial_delete(data.mdisp);
00450 gsl_multimin_fminimizer_free(minimizer);
00451 gsl_vector_free(dispgsl);
00452 gsl_vector_free(dispprev);
00453 gsl_vector_free(stepsize);
00454
00455 cpl_ensure_code(status != GSL_CONTINUE, CPL_ERROR_CONTINUE);
00456 cpl_ensure_code(status == GSL_SUCCESS, CPL_ERROR_DATA_NOT_FOUND);
00457 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00458
00459 return CPL_ERROR_NONE;
00460 #endif
00461 }
00462
00463
00464
00492
00493 cpl_error_code
00494 irplib_vector_fill_line_spectrum(cpl_vector * self,
00495 const cpl_polynomial * disp,
00496 irplib_base_spectrum_model * lsslamp)
00497 {
00498
00499 irplib_line_spectrum_model * arclamp
00500 = (irplib_line_spectrum_model *)lsslamp;
00501 cpl_error_code error;
00502
00503 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00504
00505 arclamp->cost++;
00506
00507 error = irplib_vector_fill_line_spectrum_model(self,
00508 arclamp->linepix,
00509 arclamp->erftmp,
00510 disp,
00511 arclamp->lines,
00512 arclamp->wslit,
00513 arclamp->wfwhm,
00514 arclamp->xtrunc,
00515 0, CPL_FALSE, CPL_FALSE,
00516 &(arclamp->ulines));
00517 cpl_ensure_code(!error, error);
00518
00519 arclamp->xcost++;
00520
00521 return CPL_ERROR_NONE;
00522 }
00523
00524
00537
00538 cpl_error_code
00539 irplib_vector_fill_logline_spectrum(cpl_vector * self,
00540 const cpl_polynomial * disp,
00541 irplib_base_spectrum_model * lsslamp)
00542 {
00543
00544 irplib_line_spectrum_model * arclamp
00545 = (irplib_line_spectrum_model *)lsslamp;
00546 cpl_error_code error;
00547
00548 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00549
00550 arclamp->cost++;
00551
00552 error = irplib_vector_fill_line_spectrum_model(self,
00553 arclamp->linepix,
00554 arclamp->erftmp,
00555 disp,
00556 arclamp->lines,
00557 arclamp->wslit,
00558 arclamp->wfwhm,
00559 arclamp->xtrunc,
00560 0, CPL_FALSE, CPL_TRUE,
00561 &(arclamp->ulines));
00562 cpl_ensure_code(!error, error);
00563
00564 arclamp->xcost++;
00565
00566 return CPL_ERROR_NONE;
00567 }
00568
00569
00570
00583
00584 cpl_error_code
00585 irplib_vector_fill_line_spectrum_fast(cpl_vector * self,
00586 const cpl_polynomial * disp,
00587 irplib_base_spectrum_model * lsslamp)
00588 {
00589
00590 irplib_line_spectrum_model * arclamp
00591 = (irplib_line_spectrum_model *)lsslamp;
00592 cpl_error_code error;
00593
00594 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00595
00596 arclamp->cost++;
00597
00598 error = irplib_vector_fill_line_spectrum_model(self,
00599 arclamp->linepix,
00600 arclamp->erftmp,
00601 disp,
00602 arclamp->lines,
00603 arclamp->wslit,
00604 arclamp->wfwhm,
00605 arclamp->xtrunc,
00606 0, CPL_TRUE, CPL_FALSE,
00607 &(arclamp->ulines));
00608 cpl_ensure_code(!error, error);
00609
00610 arclamp->xcost++;
00611
00612 return CPL_ERROR_NONE;
00613 }
00614
00615
00628
00629 cpl_error_code
00630 irplib_vector_fill_logline_spectrum_fast(cpl_vector * self,
00631 const cpl_polynomial * disp,
00632 irplib_base_spectrum_model * lsslamp)
00633 {
00634
00635 irplib_line_spectrum_model * arclamp
00636 = (irplib_line_spectrum_model *)lsslamp;
00637 cpl_error_code error;
00638
00639 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00640
00641 arclamp->cost++;
00642
00643 error = irplib_vector_fill_line_spectrum_model(self,
00644 arclamp->linepix,
00645 arclamp->erftmp,
00646 disp,
00647 arclamp->lines,
00648 arclamp->wslit,
00649 arclamp->wfwhm,
00650 arclamp->xtrunc,
00651 0, CPL_TRUE, CPL_TRUE,
00652 &(arclamp->ulines));
00653 cpl_ensure_code(!error, error);
00654
00655 arclamp->xcost++;
00656
00657 return CPL_ERROR_NONE;
00658 }
00659
00660
00671
00672 cpl_error_code irplib_plot_spectrum_and_model(const cpl_vector * self,
00673 const cpl_polynomial * disp1d,
00674 irplib_base_spectrum_model * model,
00675 cpl_error_code (* filler)
00676 (cpl_vector *,
00677 const cpl_polynomial *,
00678 irplib_base_spectrum_model *))
00679 {
00680
00681 cpl_errorstate prestate = cpl_errorstate_get();
00682 cpl_vector * wl;
00683 cpl_vector * spectrum;
00684 cpl_vector * vxc;
00685 const int len = cpl_vector_get_size(self);
00686 double maxval, xc;
00687 int ixc;
00688 int error = 0;
00689
00690 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00691 cpl_ensure_code(disp1d != NULL, CPL_ERROR_NULL_INPUT);
00692 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00693 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00694
00695 cpl_ensure_code(cpl_polynomial_get_dimension(disp1d) == 1,
00696 CPL_ERROR_ILLEGAL_INPUT);
00697
00698 cpl_ensure_code(cpl_polynomial_get_degree(disp1d) > 0,
00699 CPL_ERROR_ILLEGAL_INPUT);
00700
00701 wl = cpl_vector_new(len);
00702 spectrum = cpl_vector_new(len);
00703 vxc = cpl_vector_new(1);
00704
00705 error |= (int)cpl_vector_fill_polynomial(wl, disp1d, 1.0, 1.0);
00706 error |= filler(spectrum, disp1d, model);
00707
00708 ixc = cpl_vector_correlate(vxc, self, spectrum);
00709 xc = cpl_vector_get(vxc, ixc);
00710
00711 maxval = cpl_vector_get_max(spectrum);
00712 if (maxval != 0.0)
00713 error |= cpl_vector_multiply_scalar(spectrum,
00714 cpl_vector_get_max(self)/maxval);
00715 if (!error) {
00716 const cpl_vector * spair[] = {wl, self, spectrum};
00717 char * pre = cpl_sprintf("set grid;set xlabel 'Wavelength (%g -> %g)'; "
00718 "set ylabel 'Intensity';", cpl_vector_get(wl, 0),
00719 cpl_vector_get(wl, len-1));
00720 char * title = cpl_sprintf("t 'Observed and modelled spectra (%d pixel "
00721 "XC=%g) ' w linespoints", len, xc);
00722
00723 (void)cpl_plot_vectors(pre, title, "", spair, 3);
00724 cpl_free(pre);
00725 cpl_free(title);
00726 }
00727
00728 cpl_vector_delete(wl);
00729 cpl_vector_delete(spectrum);
00730 cpl_vector_delete(vxc);
00731
00732 cpl_errorstate_set(prestate);
00733
00734 return CPL_ERROR_NONE;
00735 }
00736
00737
00757
00758 cpl_error_code
00759 irplib_bivector_find_shift_from_correlation(cpl_bivector * self,
00760 const cpl_polynomial * disp,
00761 const cpl_vector * obs,
00762 irplib_base_spectrum_model * model,
00763 cpl_error_code (*filler)
00764 (cpl_vector *,
00765 const cpl_polynomial *,
00766 irplib_base_spectrum_model *),
00767 int hsize,
00768 cpl_boolean doplot,
00769 double *pxc)
00770 {
00771
00772 const int nobs = cpl_vector_get_size(obs);
00773 const int nmodel = 2 * hsize + nobs;
00774 cpl_polynomial * shdisp;
00775 cpl_vector * xself = cpl_bivector_get_x(self);
00776 cpl_vector * yself = cpl_bivector_get_y(self);
00777 cpl_vector * mspec1d;
00778 cpl_vector * xcorr;
00779 cpl_error_code error = CPL_ERROR_NONE;
00780 double xcprev, xcnext;
00781 int ixc, imax = 0;
00782 int i;
00783
00784 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00785 cpl_ensure_code(disp != NULL, CPL_ERROR_NULL_INPUT);
00786 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00787 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00788 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00789 cpl_ensure_code(hsize > 0, CPL_ERROR_ILLEGAL_INPUT);
00790
00791 shdisp = cpl_polynomial_duplicate(disp);
00792
00793
00794 if (cpl_polynomial_shift_1d(shdisp, 0, -hsize)) {
00795 cpl_polynomial_delete(shdisp);
00796 return cpl_error_set_where(cpl_func);
00797 }
00798
00799 mspec1d = cpl_vector_new(nmodel);
00800
00801 if (filler(mspec1d, shdisp, model)) {
00802 cpl_vector_delete(mspec1d);
00803 return cpl_error_set_where(cpl_func);
00804 }
00805
00806
00807 xcorr = cpl_vector_new(1 + 2 * hsize);
00808 ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00809
00810 #ifdef IRPLIB_SPC_DUMP
00811
00812 irplib_polynomial_dump_corr_step(shdisp, xcorr, "Shift");
00813 #endif
00814
00815 cpl_vector_delete(mspec1d);
00816 cpl_polynomial_delete(shdisp);
00817
00818
00819
00820 i = 0;
00821 xcprev = cpl_vector_get(xcorr, i);
00822 xcnext = cpl_vector_get(xcorr, i+1);
00823
00824 if (xcprev >= xcnext) {
00825
00826
00827
00828 imax++;
00829
00830 cpl_vector_set(xself, 0, i - hsize);
00831 cpl_vector_set(yself, 0, xcprev);
00832
00833 }
00834
00835 for (i = 1; i < 2 * hsize; i++) {
00836 const double xc = xcnext;
00837 xcnext = cpl_vector_get(xcorr, i+1);
00838 if (xc >= xcprev && xc >= xcnext) {
00839
00840 int j;
00841
00842 imax++;
00843
00844 if (cpl_bivector_get_size(self) < imax) {
00845 cpl_vector_set_size(xself, imax);
00846 cpl_vector_set_size(yself, imax);
00847 }
00848
00849 for (j = imax-1; j > 0; j--) {
00850 if (xc <= cpl_vector_get(yself, j-1)) break;
00851 cpl_vector_set(xself, j, cpl_vector_get(xself, j-1));
00852 cpl_vector_set(yself, j, cpl_vector_get(yself, j-1));
00853 }
00854 cpl_vector_set(xself, j, i - hsize);
00855 cpl_vector_set(yself, j, xc);
00856 }
00857 xcprev = xc;
00858 }
00859
00860
00861
00862 if (xcnext >= xcprev) {
00863
00864
00865
00866 int j;
00867
00868 imax++;
00869
00870 if (cpl_bivector_get_size(self) < imax) {
00871 cpl_vector_set_size(xself, imax);
00872 cpl_vector_set_size(yself, imax);
00873 }
00874
00875 for (j = imax-1; j > 0; j--) {
00876 if (xcnext <= cpl_vector_get(yself, j-1)) break;
00877 cpl_vector_set(xself, j, cpl_vector_get(xself, j-1));
00878 cpl_vector_set(yself, j, cpl_vector_get(yself, j-1));
00879 }
00880 cpl_vector_set(xself, j, i - hsize);
00881 cpl_vector_set(yself, j, xcnext);
00882
00883 }
00884
00885 if (doplot) {
00886
00887 cpl_vector * xvals = cpl_vector_new(1 + 2 * hsize);
00888 cpl_bivector * bcorr = cpl_bivector_wrap_vectors(xvals, xcorr);
00889 double x = (double)-hsize;
00890 char * title = cpl_sprintf("t 'Cross-correlation of shifted %d-pixel "
00891 "spectrum (XCmax=%g at %d)' w linespoints",
00892 nobs, cpl_vector_get(xcorr, ixc),
00893 ixc - hsize);
00894
00895 for (i = 0; i < 1 + 2 * hsize; i++, x += 1.0) {
00896 cpl_vector_set(xvals, i, x);
00897 }
00898
00899 cpl_plot_bivector("set grid;set xlabel 'Offset [pixel]';", title,
00900 "", bcorr);
00901 cpl_bivector_unwrap_vectors(bcorr);
00902 cpl_vector_delete(xvals);
00903 cpl_free(title);
00904 }
00905
00906 if (pxc != NULL) *pxc = cpl_vector_get(xcorr, hsize);
00907
00908 cpl_vector_delete(xcorr);
00909
00910 if (imax < 1) {
00911 error = CPL_ERROR_DATA_NOT_FOUND;
00912 } else if (cpl_bivector_get_size(self) > imax) {
00913 cpl_vector_set_size(xself, imax);
00914 cpl_vector_set_size(yself, imax);
00915 }
00916
00917
00918 return cpl_error_set(cpl_func, error);
00919 }
00920
00921
00934
00935 cpl_error_code
00936 irplib_polynomial_shift_1d_from_correlation(cpl_polynomial * self,
00937 const cpl_vector * obs,
00938 irplib_base_spectrum_model * model,
00939 cpl_error_code (*filler)
00940 (cpl_vector *,
00941 const cpl_polynomial *,
00942 irplib_base_spectrum_model *),
00943 int hsize,
00944 cpl_boolean doplot,
00945 double * pxc)
00946 {
00947
00948 const int nobs = cpl_vector_get_size(obs);
00949 const int nmodel = 2 * hsize + nobs;
00950 cpl_vector * mspec1d;
00951 cpl_vector * xcorr;
00952 cpl_error_code error;
00953 int ixc, xxc;
00954 double xc;
00955
00956 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00957 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00958 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00959 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00960 cpl_ensure_code(hsize > 0, CPL_ERROR_ILLEGAL_INPUT);
00961
00962
00963 cpl_ensure_code(!cpl_polynomial_shift_1d(self, 0, -hsize),
00964 cpl_error_get_code());
00965
00966 mspec1d = cpl_vector_new(nmodel);
00967
00968 if (filler(mspec1d, self, model)) {
00969 cpl_vector_delete(mspec1d);
00970 cpl_ensure_code(0, cpl_error_get_code());
00971 }
00972
00973
00974 xcorr = cpl_vector_new(1 + 2 * hsize);
00975 ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00976
00977 #ifdef IRPLIB_SPC_DUMP
00978
00979 irplib_polynomial_dump_corr_step(self, xcorr, "Shift");
00980 #endif
00981
00982 cpl_vector_delete(mspec1d);
00983
00984 error = cpl_polynomial_shift_1d(self, 0, (double)ixc);
00985
00986 xc = cpl_vector_get(xcorr, ixc);
00987
00988 xxc = ixc - hsize;
00989
00990 cpl_msg_info(cpl_func, "Shifting %d pixels (%g < %g)", xxc,
00991 cpl_vector_get(xcorr, hsize), xc);
00992
00993 if (doplot) {
00994 cpl_vector * xvals = cpl_vector_new(1 + 2 * hsize);
00995 cpl_bivector * bcorr = cpl_bivector_wrap_vectors(xvals, xcorr);
00996 int i;
00997 double x = (double)-hsize;
00998 char * title = cpl_sprintf("t 'Cross-correlation of shifted %d-pixel "
00999 "spectrum (XCmax=%g at %d)' w linespoints",
01000 nobs, cpl_vector_get(xcorr, ixc), xxc);
01001
01002 for (i = 0; i < 1 + 2 * hsize; i++, x += 1.0) {
01003 cpl_vector_set(xvals, i, x);
01004 }
01005
01006 cpl_plot_bivector("set grid;set xlabel 'Offset [pixel]';", title,
01007 "", bcorr);
01008 cpl_bivector_unwrap_vectors(bcorr);
01009 cpl_vector_delete(xvals);
01010 cpl_free(title);
01011 }
01012
01013 cpl_vector_delete(xcorr);
01014
01015 cpl_ensure_code(!error, error);
01016
01017 if (pxc != NULL) *pxc = xc;
01018
01019 return CPL_ERROR_NONE;
01020
01021 }
01022
01023
01024
01044
01045 cpl_error_code
01046 irplib_vector_fill_line_spectrum_model(cpl_vector * self,
01047 cpl_vector * linepix,
01048 cpl_vector * erftmp,
01049 const cpl_polynomial * disp,
01050 const cpl_bivector * lines,
01051 double wslit,
01052 double wfwhm,
01053 double xtrunc,
01054 int hsize,
01055 cpl_boolean dofast,
01056 cpl_boolean dolog,
01057 cpl_size * pulines)
01058 {
01059
01060 cpl_errorstate prestate;
01061 const double sigma = wfwhm * CPL_MATH_SIG_FWHM;
01062 const cpl_vector * xlines = cpl_bivector_get_x_const(lines);
01063 const double * dxlines = cpl_vector_get_data_const(xlines);
01064 const double * dylines = cpl_bivector_get_y_data_const(lines);
01065 double * plinepix
01066 = linepix ? cpl_vector_get_data(linepix) : NULL;
01067 const int nlines = cpl_vector_get_size(xlines);
01068 const int nself = cpl_vector_get_size(self);
01069 double * dself = cpl_vector_get_data(self);
01070 cpl_polynomial * dispi;
01071 double * profile = NULL;
01072 const cpl_size i0 = 0;
01073 const double p0 = cpl_polynomial_get_coeff(disp, &i0);
01074 double wl;
01075 double xpos = (double)(1-hsize)-xtrunc;
01076 const double xmax = (double)(nself-hsize)+xtrunc;
01077 double xderiv, xextreme;
01078 cpl_error_code error = CPL_ERROR_NONE;
01079 int iline;
01080 cpl_size ulines = 0;
01081
01082 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01083 cpl_ensure_code(disp != NULL, CPL_ERROR_NULL_INPUT);
01084 cpl_ensure_code(lines != NULL, CPL_ERROR_NULL_INPUT);
01085
01086 cpl_ensure_code(wslit > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01087 cpl_ensure_code(wfwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01088 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
01089 cpl_ensure_code(xtrunc > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01090 cpl_ensure_code(nself > 2 * hsize, CPL_ERROR_ILLEGAL_INPUT);
01091
01092 cpl_ensure_code(cpl_polynomial_get_dimension(disp) == 1,
01093 CPL_ERROR_ILLEGAL_INPUT);
01094 cpl_ensure_code(cpl_polynomial_get_degree(disp) > 0,
01095 CPL_ERROR_ILLEGAL_INPUT);
01096
01097
01098 wl = cpl_polynomial_eval_1d(disp, xpos, &xderiv);
01099
01100 if (wl <= 0.0) return
01101 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
01102 __LINE__, "Non-positive wavelength at x=%g: "
01103 "P(x)=%g, P'(x)=%g", xpos, wl, xderiv);
01104
01105 if (xderiv <= 0.0) return
01106 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
01107 __LINE__, "Non-increasing dispersion at "
01108 "x=%g: P'(x)=%g, P(x)=%g", xpos, xderiv, wl);
01109
01110
01111 iline = cpl_vector_find(xlines, wl);
01112
01113
01114 if (dxlines[iline] < wl) iline++;
01115
01116 if (iline >= nlines) return
01117 cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND, __FILE__,
01118 __LINE__, "The %d-line catalogue has only "
01119 "lines below P(%g)=%g > %g", nlines, xpos,
01120 wl, dxlines[nlines-1]);
01121
01122 memset(dself, 0, nself * sizeof(double));
01123
01124 dispi = cpl_polynomial_duplicate(disp);
01125
01126
01127 cpl_polynomial_derivative(dispi, 0);
01128
01129 prestate = cpl_errorstate_get();
01130
01131 if (cpl_polynomial_solve_1d(dispi, 0.5*(nlines+1), &xextreme, 1)) {
01132 cpl_errorstate_set(prestate);
01133 } else if (xpos < xextreme && xextreme < xmax) {
01134 cpl_polynomial_delete(dispi);
01135 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01136 __FILE__, __LINE__, "Non-monotone "
01137 "dispersion at x=%g: P'(x)=0, "
01138 "P(x)=%g", xextreme,
01139 cpl_polynomial_eval_1d(disp, xextreme,
01140 NULL));
01141 }
01142
01143 if (dofast) {
01144 const int npix = 1+(int)xtrunc;
01145
01146 if (erftmp != NULL && cpl_vector_get_size(erftmp) == npix &&
01147 cpl_vector_get(erftmp, 0) > 0.0) {
01148 profile = cpl_vector_get_data(erftmp);
01149 } else {
01150
01151 const double yval = 0.5 / wslit;
01152 const double x0p = 0.5 * wslit + 0.5;
01153 const double x0n = -0.5 * wslit + 0.5;
01154 double x1diff
01155 = irplib_erf_antideriv(x0p, sigma)
01156 - irplib_erf_antideriv(x0n, sigma);
01157 int ipix;
01158
01159 if (erftmp == NULL) {
01160 profile = (double*)cpl_malloc(sizeof(double)*(size_t)npix);
01161 } else {
01162 cpl_vector_set_size(erftmp, npix);
01163 profile = cpl_vector_get_data(erftmp);
01164 }
01165
01166 profile[0] = 2.0 * yval * x1diff;
01167
01168 for (ipix = 1; ipix < npix; ipix++) {
01169 const double x1 = (double)ipix;
01170 const double x1p = x1 + 0.5 * wslit + 0.5;
01171 const double x1n = x1 - 0.5 * wslit + 0.5;
01172 const double x0diff = x1diff;
01173
01174 x1diff = irplib_erf_antideriv(x1p, sigma)
01175 - irplib_erf_antideriv(x1n, sigma);
01176
01177 profile[ipix] = yval * (x1diff - x0diff);
01178
01179 }
01180 }
01181 }
01182
01183 cpl_polynomial_copy(dispi, disp);
01184
01185
01186
01187
01188
01189 xpos -= (wl - dxlines[iline]) / xderiv;
01190
01191
01192 for (; !error && iline < nlines; iline++) {
01193
01194
01195
01196 if (dylines[iline] <= 0.0) continue;
01197
01198
01199 if (plinepix != NULL && plinepix[iline] > 0.0) xpos = plinepix[iline];
01200
01201 if (xpos > xmax) xpos = xmax;
01202
01203
01204 error = cpl_polynomial_set_coeff(dispi, &i0, p0 - dxlines[iline]) ||
01205 cpl_polynomial_solve_1d(dispi, xpos, &xpos, 1);
01206
01207 if (xpos > xmax) {
01208 if (error) {
01209 error = 0;
01210 cpl_msg_debug(cpl_func, "Stopping spectrum fill at line %d/%d "
01211 "at xpos=%g > xmax=%g",
01212 iline, nlines, xpos, xmax);
01213 cpl_errorstate_dump(prestate, CPL_FALSE,
01214 irplib_errorstate_dump_debug);
01215 cpl_errorstate_set(prestate);
01216 }
01217 break;
01218 } else if (error) {
01219 if (linepix != NULL && ulines) (void)cpl_vector_fill(linepix, 0.0);
01220 (void)cpl_error_set_message_macro(cpl_func, cpl_error_get_code(),
01221 __FILE__, __LINE__,
01222 "Could not find pixel-position "
01223 "of line %d/%d at wavelength=%g."
01224 " xpos=%g, xmax=%g",
01225 iline, nlines, dxlines[iline],
01226 xpos, xmax);
01227 break;
01228 } else if (dofast) {
01229 const double frac = fabs(xpos - floor(xpos));
01230 #ifdef IRPLIB_WAVECAL_FAST_FAST
01231 const double frac0 = 1.0 - frac;
01232 #else
01233
01234 const double ep1pw = irplib_erf_antideriv(frac + 0.5 * wslit, sigma);
01235 const double en1pw = irplib_erf_antideriv(frac + 0.5 * wslit - 1.0,
01236 sigma);
01237 const double ep1nw = irplib_erf_antideriv(frac - 0.5 * wslit, sigma);
01238 const double en1nw = irplib_erf_antideriv(frac - 0.5 * wslit - 1.0,
01239 sigma);
01240 const double frac0
01241 = (en1nw - en1pw) / (ep1pw - en1pw - ep1nw + en1nw);
01242
01243 #endif
01244 const double frac1 = 1.0 - frac0;
01245 const double yval0 = frac0 * dylines[iline];
01246 const double yval1 = frac1 * dylines[iline];
01247 const int npix = 1+(int)xtrunc;
01248 int ipix;
01249 int i0n = hsize - 1 + floor(xpos);
01250 int i0p = i0n;
01251 int i1n = i0n + 1;
01252 int i1p = i1n;
01253 cpl_boolean didline = CPL_FALSE;
01254
01255
01256
01257 if (plinepix != NULL) plinepix[iline] = xpos;
01258
01259 if (frac0 < 0.0) {
01260 (void)cpl_error_set_message_macro(cpl_func,
01261 CPL_ERROR_UNSPECIFIED,
01262 __FILE__, __LINE__,
01263 "Illegal split at x=%g: %g + "
01264 "%g = 1", xpos, frac0, frac1);
01265 #ifdef IRPLIB_WAVEVAL_DEBUG
01266 } else {
01267 cpl_msg_warning(cpl_func,"profile split at x=%g: %g + %g = 1",
01268 xpos, frac0, frac1);
01269 #endif
01270 }
01271
01272 for (ipix = 0; ipix < npix; ipix++, i0n--, i0p++, i1n--, i1p++) {
01273
01274 if (i0n >= 0 && i0n < nself) {
01275 dself[i0n] += yval0 * profile[ipix];
01276 didline = CPL_TRUE;
01277 }
01278 if (i1n >= 0 && i1n < nself && ipix + 1 < npix) {
01279 dself[i1n] += yval1 * profile[ipix+1];
01280 didline = CPL_TRUE;
01281 }
01282
01283 if (ipix == 0) continue;
01284
01285 if (i0p >= 0 && i0p < nself) {
01286 dself[i0p] += yval0 * profile[ipix];
01287 didline = CPL_TRUE;
01288 }
01289 if (i1p >= 0 && i1p < nself && ipix + 1 < npix) {
01290 dself[i1p] += yval1 * profile[ipix+1];
01291 didline = CPL_TRUE;
01292 }
01293 }
01294
01295 if (didline) ulines++;
01296
01297 } else {
01298 const double yval = 0.5 * dylines[iline] / wslit;
01299 const int ifirst = IRPLIB_MAX((int)(xpos-xtrunc+0.5), 1-hsize);
01300 const int ilast = IRPLIB_MIN((int)(xpos+xtrunc), nself-hsize);
01301 int ipix;
01302 const double x0 = (double)ifirst - xpos;
01303 const double x0p = x0 + 0.5*wslit - 0.5;
01304 const double x0n = x0 - 0.5*wslit - 0.5;
01305 double x1diff
01306 = irplib_erf_antideriv(x0p, sigma)
01307 - irplib_erf_antideriv(x0n, sigma);
01308
01309
01310 if (plinepix != NULL) plinepix[iline] = xpos;
01311
01312 if (ilast >= ifirst) ulines++;
01313
01314 for (ipix = ifirst; ipix <= ilast; ipix++) {
01315 const double x1 = (double)ipix - xpos;
01316 const double x1p = x1 + 0.5*wslit + 0.5;
01317 const double x1n = x1 - 0.5*wslit + 0.5;
01318 const double x0diff = x1diff;
01319
01320 x1diff = irplib_erf_antideriv(x1p, sigma)
01321 - irplib_erf_antideriv(x1n, sigma);
01322
01323 dself[ipix+hsize-1] += yval * (x1diff - x0diff);
01324
01325 }
01326 }
01327 }
01328
01329 cpl_polynomial_delete(dispi);
01330 if (erftmp == NULL) cpl_free(profile);
01331
01332 cpl_ensure_code(!error, cpl_error_get_code());
01333
01334 if (dolog) {
01335 int i;
01336 for (i = 0; i < nself; i++) {
01337 dself[i] = dself[i] > 0.0 ? log(1.0 + dself[i]) : 0.0;
01338 }
01339 }
01340
01341 if (!ulines) return
01342 cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01343 __FILE__, __LINE__, "The %d-line "
01344 "catalogue has no lines in the range "
01345 "%g -> P(%g)=%g", nlines, wl, xmax,
01346 cpl_polynomial_eval_1d(disp, xmax, NULL));
01347
01348 if (pulines != NULL) *pulines = ulines;
01349
01350 return CPL_ERROR_NONE;
01351 }
01352
01353
01362
01363 inline double irplib_erf_antideriv(double x, double sigma)
01364 {
01365 return x * erf( x / (sigma * CPL_MATH_SQRT2))
01366 + 2.0 * sigma/CPL_MATH_SQRT2PI * exp(-0.5 * x * x / (sigma * sigma));
01367 }
01368
01369
01370 #ifdef HAVE_GSL
01371
01372
01379
01380 static double irplib_gsl_correlation(const gsl_vector * self, void * data)
01381 {
01382
01383 irplib_multimin * mindata = (irplib_multimin *)data;
01384 cpl_errorstate prestate = cpl_errorstate_get();
01385 int nobs, nmodel, ndiff;
01386 cpl_size i;
01387
01388 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01389 cpl_ensure(data != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01390
01391 cpl_ensure(mindata->filler != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01392 cpl_ensure(mindata->observed != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01393 cpl_ensure(mindata->spectrum != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01394
01395 nobs = cpl_vector_get_size(mindata->observed);
01396 nmodel = cpl_vector_get_size(mindata->spectrum);
01397 ndiff = nmodel - nobs;
01398
01399 cpl_ensure((ndiff & 1) == 0, CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
01400
01401 cpl_ensure(cpl_vector_get_size(mindata->vxc) == 1 + ndiff,
01402 CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
01403
01404 ndiff /= 2;
01405
01406 for (i=0; i < (cpl_size)self->size; i++) {
01407 const double value = gsl_vector_get(self, (size_t)i);
01408 cpl_polynomial_set_coeff(mindata->disp1d, &i, value);
01409 }
01410
01411
01412
01413 cpl_ensure_code(!cpl_polynomial_shift_1d(mindata->disp1d, 0, -ndiff),
01414 cpl_error_get_code());
01415
01416 if (mindata->filler(mindata->spectrum, mindata->disp1d,
01417 mindata->param)
01418 || !cpl_errorstate_is_equal(prestate)) {
01419
01420
01421
01422
01423 (void)cpl_vector_fill(mindata->vxc, -1.0);
01424
01425 mindata->maxxc = ndiff;
01426
01427 if (!cpl_errorstate_is_equal(prestate)) {
01428 cpl_msg_debug(cpl_func, "Spectrum fill failed:");
01429 cpl_errorstate_dump(prestate, CPL_FALSE,
01430 irplib_errorstate_dump_debug);
01431 cpl_errorstate_set(prestate);
01432 }
01433 } else {
01434
01435 mindata->maxxc = cpl_vector_correlate(mindata->vxc,
01436 mindata->spectrum,
01437 mindata->observed);
01438 }
01439
01440 #ifdef IRPLIB_SPC_DUMP
01441
01442 irplib_polynomial_dump_corr_step(mindata->disp1d, mindata->vxc,
01443 "Optimize");
01444 #endif
01445
01446 mindata->xc = cpl_vector_get(mindata->vxc, ndiff);
01447
01448 if (mindata->maxxc != ndiff &&
01449 cpl_vector_get(mindata->vxc, mindata->maxxc) > mindata->mxc) {
01450 const irplib_base_spectrum_model * arclamp
01451 = (const irplib_base_spectrum_model *)mindata->param;
01452
01453 if (mindata->mdisp == NULL) {
01454 mindata->mdisp = cpl_polynomial_duplicate(mindata->disp1d);
01455 } else {
01456 cpl_polynomial_copy(mindata->mdisp, mindata->disp1d);
01457 }
01458 mindata->mxc = cpl_vector_get(mindata->vxc, mindata->maxxc);
01459 mindata->ishift = mindata->maxxc;
01460 cpl_msg_debug(cpl_func, "Local maximum: %g(%d) > %g(%d) (cost=%u:%u. "
01461 "lines=%u)", mindata->mxc, mindata->maxxc, mindata->xc,
01462 ndiff, (unsigned)arclamp->cost, (unsigned)arclamp->xcost,
01463 (unsigned)arclamp->ulines);
01464 }
01465
01466 return -mindata->xc;
01467 }
01468
01469 #endif
01470
01471
01494
01495 cpl_error_code
01496 irplib_polynomial_find_1d_from_correlation_all(cpl_polynomial * self,
01497 int maxdeg,
01498 const cpl_vector * obs,
01499 int nmaxima,
01500 int linelim,
01501 irplib_base_spectrum_model* model,
01502 cpl_error_code (* filler)
01503 (cpl_vector *,
01504 const cpl_polynomial *,
01505 irplib_base_spectrum_model *),
01506 double pixtol,
01507 double pixstep,
01508 int hsize,
01509 int maxite,
01510 int maxfail,
01511 int maxcont,
01512 cpl_boolean doplot,
01513 double * pxc)
01514 {
01515
01516 #ifdef HAVE_GSL
01517
01518 cpl_errorstate prestate = cpl_errorstate_get();
01519 cpl_polynomial * start;
01520 cpl_polynomial * cand;
01521 cpl_polynomial * backup;
01522 cpl_error_code error = CPL_ERROR_NONE;
01523 double xc;
01524 cpl_bivector * xtshift = cpl_bivector_new(nmaxima ? nmaxima : 1);
01525 const cpl_vector * xtshiftx = cpl_bivector_get_x_const(xtshift);
01526 const cpl_vector * xtshifty = cpl_bivector_get_y_const(xtshift);
01527 int nshift;
01528 int imaximum = -1;
01529 int imaxima;
01530
01531 #endif
01532
01533 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01534 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
01535 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
01536 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
01537 cpl_ensure_code(pxc != NULL, CPL_ERROR_NULL_INPUT);
01538
01539 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
01540 CPL_ERROR_ILLEGAL_INPUT);
01541
01542 cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
01543 CPL_ERROR_ILLEGAL_INPUT);
01544
01545 cpl_ensure_code(maxdeg >= 0, CPL_ERROR_ILLEGAL_INPUT);
01546 cpl_ensure_code(pixtol > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01547 cpl_ensure_code(pixstep > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01548 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
01549 cpl_ensure_code(maxite >= 0, CPL_ERROR_ILLEGAL_INPUT);
01550 cpl_ensure_code(nmaxima >= 0, CPL_ERROR_ILLEGAL_INPUT);
01551 cpl_ensure_code(maxfail > 0, CPL_ERROR_ILLEGAL_INPUT);
01552 cpl_ensure_code(maxcont > 0, CPL_ERROR_ILLEGAL_INPUT);
01553 cpl_ensure_code(linelim >= 0, CPL_ERROR_ILLEGAL_INPUT);
01554
01555 #ifndef HAVE_GSL
01556
01557 cpl_ensure_code(doplot == CPL_TRUE || doplot == CPL_FALSE,
01558 CPL_ERROR_ILLEGAL_INPUT);
01559 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
01560 "GSL is not available");
01561 #else
01562
01563 if (irplib_bivector_find_shift_from_correlation(xtshift, self, obs,
01564 model, filler,
01565 hsize, doplot, &xc)) {
01566 cpl_bivector_delete(xtshift);
01567 return cpl_error_set_where(cpl_func);
01568 }
01569
01570 if (model->ulines > (cpl_size)linelim) {
01571
01572 const double xxc = cpl_vector_get(xtshiftx, 0);
01573 const double xc0 = cpl_vector_get(xtshifty, 0);
01574
01575 cpl_msg_warning(cpl_func, "Doing only shift=%g pixels with lines=%u > "
01576 "%d and XC=%g", xxc, (unsigned)model->ulines, linelim,
01577 xc0);
01578
01579 cpl_polynomial_shift_1d(self, 0, xxc);
01580
01581 *pxc = xc0;
01582
01583 cpl_bivector_delete(xtshift);
01584
01585 return CPL_ERROR_NONE;
01586 }
01587
01588 start = cpl_polynomial_duplicate(self);
01589 cand = cpl_polynomial_new(1);
01590 backup = cpl_polynomial_new(1);
01591
01592
01593 nshift = cpl_bivector_get_size(xtshift);
01594 if (nmaxima == 0 || nmaxima > nshift) nmaxima = nshift;
01595
01596 cpl_msg_info(cpl_func, "Optimizing %d/%d local shift-maxima "
01597 "(no-shift xc=%g. linelim=%d)", nmaxima, nshift, xc, linelim);
01598 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
01599 cpl_bivector_dump(xtshift, stdout);
01600
01601 for (imaxima = 0; imaxima < nmaxima; imaxima++) {
01602
01603 const double xxc = cpl_vector_get(xtshiftx, imaxima);
01604 double xtpixstep = pixstep;
01605 double xtpixtol = pixtol;
01606 double xtxc;
01607 cpl_boolean ok = CPL_FALSE;
01608 int nfail;
01609
01610
01611 cpl_polynomial_copy(cand, start);
01612 cpl_polynomial_shift_1d(cand, 0, xxc);
01613 cpl_polynomial_copy(backup, cand);
01614
01615
01616 for (nfail = 0; nfail < maxfail; nfail++, xtpixtol *= 2.0,
01617 xtpixstep *= 2.0) {
01618 int restart = maxcont;
01619 cpl_boolean redo;
01620
01621 do {
01622 if (error) {
01623 cpl_errorstate_dump(prestate, CPL_FALSE,
01624 irplib_errorstate_dump_debug);
01625 cpl_errorstate_set(prestate);
01626 }
01627 error = irplib_polynomial_find_1d_from_correlation_
01628 (cand, maxdeg, obs, model,
01629 filler, xtpixtol, xtpixstep, 2,
01630 maxite, &xtxc, &redo);
01631 if (redo && !error) error = CPL_ERROR_CONTINUE;
01632 } while (((!error && redo) || error == CPL_ERROR_CONTINUE)
01633 && --restart);
01634
01635 if (!error && !redo) {
01636 cpl_msg_debug(cpl_func, "XC(imax=%d/%d:xtpixtol=%g): %g "
01637 "(cost=%u:%u)", 1+imaxima, nmaxima, xtpixtol,
01638 xtxc, (unsigned)model->cost,
01639 (unsigned)model->xcost);
01640 break;
01641 }
01642 cpl_msg_warning(cpl_func, "Increasing xtpixtol from %g (%g, imax="
01643 "%d/%d)", xtpixtol, xtpixstep, 1+imaxima, nmaxima);
01644 if (model->ulines > (cpl_size)linelim) {
01645 cpl_msg_warning(cpl_func, "Stopping search-refinement via "
01646 "catalogue with %u lines > %d",
01647 (unsigned)model->ulines, linelim);
01648 break;
01649 }
01650 cpl_polynomial_copy(cand, start);
01651 }
01652
01653
01654 for (; !error && xtpixtol > 0.0; xtpixtol *= 0.25, xtpixstep *= 0.5) {
01655 int restart = maxcont;
01656 cpl_boolean redo;
01657
01658 cpl_polynomial_copy(backup, cand);
01659 do {
01660 if (error) {
01661 cpl_errorstate_dump(prestate, CPL_FALSE,
01662 irplib_errorstate_dump_debug);
01663 cpl_errorstate_set(prestate);
01664 }
01665 error = irplib_polynomial_find_1d_from_correlation_
01666 (cand, maxdeg, obs, model, filler,
01667 xtpixtol, xtpixstep, 2, maxite, &xtxc, &redo);
01668 if (redo && !error) error = CPL_ERROR_CONTINUE;
01669 } while (((!error && redo) || error == CPL_ERROR_CONTINUE)
01670 && --restart);
01671 if (error) break;
01672 ok = CPL_TRUE;
01673 if (redo) break;
01674 cpl_msg_debug(cpl_func, "XC(imax=%d/%d:xtpixtol=%g): %g (cost=%u:%u"
01675 ". ulines=%u)", 1+imaxima, nmaxima, xtpixtol, xtxc,
01676 (unsigned)model->cost, (unsigned)model->xcost,
01677 (unsigned)model->ulines);
01678 if (model->ulines > (cpl_size)linelim) {
01679 cpl_msg_info(cpl_func, "Stopping search-refinement via "
01680 "catalogue with %u lines > %u",
01681 (unsigned)model->ulines, linelim);
01682 break;
01683 }
01684 }
01685
01686 if (error) {
01687 error = 0;
01688 cpl_errorstate_dump(prestate, CPL_FALSE,
01689 irplib_errorstate_dump_debug);
01690 cpl_errorstate_set(prestate);
01691 cpl_polynomial_copy(cand, backup);
01692 }
01693 if (ok && xtxc > xc) {
01694 imaximum = imaxima;
01695 cpl_polynomial_copy(self, cand);
01696 xc = xtxc;
01697
01698 cpl_msg_info(cpl_func, "XC(imax=%d/%d): %g -> %g (initial-shift=%g. "
01699 "cost=%u:%u. lines=%u)", 1+imaxima, nmaxima,
01700 cpl_vector_get(xtshifty, imaxima), xtxc,
01701 cpl_vector_get(xtshiftx, imaxima),
01702 (unsigned)model->cost, (unsigned)model->xcost,
01703 (unsigned)model->ulines);
01704 } else {
01705 cpl_msg_info(cpl_func, "xc(imax=%d/%d): %g -> %g (initial-shift=%g. "
01706 "cost=%u:%u. lines=%u)", 1+imaxima, nmaxima,
01707 cpl_vector_get(xtshifty, imaxima), xtxc,
01708 cpl_vector_get(xtshiftx, imaxima),
01709 (unsigned)model->cost, (unsigned)model->xcost,
01710 (unsigned)model->ulines);
01711 }
01712 }
01713
01714 cpl_polynomial_delete(start);
01715 cpl_polynomial_delete(backup);
01716 cpl_polynomial_delete(cand);
01717
01718 if (imaximum < 0) {
01719
01720 const double xxc = cpl_vector_get(xtshiftx, 0);
01721 const double xc0 = cpl_vector_get(xtshifty, 0);
01722
01723 error = cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01724 "Could not improve XC=%g over %d "
01725 "local shift-maxima, best at shift %g",
01726 xc0, nmaxima, xxc);
01727 } else {
01728 cpl_msg_info(cpl_func, "Maximal XC=%g (up from %g, with initial pixel-"
01729 "shift of %g) at %d/%d local shift-maximi", xc,
01730 cpl_vector_get(xtshifty, imaximum),
01731 cpl_vector_get(xtshiftx, imaximum),
01732 1+imaximum, nmaxima);
01733
01734 if (doplot) {
01735 irplib_plot_spectrum_and_model(obs, self, model, filler);
01736 }
01737
01738 *pxc = xc;
01739 }
01740
01741 cpl_bivector_delete(xtshift);
01742
01743 return error;
01744
01745 #endif
01746
01747 }