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