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 "irplib_wavecal_impl.h"
00045
00046
00047 #include "irplib_utils.h"
00048
00049
00050
00051
00052
00053 typedef struct {
00054
00055 const cpl_vector * observed;
00056 cpl_polynomial * disp1d;
00057 cpl_vector * spectrum;
00058 irplib_base_spectrum_model * param;
00059 cpl_error_code (* filler)(cpl_vector *, const cpl_polynomial *,
00060 irplib_base_spectrum_model *, int);
00061 cpl_vector * vxc;
00062 double xc;
00063 int maxxc;
00064 double mxc;
00065 cpl_polynomial * mdisp;
00066 int ishift;
00067
00068 } irplib_multimin;
00069
00070
00071
00072
00073
00074 #ifndef inline
00075 #define inline
00076 #endif
00077
00078 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
00079 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
00080
00081
00082 #if defined cpl_test_polynomial_abs
00083 #define HAVE_CPL_POLYNOMIAL_FIT
00084 #endif
00085
00086
00087
00088
00089
00090 #ifdef HAVE_GSL
00091 static double irplib_gsl_correlation(const gsl_vector *, void *);
00092 #endif
00093
00094
00098
00099
00103
00111
00112 int irplib_bivector_count_positive(const cpl_bivector * self,
00113 double x_min,
00114 double x_max)
00115 {
00116
00117 const int nself = cpl_bivector_get_size(self);
00118 const double * px = cpl_bivector_get_x_data_const(self);
00119 const double * py = cpl_bivector_get_y_data_const(self);
00120 int npos = 0;
00121 int i = 0;
00122
00123 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, -1);
00124 cpl_ensure(x_min <= x_max, CPL_ERROR_ILLEGAL_INPUT, -2);
00125
00126
00127 while (i < nself && px[i] < x_min) i++;
00128 while (i < nself && px[i] < x_max)
00129 if (py[i++] > 0) npos++;
00130
00131 return npos;
00132 }
00133
00134
00144
00145 cpl_error_code irplib_polynomial_fit_2d_dispersion(cpl_polynomial * self,
00146 const cpl_image * imgwave,
00147 int fitdeg, double * presid)
00148 {
00149
00150 const int nx = cpl_image_get_size_x(imgwave);
00151 const int ny = cpl_image_get_size_y(imgwave);
00152 const int nbad = cpl_image_count_rejected(imgwave);
00153 const int nsamp = nx * ny - nbad;
00154 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00155 cpl_matrix * xy_pos;
00156 #else
00157 cpl_bivector * xy_pos;
00158 cpl_polynomial * copy;
00159 #endif
00160 double * xdata;
00161 double * ydata;
00162 cpl_vector * wlen;
00163 double * dwlen;
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 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00176 xy_pos = cpl_matrix_new(2, nsamp);
00177 xdata = cpl_matrix_get_data(xy_pos);
00178 ydata = xdata + nsamp;
00179 #else
00180 xy_pos = cpl_bivector_new(nsamp);
00181 xdata = cpl_bivector_get_x_data(xy_pos);
00182 ydata = cpl_bivector_get_y_data(xy_pos);
00183 #endif
00184
00185 dwlen = (double*)cpl_malloc(nsamp * sizeof(double));
00186 wlen = cpl_vector_wrap(nsamp, dwlen);
00187
00188 for (i=1; i <= nx; i++) {
00189 for (j=1; j <= ny; j++) {
00190 int is_bad;
00191 const double value = cpl_image_get(imgwave, i, j, &is_bad);
00192 if (!is_bad) {
00193 xdata[k] = i;
00194 ydata[k] = j;
00195 dwlen[k] = value;
00196 k++;
00197 }
00198 }
00199 }
00200
00201 cpl_msg_info(cpl_func, "Fitting 2D polynomial to %d X %d image, ignoring "
00202 "%d poorly calibrated pixels", nx, ny, nbad);
00203
00204 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00205 if (cpl_polynomial_fit(self, xy_pos, NULL, wlen, NULL, CPL_FALSE, NULL,
00206 &fitdeg) == CPL_ERROR_NONE && presid != NULL) {
00207 cpl_vector_fill_polynomial_fit_residual(wlen, wlen, NULL, self, xy_pos,
00208 NULL);
00209 *presid = cpl_vector_product(wlen, wlen)/nsamp;
00210 }
00211 cpl_matrix_delete(xy_pos);
00212 #else
00213
00214 copy = cpl_polynomial_fit_2d_create(xy_pos, wlen, fitdeg, presid);
00215 cpl_polynomial_copy(self, copy);
00216 cpl_polynomial_delete(copy);
00217 cpl_bivector_delete(xy_pos);
00218 #endif
00219
00220 cpl_vector_delete(wlen);
00221
00222 cpl_ensure_code(k == nsamp, CPL_ERROR_UNSPECIFIED);
00223
00224 return CPL_ERROR_NONE;
00225 }
00226
00227
00228
00246
00247 cpl_error_code
00248 irplib_polynomial_find_1d_from_correlation(cpl_polynomial * self,
00249 int maxdeg,
00250 const cpl_vector * obs,
00251 irplib_base_spectrum_model * model,
00252 cpl_error_code (* filler)
00253 (cpl_vector *,
00254 const cpl_polynomial *,
00255 irplib_base_spectrum_model *, int),
00256 double pixtol,
00257 double pixstep,
00258 int hsize,
00259 int maxite,
00260 double * pxc)
00261 {
00262
00263 #ifdef HAVE_GSL
00264 const gsl_multimin_fminimizer_type * T = gsl_multimin_fminimizer_nmsimplex;
00265 gsl_multimin_fminimizer * minimizer;
00266 gsl_multimin_function my_func;
00267 irplib_multimin data;
00268 gsl_vector * dispgsl;
00269 gsl_vector * stepsize;
00270 gsl_vector * dispprev;
00271 int status = GSL_CONTINUE;
00272 const int nobs = cpl_vector_get_size(obs);
00273 const int nfit = maxdeg + 1;
00274 cpl_errorstate prestate = cpl_errorstate_get();
00275
00276 const double wlstep =
00277 cpl_polynomial_eval_1d_diff(self, 0.5 * (nobs + pixstep),
00278 0.5 * (nobs - pixstep), NULL);
00279 double wlstepi = wlstep;
00280 double size;
00281 int iter;
00282 int i;
00283
00284 #endif
00285
00286 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00287 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00288 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00289 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00290 cpl_ensure_code(pxc != NULL, CPL_ERROR_NULL_INPUT);
00291
00292 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00293 CPL_ERROR_ILLEGAL_INPUT);
00294
00295 cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
00296 CPL_ERROR_ILLEGAL_INPUT);
00297
00298 cpl_ensure_code(maxdeg >= 0, CPL_ERROR_ILLEGAL_INPUT);
00299 cpl_ensure_code(pixtol > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00300 cpl_ensure_code(pixstep > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00301 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
00302 cpl_ensure_code(maxite >= 0, CPL_ERROR_ILLEGAL_INPUT);
00303
00304 #ifndef HAVE_GSL
00305 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
00306 "GSL is not available");
00307 #else
00308
00309 minimizer = gsl_multimin_fminimizer_alloc(T, (size_t)nfit);
00310
00311 cpl_ensure_code(minimizer != NULL, CPL_ERROR_ILLEGAL_OUTPUT);
00312
00313 dispgsl = gsl_vector_alloc(nfit);
00314 stepsize = gsl_vector_alloc(nfit);
00315 dispprev = gsl_vector_alloc(nfit);
00316
00317 for (i=0; i < nfit; i++) {
00318 const double value = cpl_polynomial_get_coeff(self, &i);
00319 gsl_vector_set(dispgsl, i, value);
00320 gsl_vector_set(stepsize, i, wlstepi);
00321 wlstepi /= (double)nobs;
00322 }
00323
00324 my_func.n = nfit;
00325 my_func.f = &irplib_gsl_correlation;
00326 my_func.params = (void *)(&data);
00327
00328 data.observed = obs;
00329 data.disp1d = self;
00330 data.spectrum = cpl_vector_new(nobs + 2 * hsize);
00331 data.vxc = cpl_vector_new(1 + 2 * hsize);
00332 data.param = model;
00333 data.filler = filler;
00334 data.maxxc = 0;
00335 data.ishift = 0;
00336 data.mxc = -1.0;
00337 data.mdisp = NULL;
00338
00339 gsl_multimin_fminimizer_set (minimizer, &my_func, dispgsl, stepsize);
00340
00341 for (iter = 0; status == GSL_CONTINUE && iter < maxite; iter++) {
00342
00343 const double fprev = minimizer->fval;
00344
00345 gsl_vector_memcpy(dispprev, minimizer->x);
00346 status = gsl_multimin_fminimizer_iterate(minimizer);
00347
00348 if (status || !cpl_errorstate_is_equal(prestate)) break;
00349
00350 size = gsl_multimin_fminimizer_size (minimizer);
00351 status = gsl_multimin_test_size (size, pixtol);
00352
00353 if (status == GSL_SUCCESS) {
00354 cpl_msg_debug(cpl_func, "converged to minimum at");
00355
00356 if (nfit == 0) {
00357 cpl_msg_debug(cpl_func, "%5d %g df() = %g size = %g",
00358 iter,
00359 gsl_vector_get (minimizer->x, 0)
00360 - gsl_vector_get (dispprev, 0),
00361 minimizer->fval - fprev, size);
00362 } else if (nfit == 1) {
00363 cpl_msg_debug(cpl_func, "%5d %g %g df() = %g size = %g",
00364 iter,
00365 gsl_vector_get (minimizer->x, 0)
00366 - gsl_vector_get (dispprev, 0),
00367 gsl_vector_get (minimizer->x, 1)
00368 - gsl_vector_get (dispprev, 1),
00369 minimizer->fval - fprev, size);
00370 } else {
00371 cpl_msg_debug(cpl_func, "%5d %g %g %g df() = %g size = %g",
00372 iter,
00373 gsl_vector_get (minimizer->x, 0)
00374 - gsl_vector_get (dispprev, 0),
00375 gsl_vector_get (minimizer->x, 1)
00376 - gsl_vector_get (dispprev, 1),
00377 gsl_vector_get (minimizer->x, 2)
00378 - gsl_vector_get (dispprev, 2),
00379 minimizer->fval - fprev, size);
00380 }
00381 }
00382 }
00383
00384 if (status == GSL_SUCCESS && cpl_errorstate_is_equal(prestate)) {
00385 if (data.mxc > -minimizer->fval) {
00386 *pxc = data.mxc;
00387 cpl_msg_warning(cpl_func, "Local maximum: %g(%d) > %g",
00388 data.mxc, data.ishift, -minimizer->fval);
00389 cpl_polynomial_shift_1d(data.mdisp, 0, (double)data.ishift);
00390 cpl_polynomial_copy(self, data.mdisp);
00391 status = GSL_CONTINUE;
00392 } else {
00393 *pxc = -minimizer->fval;
00394 for (i=0; i < nfit; i++) {
00395 const double value = gsl_vector_get(minimizer->x, i);
00396 cpl_polynomial_set_coeff(self, &i, value);
00397 }
00398 }
00399 }
00400
00401 cpl_vector_delete(data.spectrum);
00402 cpl_vector_delete(data.vxc);
00403 cpl_polynomial_delete(data.mdisp);
00404 gsl_multimin_fminimizer_free(minimizer);
00405 gsl_vector_free(dispgsl);
00406 gsl_vector_free(dispprev);
00407 gsl_vector_free(stepsize);
00408
00409 cpl_ensure_code(status != GSL_CONTINUE, CPL_ERROR_CONTINUE);
00410 cpl_ensure_code(status == GSL_SUCCESS, CPL_ERROR_DATA_NOT_FOUND);
00411 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00412
00413 return CPL_ERROR_NONE;
00414 #endif
00415 }
00416
00417
00418
00447
00448 cpl_error_code
00449 irplib_vector_fill_line_spectrum(cpl_vector * self,
00450 const cpl_polynomial * disp,
00451 irplib_base_spectrum_model * lsslamp,
00452 int hsize)
00453 {
00454
00455 irplib_line_spectrum_model * arclamp
00456 = (irplib_line_spectrum_model *)lsslamp;
00457 cpl_error_code error;
00458
00459 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00460
00461 arclamp->cost++;
00462
00463 error = irplib_vector_fill_line_spectrum_model(self,
00464 arclamp->linepix,
00465 arclamp->erftmp,
00466 disp,
00467 arclamp->lines,
00468 arclamp->wslit,
00469 arclamp->wfwhm,
00470 arclamp->xtrunc,
00471 hsize, CPL_FALSE, CPL_FALSE,
00472 &(arclamp->ulines));
00473 cpl_ensure_code(!error, error);
00474
00475 arclamp->xcost++;
00476
00477 return CPL_ERROR_NONE;
00478 }
00479
00480
00494
00495 cpl_error_code
00496 irplib_vector_fill_logline_spectrum(cpl_vector * self,
00497 const cpl_polynomial * disp,
00498 irplib_base_spectrum_model * lsslamp,
00499 int hsize)
00500 {
00501
00502 irplib_line_spectrum_model * arclamp
00503 = (irplib_line_spectrum_model *)lsslamp;
00504 cpl_error_code error;
00505
00506 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00507
00508 arclamp->cost++;
00509
00510 error = irplib_vector_fill_line_spectrum_model(self,
00511 arclamp->linepix,
00512 arclamp->erftmp,
00513 disp,
00514 arclamp->lines,
00515 arclamp->wslit,
00516 arclamp->wfwhm,
00517 arclamp->xtrunc,
00518 hsize, CPL_FALSE, CPL_TRUE,
00519 &(arclamp->ulines));
00520 cpl_ensure_code(!error, error);
00521
00522 arclamp->xcost++;
00523
00524 return CPL_ERROR_NONE;
00525 }
00526
00527
00528
00542
00543 cpl_error_code
00544 irplib_vector_fill_line_spectrum_fast(cpl_vector * self,
00545 const cpl_polynomial * disp,
00546 irplib_base_spectrum_model * lsslamp,
00547 int hsize)
00548 {
00549
00550 irplib_line_spectrum_model * arclamp
00551 = (irplib_line_spectrum_model *)lsslamp;
00552 cpl_error_code error;
00553
00554 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00555
00556 arclamp->cost++;
00557
00558 error = irplib_vector_fill_line_spectrum_model(self,
00559 arclamp->linepix,
00560 arclamp->erftmp,
00561 disp,
00562 arclamp->lines,
00563 arclamp->wslit,
00564 arclamp->wfwhm,
00565 arclamp->xtrunc,
00566 hsize, CPL_TRUE, CPL_FALSE,
00567 &(arclamp->ulines));
00568 cpl_ensure_code(!error, error);
00569
00570 arclamp->xcost++;
00571
00572 return CPL_ERROR_NONE;
00573 }
00574
00575
00589
00590 cpl_error_code
00591 irplib_vector_fill_logline_spectrum_fast(cpl_vector * self,
00592 const cpl_polynomial * disp,
00593 irplib_base_spectrum_model * lsslamp,
00594 int hsize)
00595 {
00596
00597 irplib_line_spectrum_model * arclamp
00598 = (irplib_line_spectrum_model *)lsslamp;
00599 cpl_error_code error;
00600
00601 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00602
00603 arclamp->cost++;
00604
00605 error = irplib_vector_fill_line_spectrum_model(self,
00606 arclamp->linepix,
00607 arclamp->erftmp,
00608 disp,
00609 arclamp->lines,
00610 arclamp->wslit,
00611 arclamp->wfwhm,
00612 arclamp->xtrunc,
00613 hsize, CPL_TRUE, CPL_TRUE,
00614 &(arclamp->ulines));
00615 cpl_ensure_code(!error, error);
00616
00617 arclamp->xcost++;
00618
00619 return CPL_ERROR_NONE;
00620 }
00621
00622
00633
00634 cpl_error_code irplib_plot_spectrum_and_model(const cpl_vector * self,
00635 const cpl_polynomial * disp1d,
00636 irplib_base_spectrum_model * model,
00637 cpl_error_code (* filler)
00638 (cpl_vector *,
00639 const cpl_polynomial *,
00640 irplib_base_spectrum_model *,
00641 int))
00642 {
00643
00644 cpl_errorstate prestate = cpl_errorstate_get();
00645 cpl_vector * wl;
00646 cpl_vector * spectrum;
00647 cpl_vector * vxc;
00648 const int len = cpl_vector_get_size(self);
00649 double maxval, xc;
00650 int ixc;
00651 int error = 0;
00652
00653 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00654 cpl_ensure_code(disp1d != NULL, CPL_ERROR_NULL_INPUT);
00655 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00656 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00657
00658 cpl_ensure_code(cpl_polynomial_get_dimension(disp1d) == 1,
00659 CPL_ERROR_ILLEGAL_INPUT);
00660
00661 cpl_ensure_code(cpl_polynomial_get_degree(disp1d) > 0,
00662 CPL_ERROR_ILLEGAL_INPUT);
00663
00664 wl = cpl_vector_new(len);
00665 spectrum = cpl_vector_new(len);
00666 vxc = cpl_vector_new(1);
00667
00668 error |= (int)cpl_vector_fill_polynomial(wl, disp1d, 1.0, 1.0);
00669 error |= filler(spectrum, disp1d, model, 0);
00670
00671 ixc = cpl_vector_correlate(vxc, self, spectrum);
00672 xc = cpl_vector_get(vxc, 0);
00673
00674 maxval = cpl_vector_get_max(spectrum);
00675 if (maxval != 0.0)
00676 error |= cpl_vector_multiply_scalar(spectrum,
00677 cpl_vector_get_max(self)/maxval);
00678 if (!error) {
00679 const cpl_vector * spair[] = {wl, self, spectrum};
00680 char * pre = cpl_sprintf("set grid;set xlabel 'Wavelength (%g -> %g)'; "
00681 "set ylabel 'Intensity';", cpl_vector_get(wl, 0),
00682 cpl_vector_get(wl, len-1));
00683 char * title = cpl_sprintf("t 'Observed and modelled spectra (%d pixel "
00684 "XC=%g) ' w linespoints", len, xc);
00685
00686 error = cpl_plot_vectors(pre, title, "", spair, 3);
00687 cpl_free(pre);
00688 cpl_free(title);
00689 }
00690
00691 cpl_vector_delete(wl);
00692 cpl_vector_delete(spectrum);
00693 cpl_vector_delete(vxc);
00694
00695 cpl_errorstate_set(prestate);
00696
00697 return CPL_ERROR_NONE;
00698 }
00699
00700
00718
00719 cpl_error_code
00720 irplib_bivector_find_shift_from_correlation(cpl_bivector * self,
00721 const cpl_polynomial * disp,
00722 const cpl_vector * obs,
00723 irplib_base_spectrum_model * model,
00724 cpl_error_code (*filler)
00725 (cpl_vector *,
00726 const cpl_polynomial *,
00727 irplib_base_spectrum_model *, int),
00728 int hsize,
00729 cpl_boolean doplot,
00730 double *pxc)
00731 {
00732
00733 const int nobs = cpl_vector_get_size(obs);
00734 const int nmodel = 2 * hsize + nobs;
00735 cpl_vector * xself = cpl_bivector_get_x(self);
00736 cpl_vector * yself = cpl_bivector_get_y(self);
00737 cpl_vector * mspec1d;
00738 cpl_vector * xcorr;
00739 cpl_error_code error = CPL_ERROR_NONE;
00740 double xcprev, xcnext;
00741 int ixc, imax = 0;
00742 int i;
00743
00744 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00745 cpl_ensure_code(disp != NULL, CPL_ERROR_NULL_INPUT);
00746 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00747 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00748 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00749 cpl_ensure_code(hsize > 0, CPL_ERROR_ILLEGAL_INPUT);
00750
00751 mspec1d = cpl_vector_new(nmodel);
00752
00753 if (filler(mspec1d, disp, model, hsize)) {
00754 cpl_vector_delete(mspec1d);
00755 return cpl_error_set_where(cpl_func);
00756 }
00757
00758
00759 xcorr = cpl_vector_new(1 + 2 * hsize);
00760 ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00761
00762 #ifdef IRPLIB_SPC_DUMP
00763
00764 irplib_polynomial_dump_corr_step(disp, xcorr, "Shift");
00765 #endif
00766
00767 cpl_vector_delete(mspec1d);
00768
00769
00770
00771 i = 0;
00772 xcprev = cpl_vector_get(xcorr, i);
00773 xcnext = cpl_vector_get(xcorr, i+1);
00774
00775 if (xcprev >= xcnext) {
00776
00777
00778
00779 imax++;
00780
00781 cpl_vector_set(xself, 0, i - hsize);
00782 cpl_vector_set(yself, 0, xcprev);
00783
00784 }
00785
00786 for (i = 1; i < 2 * hsize; i++) {
00787 const double xc = xcnext;
00788 xcnext = cpl_vector_get(xcorr, i+1);
00789 if (xc >= xcprev && xc >= xcnext) {
00790
00791 int j;
00792
00793 imax++;
00794
00795 if (cpl_bivector_get_size(self) < imax) {
00796 cpl_vector_set_size(xself, imax);
00797 cpl_vector_set_size(yself, imax);
00798 }
00799
00800 for (j = imax-1; j > 0; j--) {
00801 if (xc <= cpl_vector_get(yself, j-1)) break;
00802 cpl_vector_set(xself, j, cpl_vector_get(xself, j-1));
00803 cpl_vector_set(yself, j, cpl_vector_get(yself, j-1));
00804 }
00805 cpl_vector_set(xself, j, i - hsize);
00806 cpl_vector_set(yself, j, xc);
00807 }
00808 xcprev = xc;
00809 }
00810
00811
00812
00813 if (xcnext >= xcprev) {
00814
00815
00816
00817 int j;
00818
00819 imax++;
00820
00821 if (cpl_bivector_get_size(self) < imax) {
00822 cpl_vector_set_size(xself, imax);
00823 cpl_vector_set_size(yself, imax);
00824 }
00825
00826 for (j = imax-1; j > 0; j--) {
00827 if (xcnext <= cpl_vector_get(yself, j-1)) break;
00828 cpl_vector_set(xself, j, cpl_vector_get(xself, j-1));
00829 cpl_vector_set(yself, j, cpl_vector_get(yself, j-1));
00830 }
00831 cpl_vector_set(xself, j, i - hsize);
00832 cpl_vector_set(yself, j, xcnext);
00833
00834 }
00835
00836 if (doplot) {
00837 cpl_vector * xvals = cpl_vector_new(1 + 2 * hsize);
00838 cpl_bivector * bcorr = cpl_bivector_wrap_vectors(xvals, xcorr);
00839 double x = (double)-hsize;
00840 char * title = cpl_sprintf("t 'Cross-correlation of shifted %d-pixel "
00841 "spectrum (XCmax=%g at %d)' w linespoints",
00842 nobs, cpl_vector_get(xcorr, ixc),
00843 ixc - hsize);
00844
00845 for (i = 0; i < 1 + 2 * hsize; i++, x += 1.0) {
00846 cpl_vector_set(xvals, i, x);
00847 }
00848
00849 cpl_plot_bivector("set grid;set xlabel 'Offset [pixel]';", title,
00850 "", bcorr);
00851 cpl_bivector_unwrap_vectors(bcorr);
00852 cpl_vector_delete(xvals);
00853 cpl_free(title);
00854 }
00855
00856 if (pxc != NULL) *pxc = cpl_vector_get(xcorr, hsize);
00857
00858 cpl_vector_delete(xcorr);
00859
00860 if (imax < 1) {
00861 error = CPL_ERROR_DATA_NOT_FOUND;
00862 } else if (cpl_bivector_get_size(self) > imax) {
00863 cpl_vector_set_size(xself, imax);
00864 cpl_vector_set_size(yself, imax);
00865 }
00866
00867
00868 return cpl_error_set(cpl_func, error);
00869 }
00870
00871
00884
00885 cpl_error_code
00886 irplib_polynomial_shift_1d_from_correlation(cpl_polynomial * self,
00887 const cpl_vector * obs,
00888 irplib_base_spectrum_model * model,
00889 cpl_error_code (*filler)
00890 (cpl_vector *,
00891 const cpl_polynomial *,
00892 irplib_base_spectrum_model *, int),
00893 int hsize,
00894 cpl_boolean doplot,
00895 double * pxc)
00896 {
00897
00898 const int nobs = cpl_vector_get_size(obs);
00899 const int nmodel = 2 * hsize + nobs;
00900 cpl_vector * mspec1d;
00901 cpl_vector * xcorr;
00902 cpl_error_code error;
00903 int ixc, xxc;
00904 double xc;
00905
00906 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00907 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00908 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00909 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00910 cpl_ensure_code(hsize > 0, CPL_ERROR_ILLEGAL_INPUT);
00911
00912 mspec1d = cpl_vector_new(nmodel);
00913
00914 if (filler(mspec1d, self, model, hsize)) {
00915 cpl_vector_delete(mspec1d);
00916 cpl_ensure_code(0, cpl_error_get_code());
00917 }
00918
00919
00920 xcorr = cpl_vector_new(1 + 2 * hsize);
00921 ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00922
00923 #ifdef IRPLIB_SPC_DUMP
00924
00925 irplib_polynomial_dump_corr_step(self, xcorr, "Shift");
00926 #endif
00927
00928 cpl_vector_delete(mspec1d);
00929
00930 xxc = ixc - hsize;
00931
00932 error = cpl_polynomial_shift_1d(self, 0, (double)xxc);
00933
00934 xc = cpl_vector_get(xcorr, ixc);
00935
00936 cpl_msg_info(cpl_func, "Shifting %d pixels (%g < %g)", xxc,
00937 cpl_vector_get(xcorr, hsize), xc);
00938
00939 if (doplot) {
00940 cpl_vector * xvals = cpl_vector_new(1 + 2 * hsize);
00941 cpl_bivector * bcorr = cpl_bivector_wrap_vectors(xvals, xcorr);
00942 int i;
00943 double x = (double)-hsize;
00944 char * title = cpl_sprintf("t 'Cross-correlation of shifted %d-pixel "
00945 "spectrum (XCmax=%g at %d)' w linespoints",
00946 nobs, cpl_vector_get(xcorr, ixc), xxc);
00947
00948 for (i = 0; i < 1 + 2 * hsize; i++, x += 1.0) {
00949 cpl_vector_set(xvals, i, x);
00950 }
00951
00952 cpl_plot_bivector("set grid;set xlabel 'Offset [pixel]';", title,
00953 "", bcorr);
00954 cpl_bivector_unwrap_vectors(bcorr);
00955 cpl_vector_delete(xvals);
00956 cpl_free(title);
00957 }
00958
00959 cpl_vector_delete(xcorr);
00960
00961 cpl_ensure_code(!error, error);
00962
00963 if (pxc != NULL) *pxc = xc;
00964
00965 return CPL_ERROR_NONE;
00966
00967 }
00968
00969
00970
00990
00991 cpl_error_code
00992 irplib_vector_fill_line_spectrum_model(cpl_vector * self,
00993 cpl_vector * linepix,
00994 cpl_vector * erftmp,
00995 const cpl_polynomial * disp,
00996 const cpl_bivector * lines,
00997 double wslit,
00998 double wfwhm,
00999 double xtrunc,
01000 int hsize,
01001 cpl_boolean dofast,
01002 cpl_boolean dolog,
01003 unsigned * pulines)
01004 {
01005
01006 cpl_errorstate prestate;
01007 const double sigma = wfwhm * CPL_MATH_SIG_FWHM;
01008 const cpl_vector * xlines = cpl_bivector_get_x_const(lines);
01009 const double * dxlines = cpl_vector_get_data_const(xlines);
01010 const double * dylines = cpl_bivector_get_y_data_const(lines);
01011 double * plinepix
01012 = linepix ? cpl_vector_get_data(linepix) : NULL;
01013 const int nlines = cpl_vector_get_size(xlines);
01014 const int nself = cpl_vector_get_size(self);
01015 double * dself = cpl_vector_get_data(self);
01016 cpl_polynomial * dispi;
01017 double * profile = NULL;
01018 const int i0 = 0;
01019 const double p0 = cpl_polynomial_get_coeff(disp, &i0);
01020 double wl;
01021 double xpos = (double)(1-hsize)-xtrunc;
01022 const double xmax = (double)(nself-hsize)+xtrunc;
01023 double xderiv, xextreme;
01024 cpl_error_code error = CPL_ERROR_NONE;
01025 int iline;
01026 unsigned ulines = 0;
01027
01028 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01029 cpl_ensure_code(disp != NULL, CPL_ERROR_NULL_INPUT);
01030 cpl_ensure_code(lines != NULL, CPL_ERROR_NULL_INPUT);
01031
01032 cpl_ensure_code(wslit > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01033 cpl_ensure_code(wfwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01034 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
01035 cpl_ensure_code(xtrunc > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01036 cpl_ensure_code(nself > 2 * hsize, CPL_ERROR_ILLEGAL_INPUT);
01037
01038 cpl_ensure_code(cpl_polynomial_get_dimension(disp) == 1,
01039 CPL_ERROR_ILLEGAL_INPUT);
01040 cpl_ensure_code(cpl_polynomial_get_degree(disp) > 0,
01041 CPL_ERROR_ILLEGAL_INPUT);
01042
01043
01044 wl = cpl_polynomial_eval_1d(disp, xpos, &xderiv);
01045
01046 if (wl <= 0.0) return
01047 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
01048 __LINE__, "Non-positive wavelength at x=%g: "
01049 "P(x)=%g, P'(x)=%g", xpos, wl, xderiv);
01050
01051 if (xderiv <= 0.0) return
01052 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
01053 __LINE__, "Non-increasing dispersion at "
01054 "x=%g: P'(x)=%g, P(x)=%g", xpos, xderiv, wl);
01055
01056
01057 iline = cpl_vector_find(xlines, wl);
01058
01059
01060 if (dxlines[iline] < wl) iline++;
01061
01062 if (iline >= nlines) return
01063 cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND, __FILE__,
01064 __LINE__, "The %d-line catalogue has only "
01065 "lines below P(%g)=%g > %g", nlines, xpos,
01066 wl, dxlines[nlines-1]);
01067
01068 memset(dself, 0, nself * sizeof(double));
01069
01070 dispi = cpl_polynomial_duplicate(disp);
01071
01072
01073 cpl_polynomial_derivative(dispi, 0);
01074
01075 prestate = cpl_errorstate_get();
01076
01077 if (cpl_polynomial_solve_1d(dispi, 0.5*(nlines+1), &xextreme, 1)) {
01078 cpl_errorstate_set(prestate);
01079 } else if (xpos < xextreme && xextreme < xmax) {
01080 cpl_polynomial_delete(dispi);
01081 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01082 __FILE__, __LINE__, "Non-monotone "
01083 "dispersion at x=%g: P'(x)=0, "
01084 "P(x)=%g", xextreme,
01085 cpl_polynomial_eval_1d(disp, xextreme,
01086 NULL));
01087 }
01088
01089 if (dofast) {
01090 const int npix = 1+(int)xtrunc;
01091
01092 if (erftmp != NULL && cpl_vector_get_size(erftmp) == npix &&
01093 cpl_vector_get(erftmp, 0) > 0.0) {
01094 profile = cpl_vector_get_data(erftmp);
01095 } else {
01096
01097 const double yval = 0.5 / wslit;
01098 const double x0p = 0.5 * wslit + 0.5;
01099 const double x0n = -0.5 * wslit + 0.5;
01100 double x1diff
01101 = irplib_erf_antideriv(x0p, sigma)
01102 - irplib_erf_antideriv(x0n, sigma);
01103 int ipix;
01104
01105 if (erftmp == NULL) {
01106 profile = (double*)cpl_malloc(sizeof(double)*(size_t)npix);
01107 } else {
01108 cpl_vector_set_size(erftmp, npix);
01109 profile = cpl_vector_get_data(erftmp);
01110 }
01111
01112 profile[0] = 2.0 * yval * x1diff;
01113
01114 for (ipix = 1; ipix < npix; ipix++) {
01115 const double x1 = (double)ipix;
01116 const double x1p = x1 + 0.5 * wslit + 0.5;
01117 const double x1n = x1 - 0.5 * wslit + 0.5;
01118 const double x0diff = x1diff;
01119
01120 x1diff = irplib_erf_antideriv(x1p, sigma)
01121 - irplib_erf_antideriv(x1n, sigma);
01122
01123 profile[ipix] = yval * (x1diff - x0diff);
01124
01125 }
01126 }
01127 }
01128
01129 cpl_polynomial_copy(dispi, disp);
01130
01131
01132
01133
01134
01135 xpos -= (wl - dxlines[iline]) / xderiv;
01136
01137
01138 for (; !error && iline < nlines; iline++) {
01139
01140
01141
01142 if (dylines[iline] <= 0.0) continue;
01143
01144
01145 if (plinepix != NULL && plinepix[iline] > 0.0) xpos = plinepix[iline];
01146
01147 if (xpos > xmax) xpos = xmax;
01148
01149
01150 error = cpl_polynomial_set_coeff(dispi, &i0, p0 - dxlines[iline]) ||
01151 cpl_polynomial_solve_1d(dispi, xpos, &xpos, 1);
01152
01153 if (xpos > xmax) {
01154 if (error) {
01155 error = 0;
01156 cpl_msg_debug(cpl_func, "Stopping spectrum fill at line %d/%d "
01157 "at xpos=%g > xmax=%g",
01158 iline, nlines, xpos, xmax);
01159 cpl_errorstate_dump(prestate, CPL_FALSE,
01160 irplib_errorstate_dump_debug);
01161 cpl_errorstate_set(prestate);
01162 }
01163 break;
01164 } else if (error) {
01165 if (linepix != NULL && ulines) (void)cpl_vector_fill(linepix, 0.0);
01166 (void)cpl_error_set_message_macro(cpl_func, cpl_error_get_code(),
01167 __FILE__, __LINE__,
01168 "Could not find pixel-position "
01169 "of line %d/%d at wavelength=%g."
01170 " xpos=%g, xmax=%g",
01171 iline, nlines, dxlines[iline],
01172 xpos, xmax);
01173 break;
01174 } else if (dofast) {
01175 const double frac = fabs(xpos - floor(xpos));
01176 #ifdef IRPLIB_WAVECAL_FAST_FAST
01177 const double frac0 = 1.0 - frac;
01178 #else
01179
01180 const double ep1pw = irplib_erf_antideriv(frac + 0.5 * wslit, sigma);
01181 const double en1pw = irplib_erf_antideriv(frac + 0.5 * wslit - 1.0,
01182 sigma);
01183 const double ep1nw = irplib_erf_antideriv(frac - 0.5 * wslit, sigma);
01184 const double en1nw = irplib_erf_antideriv(frac - 0.5 * wslit - 1.0,
01185 sigma);
01186 const double frac0
01187 = (en1nw - en1pw) / (ep1pw - en1pw - ep1nw + en1nw);
01188
01189 #endif
01190 const double frac1 = 1.0 - frac0;
01191 const double yval0 = frac0 * dylines[iline];
01192 const double yval1 = frac1 * dylines[iline];
01193 const int npix = 1+(int)xtrunc;
01194 int ipix;
01195 int i0n = hsize - 1 + floor(xpos);
01196 int i0p = i0n;
01197 int i1n = i0n + 1;
01198 int i1p = i1n;
01199 cpl_boolean didline = CPL_FALSE;
01200
01201
01202
01203 if (plinepix != NULL) plinepix[iline] = xpos;
01204
01205 if (frac0 < 0.0) {
01206 (void)cpl_error_set_message_macro(cpl_func,
01207 CPL_ERROR_UNSPECIFIED,
01208 __FILE__, __LINE__,
01209 "Illegal split at x=%g: %g + "
01210 "%g = 1", xpos, frac0, frac1);
01211 #ifdef IRPLIB_WAVEVAL_DEBUG
01212 } else {
01213 cpl_msg_warning(cpl_func,"profile split at x=%g: %g + %g = 1",
01214 xpos, frac0, frac1);
01215 #endif
01216 }
01217
01218 for (ipix = 0; ipix < npix; ipix++, i0n--, i0p++, i1n--, i1p++) {
01219
01220 if (i0n >= 0 && i0n < nself) {
01221 dself[i0n] += yval0 * profile[ipix];
01222 didline = CPL_TRUE;
01223 }
01224 if (i1n >= 0 && i1n < nself && ipix + 1 < npix) {
01225 dself[i1n] += yval1 * profile[ipix+1];
01226 didline = CPL_TRUE;
01227 }
01228
01229 if (ipix == 0) continue;
01230
01231 if (i0p >= 0 && i0p < nself) {
01232 dself[i0p] += yval0 * profile[ipix];
01233 didline = CPL_TRUE;
01234 }
01235 if (i1p >= 0 && i1p < nself && ipix + 1 < npix) {
01236 dself[i1p] += yval1 * profile[ipix+1];
01237 didline = CPL_TRUE;
01238 }
01239 }
01240
01241 if (didline) ulines++;
01242
01243 } else {
01244 const double yval = 0.5 * dylines[iline] / wslit;
01245 const int ifirst = IRPLIB_MAX((int)(xpos-xtrunc+0.5), 1-hsize);
01246 const int ilast = IRPLIB_MIN((int)(xpos+xtrunc), nself-hsize);
01247 int ipix;
01248 const double x0 = (double)ifirst - xpos;
01249 const double x0p = x0 + 0.5*wslit - 0.5;
01250 const double x0n = x0 - 0.5*wslit - 0.5;
01251 double x1diff
01252 = irplib_erf_antideriv(x0p, sigma)
01253 - irplib_erf_antideriv(x0n, sigma);
01254
01255
01256 if (plinepix != NULL) plinepix[iline] = xpos;
01257
01258 if (ilast >= ifirst) ulines++;
01259
01260 for (ipix = ifirst; ipix <= ilast; ipix++) {
01261 const double x1 = (double)ipix - xpos;
01262 const double x1p = x1 + 0.5*wslit + 0.5;
01263 const double x1n = x1 - 0.5*wslit + 0.5;
01264 const double x0diff = x1diff;
01265
01266 x1diff = irplib_erf_antideriv(x1p, sigma)
01267 - irplib_erf_antideriv(x1n, sigma);
01268
01269 dself[ipix+hsize-1] += yval * (x1diff - x0diff);
01270
01271 }
01272 }
01273 }
01274
01275 cpl_polynomial_delete(dispi);
01276 if (erftmp == NULL) cpl_free(profile);
01277
01278 cpl_ensure_code(!error, cpl_error_get_code());
01279
01280 if (dolog) {
01281 int i;
01282 for (i = 0; i < nself; i++) {
01283 dself[i] = dself[i] > 0.0 ? log(1.0 + dself[i]) : 0.0;
01284 }
01285 }
01286
01287 if (!ulines) return
01288 cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01289 __FILE__, __LINE__, "The %d-line "
01290 "catalogue has no lines in the range "
01291 "%g -> P(%g)=%g", nlines, wl, xmax,
01292 cpl_polynomial_eval_1d(disp, xmax, NULL));
01293
01294 if (pulines != NULL) *pulines = ulines;
01295
01296 return CPL_ERROR_NONE;
01297 }
01298
01299
01308
01309 inline double irplib_erf_antideriv(double x, double sigma)
01310 {
01311 return x * erf( x / (sigma * CPL_MATH_SQRT2))
01312 + 2.0 * sigma/CPL_MATH_SQRT2PI * exp(-0.5 * x * x / (sigma * sigma));
01313 }
01314
01315
01316 #ifdef HAVE_GSL
01317
01318
01326
01327 static double irplib_gsl_correlation(const gsl_vector * self, void * data)
01328 {
01329
01330 irplib_multimin * mindata = (irplib_multimin *)data;
01331 cpl_errorstate prestate = cpl_errorstate_get();
01332 int nobs, nmodel, ndiff;
01333 int i;
01334
01335 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01336 cpl_ensure(data != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01337
01338 cpl_ensure(mindata->filler != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01339 cpl_ensure(mindata->observed != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01340 cpl_ensure(mindata->spectrum != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
01341
01342 nobs = cpl_vector_get_size(mindata->observed);
01343 nmodel = cpl_vector_get_size(mindata->spectrum);
01344 ndiff = nmodel - nobs;
01345
01346 cpl_ensure((ndiff & 1) == 0, CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
01347
01348 cpl_ensure(cpl_vector_get_size(mindata->vxc) == 1 + ndiff,
01349 CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
01350
01351 ndiff /= 2;
01352
01353 for (i=0; i < (int)self->size; i++) {
01354 const double value = gsl_vector_get(self, i);
01355 cpl_polynomial_set_coeff(mindata->disp1d, &i, value);
01356 }
01357
01358 if (mindata->filler(mindata->spectrum, mindata->disp1d,
01359 mindata->param, ndiff)
01360 || !cpl_errorstate_is_equal(prestate)) {
01361
01362
01363
01364
01365 (void)cpl_vector_fill(mindata->vxc, -1.0);
01366
01367 mindata->maxxc = ndiff;
01368
01369 if (!cpl_errorstate_is_equal(prestate)) {
01370 cpl_msg_debug(cpl_func, "Spectrum fill failed:");
01371 cpl_errorstate_dump(prestate, CPL_FALSE,
01372 irplib_errorstate_dump_debug);
01373 cpl_errorstate_set(prestate);
01374 }
01375 } else {
01376
01377 mindata->maxxc = cpl_vector_correlate(mindata->vxc,
01378 mindata->spectrum,
01379 mindata->observed);
01380 }
01381
01382 #ifdef IRPLIB_SPC_DUMP
01383
01384 irplib_polynomial_dump_corr_step(mindata->disp1d, mindata->vxc,
01385 "Optimize");
01386 #endif
01387
01388 mindata->xc = cpl_vector_get(mindata->vxc, ndiff);
01389
01390 if (mindata->maxxc != ndiff &&
01391 cpl_vector_get(mindata->vxc, mindata->maxxc) > mindata->mxc) {
01392 const irplib_base_spectrum_model * arclamp
01393 = (const irplib_base_spectrum_model *)mindata->param;
01394
01395 if (mindata->mdisp == NULL) {
01396 mindata->mdisp = cpl_polynomial_duplicate(mindata->disp1d);
01397 } else {
01398 cpl_polynomial_copy(mindata->mdisp, mindata->disp1d);
01399 }
01400 mindata->mxc = cpl_vector_get(mindata->vxc, mindata->maxxc);
01401 mindata->ishift = mindata->maxxc - ndiff;
01402 cpl_msg_debug(cpl_func, "Local maximum: %g(%d) > %g(%d) (cost=%u:%u. "
01403 "lines=%u)", mindata->mxc, mindata->maxxc, mindata->xc,
01404 ndiff, arclamp->cost, arclamp->xcost, arclamp->ulines);
01405 }
01406
01407 return -mindata->xc;
01408 }
01409
01410 #endif
01411
01412
01435
01436 cpl_error_code
01437 irplib_polynomial_find_1d_from_correlation_all(cpl_polynomial * self,
01438 int maxdeg,
01439 const cpl_vector * obs,
01440 int nmaxima,
01441 int linelim,
01442 irplib_base_spectrum_model* model,
01443 cpl_error_code (* filler)
01444 (cpl_vector *,
01445 const cpl_polynomial *,
01446 irplib_base_spectrum_model *,
01447 int),
01448 double pixtol,
01449 double pixstep,
01450 int hsize,
01451 int maxite,
01452 int maxfail,
01453 int maxcont,
01454 cpl_boolean doplot,
01455 double * pxc)
01456 {
01457
01458 #ifdef HAVE_GSL
01459
01460 cpl_errorstate prestate = cpl_errorstate_get();
01461 cpl_polynomial * start;
01462 cpl_polynomial * cand;
01463 cpl_polynomial * backup;
01464 cpl_error_code error = CPL_ERROR_NONE;
01465 double xc;
01466 cpl_bivector * xtshift = cpl_bivector_new(nmaxima ? nmaxima : 1);
01467 const cpl_vector * xtshiftx = cpl_bivector_get_x_const(xtshift);
01468 const cpl_vector * xtshifty = cpl_bivector_get_y_const(xtshift);
01469 int nshift;
01470 int imaximum = -1;
01471 int imaxima;
01472
01473 #endif
01474
01475 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01476 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
01477 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
01478 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
01479 cpl_ensure_code(pxc != NULL, CPL_ERROR_NULL_INPUT);
01480
01481 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
01482 CPL_ERROR_ILLEGAL_INPUT);
01483
01484 cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
01485 CPL_ERROR_ILLEGAL_INPUT);
01486
01487 cpl_ensure_code(maxdeg >= 0, CPL_ERROR_ILLEGAL_INPUT);
01488 cpl_ensure_code(pixtol > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01489 cpl_ensure_code(pixstep > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01490 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
01491 cpl_ensure_code(maxite >= 0, CPL_ERROR_ILLEGAL_INPUT);
01492 cpl_ensure_code(nmaxima >= 0, CPL_ERROR_ILLEGAL_INPUT);
01493 cpl_ensure_code(maxfail > 0, CPL_ERROR_ILLEGAL_INPUT);
01494 cpl_ensure_code(maxcont > 0, CPL_ERROR_ILLEGAL_INPUT);
01495 cpl_ensure_code(linelim >= 0, CPL_ERROR_ILLEGAL_INPUT);
01496
01497 #ifndef HAVE_GSL
01498
01499 cpl_ensure_code(doplot == CPL_TRUE || doplot == CPL_FALSE,
01500 CPL_ERROR_ILLEGAL_INPUT);
01501 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
01502 "GSL is not available");
01503 #else
01504
01505 if (irplib_bivector_find_shift_from_correlation(xtshift, self, obs,
01506 model, filler,
01507 hsize, doplot, &xc)) {
01508 cpl_bivector_delete(xtshift);
01509 return cpl_error_set_where(cpl_func);
01510 }
01511
01512 if (model->ulines > (unsigned)linelim) {
01513
01514 const double xxc = cpl_vector_get(xtshiftx, 0);
01515 const double xc0 = cpl_vector_get(xtshifty, 0);
01516
01517 cpl_msg_warning(cpl_func, "Doing only shift=%g pixels with lines=%u > "
01518 "%d and XC=%g", xxc, model->ulines, linelim, xc0);
01519
01520 cpl_polynomial_shift_1d(self, 0, xxc);
01521
01522 *pxc = xc0;
01523
01524 cpl_bivector_delete(xtshift);
01525
01526 return CPL_ERROR_NONE;
01527 }
01528
01529 start = cpl_polynomial_duplicate(self);
01530 cand = cpl_polynomial_new(1);
01531 backup = cpl_polynomial_new(1);
01532
01533
01534 nshift = cpl_bivector_get_size(xtshift);
01535 if (nmaxima == 0 || nmaxima > nshift) nmaxima = nshift;
01536
01537 cpl_msg_info(cpl_func, "Optimizing %d/%d local shift-maxima "
01538 "(no-shift xc=%g. linelim=%d)", nmaxima, nshift, xc, linelim);
01539 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
01540 cpl_bivector_dump(xtshift, stdout);
01541
01542 for (imaxima = 0; imaxima < nmaxima; imaxima++) {
01543
01544 const double xxc = cpl_vector_get(xtshiftx, imaxima);
01545 double xtpixstep = pixstep;
01546 double xtpixtol = pixtol;
01547 double xtxc;
01548 cpl_boolean ok = CPL_FALSE;
01549 int nfail;
01550
01551
01552 cpl_polynomial_copy(cand, start);
01553 cpl_polynomial_shift_1d(cand, 0, xxc);
01554 cpl_polynomial_copy(backup, cand);
01555
01556
01557 for (nfail = 0; nfail < maxfail; nfail++, xtpixtol *= 2.0,
01558 xtpixstep *= 2.0) {
01559 int restart = maxcont;
01560 do {
01561 error = irplib_polynomial_find_1d_from_correlation
01562 (cand, maxdeg, obs, model,
01563 filler, xtpixtol, xtpixstep, 2,
01564 maxite, &xtxc);
01565 } while (error == CPL_ERROR_CONTINUE && --restart);
01566
01567 if (!error) {
01568 cpl_msg_debug(cpl_func, "XC(imax=%d/%d:xtpixtol=%g): %g "
01569 "(cost=%u:%u)", 1+imaxima, nmaxima, xtpixtol,
01570 xtxc, model->cost, model->xcost);
01571 break;
01572 }
01573 cpl_msg_warning(cpl_func, "Increasing xtpixtol from %g (%g, imax="
01574 "%d/%d)", xtpixtol, xtpixstep, 1+imaxima, nmaxima);
01575 if (model->ulines > (unsigned)linelim) {
01576 cpl_msg_warning(cpl_func, "Stopping search-refinement via "
01577 "catalogue with %u lines > %u", model->ulines,
01578 linelim);
01579 break;
01580 }
01581 cpl_polynomial_copy(cand, start);
01582 }
01583
01584
01585 for (; !error && xtpixtol > 0.0; xtpixtol *= 0.25, xtpixstep *= 0.5) {
01586 int restart = maxcont;
01587
01588 cpl_polynomial_copy(backup, cand);
01589 do {
01590 error = irplib_polynomial_find_1d_from_correlation
01591 (cand, maxdeg, obs, model, filler,
01592 xtpixtol, xtpixstep, 2, maxite, &xtxc);
01593 } while (error == CPL_ERROR_CONTINUE && --restart);
01594 if (error) break;
01595 ok = CPL_TRUE;
01596 cpl_msg_debug(cpl_func, "XC(imax=%d/%d:xtpixtol=%g): %g (cost=%u:%u"
01597 ". ulines=%u)", 1+imaxima, nmaxima, xtpixtol, xtxc,
01598 model->cost, model->xcost, model->ulines);
01599 if (model->ulines > (unsigned)linelim) {
01600 cpl_msg_info(cpl_func, "Stopping search-refinement via "
01601 "catalogue with %u lines > %u", model->ulines,
01602 linelim);
01603 break;
01604 }
01605 }
01606
01607 if (error) {
01608 error = 0;
01609 cpl_errorstate_dump(prestate, CPL_FALSE,
01610 irplib_errorstate_dump_debug);
01611 cpl_errorstate_set(prestate);
01612 cpl_polynomial_copy(cand, backup);
01613 }
01614 if (ok && xtxc > xc) {
01615 imaximum = imaxima;
01616 cpl_polynomial_copy(self, cand);
01617 xc = xtxc;
01618
01619 cpl_msg_info(cpl_func, "XC(imax=%d/%d): %g -> %g (initial-shift=%g. "
01620 "cost=%u:%u. lines=%u)", 1+imaxima, nmaxima,
01621 cpl_vector_get(xtshifty, imaxima), xtxc,
01622 cpl_vector_get(xtshiftx, imaxima), model->cost,
01623 model->xcost, model->ulines);
01624 } else {
01625 cpl_msg_info(cpl_func, "xc(imax=%d/%d): %g -> %g (initial-shift=%g. "
01626 "cost=%u:%u. lines=%u)", 1+imaxima, nmaxima,
01627 cpl_vector_get(xtshifty, imaxima), xtxc,
01628 cpl_vector_get(xtshiftx, imaxima),
01629 model->cost, model->xcost, model->ulines);
01630 }
01631 }
01632
01633 cpl_polynomial_delete(start);
01634 cpl_polynomial_delete(backup);
01635 cpl_polynomial_delete(cand);
01636
01637 if (imaximum < 0) {
01638 error = cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
01639 "XC could not be optimized over %d "
01640 "local shift-maxima (xc=%g)", nmaxima, xc);
01641 } else {
01642 cpl_msg_info(cpl_func, "Maximal XC=%g (up from %g, with initial pixel-"
01643 "shift of %g) at %d/%d local shift-maximi", xc,
01644 cpl_vector_get(xtshifty, imaximum),
01645 cpl_vector_get(xtshiftx, imaximum),
01646 1+imaximum, nmaxima);
01647
01648 if (doplot) {
01649 irplib_plot_spectrum_and_model(obs, self, model, filler);
01650 }
01651
01652 *pxc = xc;
01653 }
01654
01655 cpl_bivector_delete(xtshift);
01656
01657 return error;
01658
01659 #endif
01660
01661 }