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 #include "irplib_plot.h"
00047
00048
00049
00050
00051
00052
00053 typedef struct {
00054
00055 const cpl_vector * observed;
00056 cpl_polynomial * disp1d;
00057 cpl_vector * spectrum;
00058 void * param;
00059 cpl_error_code (* filler)(cpl_vector *, const cpl_polynomial *,
00060 void *, 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
00102
00112
00113 cpl_error_code irplib_polynomial_fit_2d_dispersion(cpl_polynomial * self,
00114 const cpl_image * imgwave,
00115 int fitdeg, double * presid)
00116 {
00117
00118 const int nx = cpl_image_get_size_x(imgwave);
00119 const int ny = cpl_image_get_size_y(imgwave);
00120 const int nbad = cpl_image_count_rejected(imgwave);
00121 const int nsamp = nx * ny - nbad;
00122 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00123 cpl_matrix * xy_pos;
00124 #else
00125 cpl_bivector * xy_pos;
00126 cpl_polynomial * copy;
00127 #endif
00128 double * xdata;
00129 double * ydata;
00130 cpl_vector * wlen;
00131 double * dwlen;
00132 int i, j;
00133 int k = 0;
00134
00135 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00136 cpl_ensure_code(imgwave != NULL, CPL_ERROR_NULL_INPUT);
00137 cpl_ensure_code(presid != NULL, CPL_ERROR_NULL_INPUT);
00138 cpl_ensure_code(fitdeg > 0, CPL_ERROR_ILLEGAL_INPUT);
00139
00140 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 2,
00141 CPL_ERROR_ILLEGAL_INPUT);
00142
00143 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00144 xy_pos = cpl_matrix_new(2, nsamp);
00145 xdata = cpl_matrix_get_data(xy_pos);
00146 ydata = xdata + nsamp;
00147 #else
00148 xy_pos = cpl_bivector_new(nsamp);
00149 xdata = cpl_bivector_get_x_data(xy_pos);
00150 ydata = cpl_bivector_get_y_data(xy_pos);
00151 #endif
00152
00153 dwlen = (double*)cpl_malloc(nsamp * sizeof(double));
00154 wlen = cpl_vector_wrap(nsamp, dwlen);
00155
00156 for (i=1; i <= nx; i++) {
00157 for (j=1; j <= ny; j++) {
00158 int is_bad;
00159 const double value = cpl_image_get(imgwave, i, j, &is_bad);
00160 if (!is_bad) {
00161 xdata[k] = i;
00162 ydata[k] = j;
00163 dwlen[k] = value;
00164 k++;
00165 }
00166 }
00167 }
00168
00169 cpl_msg_info(cpl_func, "Fitting 2D polynomial to %d X %d image, ignoring "
00170 "%d poorly calibrated pixels", nx, ny, nbad);
00171
00172 #ifdef HAVE_CPL_POLYNOMIAL_FIT
00173 if (cpl_polynomial_fit(self, xy_pos, NULL, wlen, NULL, CPL_FALSE, NULL,
00174 &fitdeg) == CPL_ERROR_NONE && presid != NULL) {
00175 cpl_vector_fill_polynomial_fit_residual(wlen, wlen, NULL, self, xy_pos,
00176 NULL);
00177 *presid = cpl_vector_product(wlen, wlen)/nsamp;
00178 }
00179 cpl_matrix_delete(xy_pos);
00180 #else
00181
00182 copy = cpl_polynomial_fit_2d_create(xy_pos, wlen, fitdeg, presid);
00183 cpl_polynomial_copy(self, copy);
00184 cpl_polynomial_delete(copy);
00185 cpl_bivector_delete(xy_pos);
00186 #endif
00187
00188 cpl_vector_delete(wlen);
00189
00190 cpl_ensure_code(k == nsamp, CPL_ERROR_UNSPECIFIED);
00191
00192 return CPL_ERROR_NONE;
00193 }
00194
00195
00213
00214 cpl_error_code
00215 irplib_polynomial_find_1d_from_correlation(cpl_polynomial * self,
00216 int maxdeg,
00217 const cpl_vector * obs,
00218 void * model,
00219 cpl_error_code (* filler)
00220 (cpl_vector *,
00221 const cpl_polynomial *,
00222 void *, int),
00223 double pixtol,
00224 double pixstep,
00225 int hsize,
00226 int maxite,
00227 double * pxc)
00228 {
00229
00230 #ifdef HAVE_GSL
00231 const gsl_multimin_fminimizer_type * T = gsl_multimin_fminimizer_nmsimplex;
00232 gsl_multimin_fminimizer * minimizer;
00233 gsl_multimin_function my_func;
00234 irplib_multimin data;
00235 gsl_vector * dispgsl;
00236 gsl_vector * stepsize;
00237 gsl_vector * dispprev;
00238 int status = GSL_CONTINUE;
00239 const int nobs = cpl_vector_get_size(obs);
00240 const int nfit = maxdeg + 1;
00241 cpl_errorstate prestate = cpl_errorstate_get();
00242
00243 const double wlstep =
00244 cpl_polynomial_eval_1d(self, 0.5 * (nobs + pixstep), NULL) -
00245 cpl_polynomial_eval_1d(self, 0.5 * (nobs - pixstep), NULL);
00246 double wlstepi = wlstep;
00247 double size;
00248 double fprev;
00249 int iter;
00250 int i;
00251
00252 #endif
00253
00254 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00255 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00256 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00257 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00258 cpl_ensure_code(pxc != NULL, CPL_ERROR_NULL_INPUT);
00259
00260 cpl_ensure_code(cpl_polynomial_get_dimension(self) == 1,
00261 CPL_ERROR_ILLEGAL_INPUT);
00262
00263 cpl_ensure_code(cpl_polynomial_get_degree(self) > 0,
00264 CPL_ERROR_ILLEGAL_INPUT);
00265
00266 cpl_ensure_code(maxdeg >= 0, CPL_ERROR_ILLEGAL_INPUT);
00267 cpl_ensure_code(pixtol > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00268 cpl_ensure_code(pixstep > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00269 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
00270 cpl_ensure_code(maxite >= 0, CPL_ERROR_ILLEGAL_INPUT);
00271
00272 #ifndef HAVE_GSL
00273 return cpl_error_set_message(cpl_func, CPL_ERROR_UNSUPPORTED_MODE,
00274 "GSL is not available");
00275 #else
00276
00277 minimizer = gsl_multimin_fminimizer_alloc(T, (size_t)nfit);
00278
00279 cpl_ensure_code(minimizer != NULL, CPL_ERROR_ILLEGAL_OUTPUT);
00280
00281 dispgsl = gsl_vector_alloc(nfit);
00282 stepsize = gsl_vector_alloc(nfit);
00283 dispprev = gsl_vector_alloc(nfit);
00284
00285 for (i=0; i < nfit; i++) {
00286 const double value = cpl_polynomial_get_coeff(self, &i);
00287 gsl_vector_set(dispgsl, i, value);
00288 gsl_vector_set(stepsize, i, wlstepi);
00289 wlstepi /= (double)nobs;
00290 }
00291
00292 my_func.n = nfit;
00293 my_func.f = &irplib_gsl_correlation;
00294 my_func.params = (void *)(&data);
00295
00296 data.observed = obs;
00297 data.disp1d = self;
00298 data.spectrum = cpl_vector_new(nobs + 2 * hsize);
00299 data.vxc = cpl_vector_new(1 + 2 * hsize);
00300 data.param = model;
00301 data.filler = filler;
00302 data.maxxc = 0;
00303 data.ishift = 0;
00304 data.mxc = -1.0;
00305 data.mdisp = NULL;
00306
00307 gsl_multimin_fminimizer_set (minimizer, &my_func, dispgsl, stepsize);
00308
00309 for (iter = 0; status == GSL_CONTINUE && iter < maxite; iter++) {
00310
00311 fprev = minimizer->fval;
00312 gsl_vector_memcpy(dispprev, minimizer->x);
00313 status = gsl_multimin_fminimizer_iterate(minimizer);
00314
00315 if (status || !cpl_errorstate_is_equal(prestate)) break;
00316
00317 size = gsl_multimin_fminimizer_size (minimizer);
00318 status = gsl_multimin_test_size (size, pixtol);
00319
00320 if (status == GSL_SUCCESS) {
00321 cpl_msg_debug(cpl_func, "converged to minimum at");
00322
00323 if (nfit == 0) {
00324 cpl_msg_debug(cpl_func, "%5d %g df() = %g size = %g",
00325 iter,
00326 gsl_vector_get (minimizer->x, 0)
00327 - gsl_vector_get (dispprev, 0),
00328 minimizer->fval - fprev, size);
00329 } else if (nfit == 1) {
00330 cpl_msg_debug(cpl_func, "%5d %g %g df() = %g size = %g",
00331 iter,
00332 gsl_vector_get (minimizer->x, 0)
00333 - gsl_vector_get (dispprev, 0),
00334 gsl_vector_get (minimizer->x, 1)
00335 - gsl_vector_get (dispprev, 1),
00336 minimizer->fval - fprev, size);
00337 } else {
00338 cpl_msg_debug(cpl_func, "%5d %g %g %g df() = %g size = %g",
00339 iter,
00340 gsl_vector_get (minimizer->x, 0)
00341 - gsl_vector_get (dispprev, 0),
00342 gsl_vector_get (minimizer->x, 1)
00343 - gsl_vector_get (dispprev, 1),
00344 gsl_vector_get (minimizer->x, 2)
00345 - gsl_vector_get (dispprev, 2),
00346 minimizer->fval - fprev, size);
00347 }
00348 }
00349 }
00350
00351 if (status == GSL_SUCCESS && cpl_errorstate_is_equal(prestate)) {
00352 if (data.mxc > -minimizer->fval) {
00353 *pxc = data.mxc;
00354 cpl_msg_warning(cpl_func, "Local maximum: %g(%d) > %g", data.mxc,
00355 data.ishift, -minimizer->fval);
00356 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 5, 0)
00357 cpl_polynomial_shift_1d(data.mdisp, 0, (double)data.ishift);
00358 #else
00359 cpl_polynomial_shift_1d(data.mdisp, (double)data.ishift);
00360 #endif
00361 cpl_polynomial_copy(self, data.mdisp);
00362 status = GSL_CONTINUE;
00363 } else {
00364 *pxc = -minimizer->fval;
00365 for (i=0; i < nfit; i++) {
00366 const double value = gsl_vector_get(minimizer->x, i);
00367 cpl_polynomial_set_coeff(self, &i, value);
00368 }
00369 }
00370 }
00371
00372 cpl_vector_delete(data.spectrum);
00373 cpl_vector_delete(data.vxc);
00374 cpl_polynomial_delete(data.mdisp);
00375 gsl_multimin_fminimizer_free(minimizer);
00376 gsl_vector_free(dispgsl);
00377 gsl_vector_free(dispprev);
00378 gsl_vector_free(stepsize);
00379
00380 cpl_ensure_code(status != GSL_CONTINUE, CPL_ERROR_CONTINUE);
00381 cpl_ensure_code(status == GSL_SUCCESS, CPL_ERROR_DATA_NOT_FOUND);
00382 cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00383
00384 return CPL_ERROR_NONE;
00385 #endif
00386 }
00387
00388
00389
00417
00418 cpl_error_code irplib_vector_fill_line_spectrum(cpl_vector * self,
00419 const cpl_polynomial * disp,
00420 void * lsslamp,
00421 int hsize)
00422 {
00423
00424 irplib_line_spectrum_model * arclamp
00425 = (irplib_line_spectrum_model *)lsslamp;
00426 cpl_error_code error;
00427
00428 cpl_ensure_code(arclamp != NULL, CPL_ERROR_NULL_INPUT);
00429
00430 error = irplib_vector_fill_line_spectrum_model(self,
00431 arclamp->linepix,
00432 disp,
00433 arclamp->lines,
00434 arclamp->wslit,
00435 arclamp->wfwhm,
00436 arclamp->xtrunc, hsize);
00437 cpl_ensure_code(!error, error);
00438
00439 arclamp->cost++;
00440
00441 return CPL_ERROR_NONE;
00442 }
00443
00444
00455
00456 cpl_error_code irplib_plot_spectrum_and_model(const cpl_vector * self,
00457 const cpl_polynomial * disp1d,
00458 void * model,
00459 cpl_error_code (* filler)
00460 (cpl_vector *,
00461 const cpl_polynomial *,
00462 void *, int))
00463 {
00464
00465 cpl_errorstate prestate = cpl_errorstate_get();
00466 cpl_vector * wl;
00467 cpl_vector * spectrum;
00468 cpl_vector * vxc;
00469 const int len = cpl_vector_get_size(self);
00470 double maxval, xc;
00471 int ixc;
00472 int error = 0;
00473
00474 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00475 cpl_ensure_code(disp1d != NULL, CPL_ERROR_NULL_INPUT);
00476 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00477 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00478
00479 cpl_ensure_code(cpl_polynomial_get_dimension(disp1d) == 1,
00480 CPL_ERROR_ILLEGAL_INPUT);
00481
00482 cpl_ensure_code(cpl_polynomial_get_degree(disp1d) > 0,
00483 CPL_ERROR_ILLEGAL_INPUT);
00484
00485 wl = cpl_vector_new(len);
00486 spectrum = cpl_vector_new(len);
00487 vxc = cpl_vector_new(1);
00488
00489 error |= (int)cpl_vector_fill_polynomial(wl, disp1d, 1.0, 1.0);
00490 error |= filler(spectrum, disp1d, model, 0);
00491
00492 ixc = cpl_vector_correlate(vxc, self, spectrum);
00493 xc = cpl_vector_get(vxc, 0);
00494
00495 maxval = cpl_vector_get_max(spectrum);
00496 if (maxval != 0.0)
00497 error |= cpl_vector_multiply_scalar(spectrum,
00498 cpl_vector_get_max(self)/maxval);
00499 if (!error) {
00500 const cpl_vector * spair[] = {wl, self, spectrum};
00501 char * pre = cpl_sprintf("set grid;set xlabel 'Wavelength (%g -> %g)'; "
00502 "set ylabel 'Intensity';", cpl_vector_get(wl, 0),
00503 cpl_vector_get(wl, len-1));
00504 char * title = cpl_sprintf("t 'Observed and modelled spectra (%d pixel "
00505 "XC=%g) ' w linespoints", len, xc);
00506
00507 error = irplib_vectors_plot(pre, title, "", spair, 3);
00508 cpl_free(pre);
00509 cpl_free(title);
00510 }
00511
00512 cpl_vector_delete(wl);
00513 cpl_vector_delete(spectrum);
00514 cpl_vector_delete(vxc);
00515
00516 cpl_errorstate_set(prestate);
00517
00518 return CPL_ERROR_NONE;
00519 }
00520
00521
00533
00534 cpl_error_code irplib_polynomial_shift_1d_from_correlation(cpl_polynomial * self,
00535 const cpl_vector * obs,
00536 void * model,
00537 cpl_error_code (*filler)
00538 (cpl_vector *,
00539 const cpl_polynomial *,
00540 void *, int),
00541 int hsize,
00542 cpl_boolean doplot)
00543 {
00544
00545 const int nobs = cpl_vector_get_size(obs);
00546 const int nmodel = 2 * hsize + nobs;
00547 cpl_vector * mspec1d;
00548 cpl_vector * xcorr;
00549 cpl_error_code error;
00550 int ixc, xxc;
00551
00552 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00553 cpl_ensure_code(obs != NULL, CPL_ERROR_NULL_INPUT);
00554 cpl_ensure_code(model != NULL, CPL_ERROR_NULL_INPUT);
00555 cpl_ensure_code(filler != NULL, CPL_ERROR_NULL_INPUT);
00556 cpl_ensure_code(hsize > 0, CPL_ERROR_ILLEGAL_INPUT);
00557
00558 mspec1d = cpl_vector_new(nmodel);
00559
00560 if (filler(mspec1d, self, model, hsize)) {
00561 cpl_vector_delete(mspec1d);
00562 cpl_ensure_code(0, cpl_error_get_code());
00563 }
00564
00565
00566 xcorr = cpl_vector_new(1 + 2 * hsize);
00567 ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00568
00569 #ifdef IRPLIB_SPC_DUMP
00570
00571 irplib_polynomial_dump_corr_step(self, xcorr, "Shift");
00572 #endif
00573
00574 cpl_vector_delete(mspec1d);
00575
00576 xxc = ixc - hsize;
00577
00578 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 5, 0)
00579 error = cpl_polynomial_shift_1d(self, 0, (double)xxc);
00580 #else
00581 error = cpl_polynomial_shift_1d(self, (double)xxc);
00582 #endif
00583
00584
00585 cpl_msg_info(cpl_func, "Shifting %d pixels (%g < %g)", xxc,
00586 cpl_vector_get(xcorr, hsize), cpl_vector_get(xcorr, ixc));
00587
00588 if (doplot) {
00589 cpl_vector * xvals = cpl_vector_new(1 + 2 * hsize);
00590 cpl_bivector * bcorr = cpl_bivector_wrap_vectors(xvals, xcorr);
00591 int i;
00592 double x = (double)-hsize;
00593 char * title = cpl_sprintf("t 'Cross-correlation of shifted %d-pixel "
00594 "spectrum (XCmax=%g at %d)' w linespoints",
00595 nobs, cpl_vector_get(xcorr, ixc), xxc);
00596
00597 for (i = 0; i < 1 + 2 * hsize; i++, x += 1.0) {
00598 cpl_vector_set(xvals, i, x);
00599 }
00600
00601 irplib_bivector_plot("set grid;set xlabel 'Offset [pixel]';", title,
00602 "", bcorr);
00603 cpl_bivector_unwrap_vectors(bcorr);
00604 cpl_vector_delete(xvals);
00605 cpl_free(title);
00606 }
00607
00608 cpl_vector_delete(xcorr);
00609
00610 cpl_ensure_code(!error, error);
00611
00612 return CPL_ERROR_NONE;
00613
00614 }
00615
00616
00617
00634
00635 cpl_error_code
00636 irplib_vector_fill_line_spectrum_model(cpl_vector * self,
00637 cpl_vector * linepix,
00638 const cpl_polynomial * disp,
00639 const cpl_bivector * lines,
00640 double wslit,
00641 double wfwhm,
00642 double xtrunc,
00643 int hsize)
00644 {
00645
00646 cpl_errorstate prestate;
00647 const double sigma = wfwhm * CPL_MATH_SIG_FWHM;
00648 const cpl_vector * xlines = cpl_bivector_get_x_const(lines);
00649 const double * dxlines = cpl_vector_get_data_const(xlines);
00650 const double * dylines = cpl_bivector_get_y_data_const(lines);
00651 double * plinepix
00652 = linepix ? cpl_vector_get_data(linepix) : NULL;
00653 const int nlines = cpl_vector_get_size(xlines);
00654 const int nself = cpl_vector_get_size(self);
00655 double * dself = cpl_vector_get_data(self);
00656 cpl_polynomial * dispi;
00657 const int i0 = 0;
00658 const double p0 = cpl_polynomial_get_coeff(disp, &i0);
00659 double wl;
00660 double xpos = (double)(1-hsize)-xtrunc;
00661 const double xmax = (double)(nself-hsize)+xtrunc;
00662 double xderiv;
00663 cpl_error_code error = CPL_ERROR_NONE;
00664 cpl_boolean has_lines = CPL_FALSE;
00665 int iline;
00666
00667 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00668 cpl_ensure_code(disp != NULL, CPL_ERROR_NULL_INPUT);
00669 cpl_ensure_code(lines != NULL, CPL_ERROR_NULL_INPUT);
00670
00671 cpl_ensure_code(wslit > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00672 cpl_ensure_code(wfwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00673 cpl_ensure_code(hsize >= 0, CPL_ERROR_ILLEGAL_INPUT);
00674 cpl_ensure_code(xtrunc > 0.0, CPL_ERROR_ILLEGAL_INPUT);
00675 cpl_ensure_code(nself > 2 * hsize, CPL_ERROR_ILLEGAL_INPUT);
00676
00677 cpl_ensure_code(cpl_polynomial_get_dimension(disp) == 1,
00678 CPL_ERROR_ILLEGAL_INPUT);
00679 cpl_ensure_code(cpl_polynomial_get_degree(disp) > 0,
00680 CPL_ERROR_ILLEGAL_INPUT);
00681
00682
00683 wl = cpl_polynomial_eval_1d(disp, xpos, &xderiv);
00684
00685 if (wl <= 0.0) return
00686 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
00687 __LINE__, "Non-positive wavelength at x=%g: "
00688 "P(x)=%g, P'(x)=%g", xpos, wl, xderiv);
00689
00690 if (xderiv <= 0.0) return
00691 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT, __FILE__,
00692 __LINE__, "Non-increasing dispersion at "
00693 "x=%g: P'(x)=%g, P(x)=%g", xpos, xderiv, wl);
00694
00695
00696 iline = cpl_vector_find(xlines, wl);
00697
00698
00699 if (dxlines[iline] < wl) iline++;
00700
00701 if (iline >= nlines) return
00702 cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND, __FILE__,
00703 __LINE__, "The %d-line catalogue has only "
00704 "lines below P(%g)=%g > %g", nlines, xpos,
00705 wl, dxlines[nlines-1]);
00706
00707
00708
00709
00710 xpos -= (wl - dxlines[iline]) / xderiv;
00711
00712 memset(dself, 0, nself * sizeof(double));
00713
00714 dispi = cpl_polynomial_duplicate(disp);
00715
00716
00717 cpl_polynomial_derivative(dispi, 0);
00718
00719 prestate = cpl_errorstate_get();
00720 if (cpl_polynomial_solve_1d(dispi, 0.5*(nlines+1), &xderiv, 1)) {
00721 cpl_errorstate_set(prestate);
00722 } else if (xpos < xderiv && xderiv < xmax) {
00723 cpl_polynomial_delete(dispi);
00724 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00725 __FILE__, __LINE__, "Non-monotone "
00726 "dispersion at x=%g: P'(x)=0, "
00727 "P(x)=%g", xderiv,
00728 cpl_polynomial_eval_1d(disp, xderiv,
00729 NULL));
00730 }
00731
00732 cpl_polynomial_copy(dispi, disp);
00733
00734
00735 for (; !error && iline < nlines; iline++) {
00736
00737
00738
00739 if (dylines[iline] <= 0.0) continue;
00740
00741
00742 if (plinepix != NULL && plinepix[iline] > 0.0) xpos = plinepix[iline];
00743
00744
00745 error = cpl_polynomial_set_coeff(dispi, &i0, p0 - dxlines[iline]) ||
00746 cpl_polynomial_solve_1d(dispi, xpos, &xpos, 1);
00747
00748
00749 if (error || xpos > xmax) {
00750 break;
00751 } else {
00752 const double yval = 0.5 * dylines[iline] / wslit;
00753 const int ifirst = IRPLIB_MAX((int)(xpos-xtrunc+0.5), 1-hsize);
00754 const int ilast = IRPLIB_MIN((int)(xpos+xtrunc), nself-hsize);
00755 int ipix;
00756 const double x0 = (double)ifirst - xpos;
00757 const double x0p = x0 + 0.5*wslit - 0.5;
00758 const double x0n = x0 - 0.5*wslit - 0.5;
00759 double x1diff
00760 = irplib_erf_antideriv(x0p, sigma)
00761 - irplib_erf_antideriv(x0n, sigma);
00762
00763
00764 if (plinepix != NULL) plinepix[iline] = xpos;
00765
00766 has_lines = ilast >= ifirst;
00767
00768 for (ipix = ifirst; ipix <= ilast; ipix++) {
00769 const double x1 = (double)ipix - xpos;
00770 const double x1p = x1 + 0.5*wslit + 0.5;
00771 const double x1n = x1 - 0.5*wslit + 0.5;
00772 const double x0diff = x1diff;
00773
00774 x1diff = irplib_erf_antideriv(x1p, sigma)
00775 - irplib_erf_antideriv(x1n, sigma);
00776
00777 dself[ipix+hsize-1] += yval * (x1diff - x0diff);
00778
00779 }
00780 }
00781 }
00782
00783 cpl_polynomial_delete(dispi);
00784
00785 cpl_ensure_code(!error, cpl_error_get_code());
00786
00787 return has_lines ? CPL_ERROR_NONE
00788 : cpl_error_set_message_macro(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
00789 __FILE__, __LINE__, "The %d-line "
00790 "catalogue has no lines in the range "
00791 "%g -> P(%g)=%g", nlines, wl, xmax,
00792 cpl_polynomial_eval_1d(disp, xmax, NULL));
00793 }
00794
00795
00796
00805
00806 inline double irplib_erf_antideriv(double x, double sigma)
00807 {
00808 return x * erf( x / (sigma * CPL_MATH_SQRT2))
00809 + 2.0 * sigma/CPL_MATH_SQRT2PI * exp(-0.5 * x * x / (sigma * sigma));
00810 }
00811
00812
00813 #ifdef HAVE_GSL
00814
00815
00823
00824 static double irplib_gsl_correlation(const gsl_vector * self, void * data)
00825 {
00826
00827 irplib_multimin * mindata = (irplib_multimin *)data;
00828 int nobs, nmodel, ndiff;
00829 int i;
00830
00831 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
00832 cpl_ensure(data != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
00833
00834 cpl_ensure(mindata->filler != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
00835 cpl_ensure(mindata->observed != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
00836 cpl_ensure(mindata->spectrum != NULL, CPL_ERROR_NULL_INPUT, GSL_NAN);
00837
00838 nobs = cpl_vector_get_size(mindata->observed);
00839 nmodel = cpl_vector_get_size(mindata->spectrum);
00840 ndiff = nmodel - nobs;
00841
00842 cpl_ensure((ndiff & 1) == 0, CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
00843
00844 cpl_ensure(cpl_vector_get_size(mindata->vxc) == 1 + ndiff,
00845 CPL_ERROR_ILLEGAL_INPUT, GSL_NAN);
00846
00847 ndiff /= 2;
00848
00849 for (i=0; i < (int)self->size; i++) {
00850 const double value = gsl_vector_get(self, i);
00851 cpl_polynomial_set_coeff(mindata->disp1d, &i, value);
00852 }
00853
00854 cpl_ensure(!mindata->filler(mindata->spectrum, mindata->disp1d,
00855 mindata->param, ndiff), cpl_error_get_code(),
00856 GSL_NAN);
00857
00858 mindata->maxxc = cpl_vector_correlate(mindata->vxc,
00859 mindata->spectrum,
00860 mindata->observed);
00861
00862 #ifdef IRPLIB_SPC_DUMP
00863
00864 irplib_polynomial_dump_corr_step(mindata->disp1d, mindata->vxc, "Optimize");
00865 #endif
00866
00867 mindata->xc = cpl_vector_get(mindata->vxc, ndiff);
00868
00869 if (mindata->maxxc != ndiff &&
00870 cpl_vector_get(mindata->vxc, mindata->maxxc) > mindata->mxc) {
00871 if (mindata->mdisp == NULL) {
00872 mindata->mdisp = cpl_polynomial_duplicate(mindata->disp1d);
00873 } else {
00874 cpl_polynomial_copy(mindata->mdisp, mindata->disp1d);
00875 }
00876 mindata->mxc = cpl_vector_get(mindata->vxc, mindata->maxxc);
00877 mindata->ishift = mindata->maxxc - ndiff;
00878 cpl_msg_warning(cpl_func, "Local maximum: %g(%d) > %g(%d)",
00879 mindata->mxc, mindata->maxxc,
00880 mindata->xc, ndiff);
00881 }
00882
00883 return -mindata->xc;
00884 }
00885
00886 #endif