irplib_wavecal.c

00001 /* $Id: irplib_wavecal.c,v 1.18 2009/01/23 10:48:28 llundin Exp $
00002  *
00003  * This file is part of the IRPLIB Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2009/01/23 10:48:28 $
00024  * $Revision: 1.18 $
00025  * $Name: visir-3_2_2 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                    Includes
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                                Private types
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                                Defines
00072  -----------------------------------------------------------------------------*/
00073 
00074 #ifndef inline
00075 #define inline /* 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 /* Detect presence of cpl_polynoimial_fit() via fingerprinting */
00082 #if defined cpl_test_polynomial_abs
00083 #define HAVE_CPL_POLYNOMIAL_FIT
00084 #endif
00085 
00086 /*-----------------------------------------------------------------------------
00087                                    Private functions
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     /* FIXME: Waiting for new API of fitting function */
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     /* Convert pixel step to wavelength step on detector center */
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; /* Output */
00303     data.ishift   = 0; /* Output */
00304     data.mxc      = -1.0; /* Output */
00305     data.mdisp    = NULL; /* Output */
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     /* Should not be able to fail now */
00566     xcorr = cpl_vector_new(1 + 2 * hsize);
00567     ixc = cpl_vector_correlate(xcorr, mspec1d, obs);
00568 
00569 #ifdef IRPLIB_SPC_DUMP
00570     /* Need irplib_wavecal.c rev. 1.12 through 1.15 */
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     /* The smallest wavelength contributing to the spectrum. */
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     /* Find the 1st line */
00696     iline = cpl_vector_find(xlines, wl);
00697 
00698     /* The first line must be at least at wl */
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     /* FIXME: A custom version of cpl_polynomial_solve_1d() which returns
00708        P'(xpos) can be used for the 1st NR-iteration. */
00709     /* Perform 1st NR-iteration in solving for P(xpos) = dxlines[iline] */
00710     xpos -= (wl - dxlines[iline]) / xderiv;
00711 
00712     memset(dself, 0, nself * sizeof(double));
00713 
00714     dispi = cpl_polynomial_duplicate(disp);
00715 
00716     /* Verify monotony of dispersion */
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     /* Iterate through the lines */
00735     for (; !error && iline < nlines; iline++) {
00736 
00737         /* Lines may have a non-physical intensity (e.g. zero) to indicate some
00738            property of the line, e.g. unknown intensity due to blending */
00739         if (dylines[iline] <= 0.0) continue;
00740 
00741         /* Use 1st guess, if available (Use 0.0 to flag unavailable) */
00742         if (plinepix != NULL && plinepix[iline] > 0.0) xpos = plinepix[iline];
00743 
00744         /* Find the (sub-) pixel position of the line */
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             /* Update 1st guess for next time, if available */
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     /* Need irplib_wavecal.c rev. 1.12 through 1.15 */
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

Generated on Fri Jul 3 11:15:23 2009 for VISIR Pipeline Reference Manual by  doxygen 1.5.8