irplib_wlxcorr.c

00001 /* $Id: irplib_wlxcorr.c,v 1.45 2008/11/17 14:44:52 llundin Exp $
00002  *
00003  * This file is part of the IRPLIB package
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2008/11/17 14:44:52 $
00024  * $Revision: 1.45 $
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 <math.h>
00037 #include <string.h>
00038 
00039 #include <cpl.h>
00040 
00041 #include "irplib_wavecal_impl.h"
00042 
00043 #include "irplib_wlxcorr.h"
00044 #include "irplib_plot.h"
00045 
00046 /*----------------------------------------------------------------------------*/
00056 /*----------------------------------------------------------------------------*/
00057 
00058 /*-----------------------------------------------------------------------------
00059                            Defines
00060  -----------------------------------------------------------------------------*/
00061 
00062 #ifndef inline
00063 #define inline /* inline */
00064 #endif
00065 
00066 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
00067 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
00068 
00069 #define IRPLIB_PTR_SWAP(a,b)                                               \
00070     do { void * irplib_ptr_swap =(a);(a)=(b);(b)=irplib_ptr_swap; } while (0)
00071 
00072 /*-----------------------------------------------------------------------------
00073                            Private functions
00074  -----------------------------------------------------------------------------*/
00075 
00076 static void irplib_wlxcorr_estimate(cpl_vector *, cpl_vector *,
00077                                     const cpl_vector *,
00078                                     const cpl_bivector *,
00079                                     const cpl_vector *,
00080                                     const cpl_polynomial *,
00081                                     double, double);
00082 
00083 static int irplib_wlxcorr_signal_resample(cpl_vector *, const cpl_vector *, 
00084         const cpl_bivector *) ;
00085 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector *,
00086                                                             double, double);
00087 static cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector *,
00088                                                 const cpl_bivector *,
00089                                                 const cpl_vector *,
00090                                                 const cpl_polynomial *, int);
00091 
00092 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector *,
00093                                         const cpl_polynomial *,
00094                                         int, double);
00095 
00099 /*----------------------------------------------------------------------------*/
00135 /*----------------------------------------------------------------------------*/
00136 cpl_polynomial * irplib_wlxcorr_best_poly(const cpl_vector     * spectrum,
00137                                           const cpl_bivector   * lines_catalog,
00138                                           int                    degree,
00139                                           const cpl_polynomial * guess_poly,
00140                                           const cpl_vector     * wl_error,
00141                                           int                    nsamples,
00142                                           double                 slitw,
00143                                           double                 fwhm,
00144                                           double               * xc,
00145                                           cpl_table           ** wlres,
00146                                           cpl_vector          ** xcorrs)
00147 {
00148     const int         spec_sz = cpl_vector_get_size(spectrum);
00149     const int         nfree   = cpl_vector_get_size(wl_error);
00150     int               ntests  = 1;
00151     cpl_vector      * model;
00152     cpl_vector      * vxc;
00153     cpl_vector      * init_pts_wl;
00154 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00155     cpl_matrix      * init_pts_x;
00156 #else
00157     cpl_vector      * init_pts_x;
00158 #endif
00159     cpl_vector      * pts_wl;
00160     cpl_vector      * vxcorrs;
00161     cpl_vector      * conv_kernel = NULL;    
00162     cpl_polynomial  * poly_sol;
00163     cpl_polynomial  * poly_candi;
00164     const double    * pwl_error = cpl_vector_get_data_const(wl_error); 
00165     const double    * dxc;
00166 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00167     const cpl_boolean symsamp = CPL_TRUE; /* init_pts_x is symmetric */
00168 #endif
00169     const cpl_boolean is_lines
00170         = irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00171                                guess_poly, spec_sz, 1.0);
00172     int               i;
00173 
00174     /* FIXME: Need mode parameter for catalogue type (lines <=> profile) */
00175 
00176     /* In case of failure */
00177     if (wlres  != NULL) *wlres  = NULL;
00178     if (xcorrs != NULL) *xcorrs = NULL;
00179 
00180     /* Useful for knowing if resampling is used */
00181     cpl_msg_debug(cpl_func, "Checking %d^%d dispersion polynomials (slitw=%g, "
00182                   "fwhm=%g) against %d-point observed spectrum with%s "
00183                   "catalog resampling", nsamples, nfree, slitw, fwhm, spec_sz,
00184                   is_lines ? "out" : "");
00185 
00186     cpl_ensure(xc            != NULL, CPL_ERROR_NULL_INPUT,    NULL);
00187     *xc = -1.0;
00188     cpl_ensure(spectrum      != NULL,  CPL_ERROR_NULL_INPUT,    NULL);
00189     cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT,    NULL);
00190     cpl_ensure(guess_poly    != NULL, CPL_ERROR_NULL_INPUT,    NULL);
00191     cpl_ensure(wl_error      != NULL, CPL_ERROR_NULL_INPUT,    NULL);
00192     cpl_ensure(nfree         >= 2,    CPL_ERROR_ILLEGAL_INPUT, NULL);
00193     cpl_ensure(nsamples      >  0,    CPL_ERROR_ILLEGAL_INPUT, NULL);
00194     /* FIXME: degree is redundant */
00195     cpl_ensure(1 + degree   == nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00196 
00197     cpl_ensure(cpl_polynomial_get_dimension(guess_poly) == 1,
00198                CPL_ERROR_ILLEGAL_INPUT, NULL);
00199 
00200     if (nsamples > 1) {
00201         /* Search place must consist of more than one point */
00202         /* FIXME: The bounds should probably not be negative */
00203         for (i = 0; i < nfree; i++) {
00204             if (pwl_error[i] != 0.0) break;
00205         }
00206         cpl_ensure(i < nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00207     }
00208  
00209     if (!is_lines) {
00210         /* Create the convolution kernel */
00211         conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00212         cpl_ensure(conv_kernel   != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00213     }
00214 
00215     /* Create initial test points */
00216 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00217     init_pts_x  = cpl_matrix_new(1, nfree);
00218 #else
00219     init_pts_x  = cpl_vector_new(nfree);
00220 #endif
00221     init_pts_wl = cpl_vector_new(nfree);
00222     pts_wl      = cpl_vector_new(nfree);
00223     for (i = 0; i < nfree; i++) {
00224         const double xpos  = spec_sz * i / (double)degree;
00225         const double wlpos = cpl_polynomial_eval_1d(guess_poly, xpos, NULL)
00226             - 0.5 * pwl_error[i];
00227 
00228 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00229         cpl_matrix_set(init_pts_x, 0, i, xpos);
00230 #else
00231         cpl_vector_set(init_pts_x,    i, xpos);
00232 #endif
00233         cpl_vector_set(init_pts_wl,   i, wlpos);
00234 
00235         ntests *= nsamples; /* Count number of tests */
00236 
00237     }
00238 
00239     vxcorrs = xcorrs != NULL ? cpl_vector_new(ntests) : NULL;
00240 
00241     poly_sol   = cpl_polynomial_new(1);
00242     poly_candi = cpl_polynomial_new(1);
00243     model = cpl_vector_new(spec_sz);
00244     vxc = cpl_vector_new(1);
00245     dxc = cpl_vector_get_data_const(vxc);
00246    
00247     /* Create the polynomial candidates and estimate them */
00248     for (i=0; i < ntests; i++) {
00249         int    idiv = i;
00250         int    deg;
00251 
00252         /* Update wavelength at one anchor point - and reset wavelengths
00253            to their default for any anchor point(s) at higher wavelengths */
00254         for (deg = degree; deg >= 0; deg--, idiv /= nsamples) {
00255             const int imod = idiv % nsamples;
00256             const double wlpos = cpl_vector_get(init_pts_wl, deg)
00257                                + imod * pwl_error[deg] / nsamples;
00258 
00259             /* FIXME: If wlpos causes pts_wl to be non-increasing, the
00260                solution will be non-physical with no need for evaluation.
00261                (*xc could be set to -1 in this case). */
00262             cpl_vector_set(pts_wl, deg, wlpos);
00263 
00264             if (imod > 0) break;
00265         }
00266 
00267         /* Generate */
00268 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00269         cpl_polynomial_fit(poly_candi, init_pts_x, &symsamp, pts_wl,
00270                            NULL, CPL_FALSE, NULL, &degree);
00271 #else
00272         cpl_polynomial_delete(poly_candi);
00273         poly_candi = cpl_polynomial_fit_1d_create(init_pts_x, pts_wl, degree,
00274                                                   NULL);
00275 #endif
00276         /* *** Estimate *** */
00277         irplib_wlxcorr_estimate(vxc, model, spectrum, lines_catalog,
00278                                 conv_kernel, poly_candi, slitw, fwhm);
00279         if (vxcorrs != NULL) cpl_vector_set(vxcorrs, i, *dxc);
00280         if (*dxc > *xc) {
00281             /* Found a better solution */
00282             *xc = *dxc;
00283             IRPLIB_PTR_SWAP(poly_sol, poly_candi);
00284         }
00285     }
00286 
00287     cpl_vector_delete(model);
00288     cpl_vector_delete(vxc);
00289     cpl_vector_delete(conv_kernel);
00290     cpl_vector_delete(pts_wl);
00291 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00292     cpl_matrix_delete(init_pts_x);
00293 #else
00294     cpl_vector_delete(init_pts_x);
00295 #endif
00296     cpl_vector_delete(init_pts_wl);
00297     cpl_polynomial_delete(poly_candi);
00298 
00299 #ifdef CPL_WLCALIB_FAIL_ON_CONSTANT
00300     /* FIXME: */
00301     if (cpl_polynomial_get_degree(poly_sol) == 0) {
00302         cpl_polynomial_delete(poly_sol);
00303         cpl_vector_delete(vxcorrs);
00304         *xc = 0.0;
00305         cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00306                                     __FILE__, __LINE__, "Found a constant "
00307                                     "dispersion");
00308             cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00309         return NULL;
00310     }
00311 #endif
00312     
00313     if (wlres != NULL) {
00314         /* FIXME: A failure in the table creation is not considered a failure
00315            of the whole function call (although all outputs may be useless) */
00316 
00317         cpl_errorstate prestate = cpl_errorstate_get();
00318         /* Create the spc_table  */
00319         *wlres = irplib_wlxcorr_gen_spc_table(spectrum, lines_catalog, slitw,
00320                                               fwhm, guess_poly, poly_sol);
00321         if (*wlres == NULL) {
00322             cpl_polynomial_delete(poly_sol);
00323             cpl_vector_delete(vxcorrs);
00324             *xc = -1.0;
00325             cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00326                                         __FILE__, __LINE__, "Cannot generate "
00327                                         "infos table");
00328             /* cpl_errorstate_dump(prestate, CPL_FALSE, NULL); */
00329             cpl_errorstate_set(prestate);
00330             return NULL;
00331         }
00332     } 
00333     
00334     if (xcorrs != NULL) {
00335         *xcorrs = vxcorrs;
00336     } else {
00337         /* assert(vxcorrs == NULL); */
00338     }
00339 
00340     return poly_sol;
00341 }
00342 
00343 /*----------------------------------------------------------------------------*/
00361 /*----------------------------------------------------------------------------*/
00362 cpl_table * irplib_wlxcorr_gen_spc_table(
00363         const cpl_vector        *   spectrum,
00364         const cpl_bivector      *   lines_catalog,
00365         double                      slitw,
00366         double                      fwhm,
00367         const cpl_polynomial    *   guess_poly,
00368         const cpl_polynomial    *   corr_poly)
00369 {
00370 
00371     cpl_vector      *   conv_kernel = NULL;
00372     cpl_bivector    *   gen_init ;
00373     cpl_bivector    *   gen_corr ;
00374     cpl_table       *   spc_table ;
00375     const double    *   pgen ;
00376     const double        xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00377     const int           spec_sz = cpl_vector_get_size(spectrum);
00378     const cpl_boolean   guess_resamp
00379         = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00380                                 guess_poly, spec_sz, 1.0);
00381     const cpl_boolean   corr_resamp
00382         = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00383                                 corr_poly, spec_sz, 1.0);
00384     cpl_error_code      error;
00385 
00386     cpl_msg_debug(cpl_func, "Tabel for guess dispersion polynomial (slitw=%g, "
00387                   "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00388                   "sampling", slitw, fwhm, spec_sz, guess_resamp ? "out" : "");
00389     cpl_msg_debug(cpl_func, "Tabel for corr. dispersion polynomial (slitw=%g, "
00390                   "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00391                   "sampling", slitw, fwhm, spec_sz, corr_resamp ? "out" : "");
00392 
00393     /* Test inputs */
00394     cpl_ensure(spectrum, CPL_ERROR_NULL_INPUT, NULL) ;
00395     cpl_ensure(lines_catalog, CPL_ERROR_NULL_INPUT, NULL) ;
00396     cpl_ensure(guess_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00397     cpl_ensure(corr_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00398 
00399     /* Create the convolution kernel */
00400     if (guess_resamp || corr_resamp) {
00401         conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00402 
00403         if (conv_kernel == NULL) {
00404             cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00405                                         __FILE__, __LINE__, "Cannot create "
00406                                         "convolution kernel") ;
00407             return NULL ;
00408         }
00409     }
00410 
00411     /* Get the emission at initial wavelengths */
00412     gen_init = cpl_bivector_new(spec_sz);
00413     if (guess_resamp) {
00414         error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_init),
00415                                           lines_catalog, conv_kernel,
00416                                           guess_poly, 0);
00417     } else {
00418         error = irplib_vector_fill_line_spectrum_model
00419             (cpl_bivector_get_y(gen_init), NULL,
00420              guess_poly, lines_catalog,
00421              slitw, fwhm, xtrunc, 0);
00422     }
00423 
00424     if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_init),
00425                                             guess_poly, 1, 1)) {
00426         cpl_vector_delete(conv_kernel);
00427         cpl_bivector_delete(gen_init);
00428         cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00429                                     __FILE__, __LINE__, "Cannot get the "
00430                                     "emission spectrum");
00431         return NULL;
00432     }
00433  
00434     /* Get the emission at corrected wavelengths */
00435     gen_corr = cpl_bivector_new(spec_sz);
00436     if (corr_resamp) {
00437         error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_corr),
00438                                           lines_catalog, conv_kernel,
00439                                           corr_poly, 0);
00440     } else {
00441         error = irplib_vector_fill_line_spectrum_model
00442             (cpl_bivector_get_y(gen_corr), NULL,
00443              corr_poly, lines_catalog,
00444              slitw, fwhm, xtrunc, 0);
00445     }
00446 
00447     if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_corr),
00448                                             corr_poly, 1, 1)) {
00449         cpl_vector_delete(conv_kernel);
00450         cpl_bivector_delete(gen_init);
00451         cpl_bivector_delete(gen_corr) ;
00452         cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00453                                     __FILE__, __LINE__, "Cannot get the "
00454                                     "emission spectrum");
00455         return NULL;
00456     }
00457     cpl_vector_delete(conv_kernel) ;
00458 
00459     /* Create the ouput table */
00460     spc_table = cpl_table_new(spec_sz);
00461     cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH, 
00462             CPL_TYPE_DOUBLE);
00463     cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT, 
00464             CPL_TYPE_DOUBLE);
00465     cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL, 
00466             CPL_TYPE_DOUBLE);
00467     cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_OBS, CPL_TYPE_DOUBLE);
00468     
00469     /* Update table */
00470     pgen = cpl_bivector_get_x_data_const(gen_corr) ;
00471     cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH, pgen) ;
00472     pgen = cpl_bivector_get_y_data_const(gen_corr) ;
00473     cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL, pgen) ;
00474     pgen = cpl_vector_get_data_const(spectrum) ;
00475     cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_OBS, pgen) ;
00476     pgen = cpl_bivector_get_y_data_const(gen_init) ;
00477     cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT, pgen);
00478     cpl_bivector_delete(gen_init);
00479     cpl_bivector_delete(gen_corr);
00480 
00481     return spc_table ;
00482 }
00483 
00484 /*----------------------------------------------------------------------------*/
00496 /*----------------------------------------------------------------------------*/
00497 cpl_bivector * irplib_wlxcorr_cat_extract(
00498         const cpl_bivector  *   lines_catalog,
00499         double                  wave_min,
00500         double                  wave_max)
00501 {
00502     const int           nlines = cpl_bivector_get_size(lines_catalog);
00503     int                 wave_min_id, wave_max_id ;
00504     cpl_vector       *  sub_cat_wl ;
00505     cpl_vector       *  sub_cat_int ;
00506     const cpl_vector *  xlines  = cpl_bivector_get_x_const(lines_catalog);
00507     const double     *  dxlines = cpl_vector_get_data_const(xlines);
00508 
00509     cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT,    NULL);
00510 
00511     /* Find the 1st line */
00512     wave_min_id = cpl_vector_find(xlines, wave_min);
00513     /* The first line must be greater than (at least?) wave_min */
00514     if (dxlines[wave_min_id] <= wave_min) wave_min_id++;
00515 
00516     /* Find the last line */
00517     wave_max_id = cpl_vector_find(xlines, wave_max);
00518     /* The last line must be less than wave_max */
00519     if (dxlines[wave_max_id] >= wave_min) wave_max_id--;
00520 
00521     /* Checking the wavelength range at this point via the indices also
00522        verifies that they were not found using non-increasing wavelengths */
00523     cpl_ensure(wave_min_id <= wave_max_id, CPL_ERROR_ILLEGAL_INPUT, NULL);
00524 
00525     if (wave_min_id < 0 || wave_max_id == nlines) {
00526         cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00527                                     __FILE__, __LINE__, "The %d-line catalogue "
00528                                     "has no lines in the range %g -> %g",
00529                                     nlines, wave_min, wave_max);
00530         return NULL ;
00531     }
00532 
00533     sub_cat_wl = cpl_vector_extract(xlines, wave_min_id, wave_max_id, 1);
00534     sub_cat_int = cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog), 
00535                                      wave_min_id, wave_max_id, 1);
00536  
00537     return cpl_bivector_wrap_vectors(sub_cat_wl, sub_cat_int);
00538 }
00539 
00540 /*----------------------------------------------------------------------------*/
00557 /*----------------------------------------------------------------------------*/
00558 cpl_vector * irplib_wlxcorr_convolve_create_kernel(double  slitw,
00559                                                    double  fwhm)
00560 {
00561     const double  sigma  = fwhm * CPL_MATH_SIG_FWHM;
00562     const int     size   = 1 + (int)(5.0 * sigma + 0.5*slitw);
00563     cpl_vector  * kernel = cpl_vector_new(size);
00564 
00565 
00566     if (cpl_vector_fill_lss_profile_symmetric(kernel, slitw, fwhm)) {
00567         cpl_vector_delete(kernel);
00568         cpl_ensure(0, cpl_error_get_code(), NULL);
00569     }
00570 
00571     return kernel;
00572 }
00573 
00574 /*----------------------------------------------------------------------------*/
00587 /*----------------------------------------------------------------------------*/
00588 int irplib_wlxcorr_convolve(
00589         cpl_vector          *   smoothed,
00590         const cpl_vector    *   conv_kernel)
00591 {
00592     int             nsamples ;
00593     int             ihwidth ;
00594     cpl_vector  *   raw ;
00595     double      *   psmoothe ;
00596     double      *   praw ;
00597     const double*   psymm ;
00598     int             i, j ;
00599 
00600     /* Test entries */
00601     cpl_ensure(smoothed, CPL_ERROR_NULL_INPUT, -1) ;
00602     cpl_ensure(conv_kernel, CPL_ERROR_NULL_INPUT, -1) ;
00603 
00604     /* Initialise */
00605     nsamples = cpl_vector_get_size(smoothed) ;
00606     ihwidth = cpl_vector_get_size(conv_kernel) - 1 ;
00607     cpl_ensure(ihwidth<nsamples, CPL_ERROR_ILLEGAL_INPUT, -1) ;
00608     psymm = cpl_vector_get_data_const(conv_kernel) ;
00609     psmoothe = cpl_vector_get_data(smoothed) ;
00610     
00611     /* Create raw vector */
00612     raw = cpl_vector_duplicate(smoothed) ;
00613     praw = cpl_vector_get_data(raw) ;
00614 
00615     /* Convolve with the symmetric function */
00616     for (i=0 ; i<ihwidth ; i++) {
00617         psmoothe[i] = praw[i] * psymm[0];
00618         for (j=1 ; j <= ihwidth ; j++) {
00619             const int k = i-j < 0 ? 0 : i-j;
00620             psmoothe[i] += (praw[k]+praw[i+j]) * psymm[j];
00621         }
00622     }
00623 
00624     for (i=ihwidth ; i<nsamples-ihwidth ; i++) {
00625         psmoothe[i] = praw[i] * psymm[0];
00626         for (j=1 ; j<=ihwidth ; j++)
00627             psmoothe[i] += (praw[i-j]+praw[i+j]) * psymm[j];
00628     }
00629     for (i=nsamples-ihwidth ; i<nsamples ; i++) {
00630         psmoothe[i] = praw[i] * psymm[0];
00631         for (j=1 ; j<=ihwidth ; j++) {
00632             const int k = i+j > nsamples-1 ? nsamples - 1 : i+j;
00633             psmoothe[i] += (praw[k]+praw[i-j]) * psymm[j];
00634         }
00635     }
00636     cpl_vector_delete(raw) ;
00637     return 0 ;
00638 }
00639 
00640 /*----------------------------------------------------------------------------*/
00650 /*----------------------------------------------------------------------------*/
00651 int irplib_wlxcorr_plot_solution(
00652         const cpl_polynomial    *   init,
00653         const cpl_polynomial    *   comp,
00654         const cpl_polynomial    *   sol,
00655         int                         pix_start,
00656         int                         pix_stop) 
00657 {
00658     int                 nsamples, nplots ;
00659     cpl_vector      **  vectors ;
00660     cpl_bivector    *   bivector ;
00661     double              diff ;
00662     int                 i ;
00663     
00664     /* Test entries */
00665     if (init == NULL || comp == NULL) return -1 ;
00666     
00667     /* Initialise */
00668     nsamples = pix_stop - pix_start + 1 ;
00669     if (sol != NULL)    nplots = 3 ;
00670     else                nplots = 2 ;
00671     
00672     /* Create vectors */
00673     vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00674     for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00675 
00676     /* First plot with the lambda/pixel relation */
00677     /* Fill vectors */
00678     for (i=0 ; i<nsamples ; i++) {
00679         cpl_vector_set(vectors[0], i, pix_start+i) ;
00680         cpl_vector_set(vectors[1], i, 
00681                 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL)) ;
00682         cpl_vector_set(vectors[2], i, 
00683                 cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL)) ;
00684         if (sol != NULL) 
00685             cpl_vector_set(vectors[3], i, 
00686                     cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL)) ;
00687     }
00688 
00689     /* Plot */
00690     irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';", 
00691         "t '1-Initial / 2-Computed / 3-Solution' w lines", 
00692         "", (const cpl_vector **)vectors, nplots+1);
00693 
00694     /* Free vectors */
00695     for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00696     cpl_free(vectors) ;
00697 
00698     /* Allocate vectors */
00699     nplots -- ;
00700     vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00701     for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00702     
00703     /* Second plot with the delta-lambda/pixel relation */
00704     /* Fill vectors */
00705     for (i=0 ; i<nsamples ; i++) {
00706         cpl_vector_set(vectors[0], i, pix_start+i) ;
00707         diff = cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL) -
00708             cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00709         cpl_vector_set(vectors[1], i, diff) ;
00710         if (sol != NULL) {
00711             diff = cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL) -
00712                 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00713             cpl_vector_set(vectors[2], i, diff) ;
00714         }
00715     }
00716 
00717     /* Plot */
00718     if (sol == NULL) {
00719         bivector = cpl_bivector_wrap_vectors(vectors[0], vectors[1]) ;
00720         irplib_bivector_plot(
00721 "set grid;set xlabel 'Position (pixels)';set ylabel 'Wavelength difference';", 
00722             "t 'Computed-Initial wavelenth' w lines", "", bivector);
00723         cpl_bivector_unwrap_vectors(bivector) ;
00724     } else {
00725         irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';", 
00726             "t '1-Computed - Initial / 2--Solution - Initial' w lines", 
00727             "", (const cpl_vector **)vectors, nplots+1);
00728     }
00729     
00730     /* Free vectors */
00731     for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00732     cpl_free(vectors) ;
00733 
00734     /* Return */
00735     return 0 ;
00736 }
00737 
00738 /*----------------------------------------------------------------------------*/
00745 /*----------------------------------------------------------------------------*/
00746 int irplib_wlxcorr_plot_spc_table(
00747         const cpl_table     *   spc_table, 
00748         const char          *   title) 
00749 {
00750     char                title_loc[1024] ;
00751     cpl_vector      **  vectors ;
00752     cpl_vector      **  sub_vectors ;
00753     cpl_vector      *   tmp_vec ;
00754     int                 nsamples ;
00755     double              hsize_nm, max, mean1, mean3 ;
00756     int                 start_ind, stop_ind, nblines, hsize_pix ;
00757     int                 i, j ;
00758 
00759     /* Test entries */
00760     if (spc_table == NULL) return -1 ;
00761     
00762     /* Initialise */
00763     nsamples = cpl_table_get_nrow(spc_table) ;
00764     hsize_nm = 0.2 ;
00765     hsize_pix = 10 ;
00766     nblines = 0 ;
00767     sprintf(title_loc, 
00768         "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed' w lines",
00769         title) ;
00770     title_loc[1023] = (char)0 ;
00771     
00772     vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00773     vectors[0] = cpl_vector_wrap(nsamples, 
00774             cpl_table_get_data_double((cpl_table*)spc_table,
00775                 IRPLIB_WLXCORR_COL_WAVELENGTH));
00776     vectors[1] = cpl_vector_wrap(nsamples, 
00777             cpl_table_get_data_double((cpl_table*)spc_table, 
00778                 IRPLIB_WLXCORR_COL_CAT_INIT));
00779     vectors[2] = cpl_vector_wrap(nsamples, 
00780             cpl_table_get_data_double((cpl_table*)spc_table, 
00781                 IRPLIB_WLXCORR_COL_CAT_FINAL));
00782     vectors[3] = cpl_vector_wrap(nsamples, 
00783             cpl_table_get_data_double((cpl_table*)spc_table, 
00784                 IRPLIB_WLXCORR_COL_OBS)) ;
00785 
00786     /* Scale the signal for a bettre display */
00787     mean1 = cpl_vector_get_mean(vectors[1]) ;
00788     mean3 = cpl_vector_get_mean(vectors[3]) ;
00789     if (fabs(mean3) > 1)
00790         cpl_vector_multiply_scalar(vectors[3], fabs(mean1/mean3)) ;
00791 
00792     irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00793         "", (const cpl_vector **)vectors, 4);
00794 
00795     /* Unscale the signal */
00796     if (fabs(mean3) > 1)
00797         cpl_vector_multiply_scalar(vectors[3], mean3/mean1) ;
00798 
00799     /* Loop on the brightest lines and zoom on them */
00800     sprintf(title_loc, 
00801 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed (ZOOMED)' w lines",
00802         title) ;
00803     title_loc[1023] = (char)0 ;
00804     tmp_vec = cpl_vector_duplicate(vectors[2]) ;
00805     for (i=0 ; i<nblines ; i++) {
00806         /* Find the brightest line */
00807         if ((max = cpl_vector_get_max(tmp_vec)) <= 0.0) break ;
00808         for (j=0 ; i<nsamples ; j++) {
00809             if (cpl_vector_get(tmp_vec, j) == max) break ;
00810         }
00811         if (j-hsize_pix < 0) start_ind = 0 ;
00812         else start_ind = j-hsize_pix ;
00813         if (j+hsize_pix > nsamples-1) stop_ind = nsamples-1 ;
00814         else stop_ind = j+hsize_pix ;
00815         for (j=start_ind ; j<=stop_ind ; j++) cpl_vector_set(tmp_vec, j, 0.0) ;
00816 
00817         sub_vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00818         sub_vectors[0]=cpl_vector_extract(vectors[0],start_ind,stop_ind,1);
00819         sub_vectors[1]=cpl_vector_extract(vectors[1],start_ind,stop_ind,1);
00820         sub_vectors[2]=cpl_vector_extract(vectors[2],start_ind,stop_ind,1);
00821         sub_vectors[3]=cpl_vector_extract(vectors[3],start_ind,stop_ind,1);
00822 
00823         irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00824             "", (const cpl_vector **)sub_vectors, 4);
00825 
00826         cpl_vector_delete(sub_vectors[0]) ;
00827         cpl_vector_delete(sub_vectors[1]) ;
00828         cpl_vector_delete(sub_vectors[2]) ;
00829         cpl_vector_delete(sub_vectors[3]) ;
00830         cpl_free(sub_vectors) ;
00831     }
00832     cpl_vector_delete(tmp_vec) ;
00833     
00834     cpl_vector_unwrap(vectors[0]) ;
00835     cpl_vector_unwrap(vectors[1]) ;
00836     cpl_vector_unwrap(vectors[2]) ;
00837     cpl_vector_unwrap(vectors[3]) ;
00838     cpl_free(vectors) ;
00839 
00840     return 0 ;
00841 }
00842 
00843 /*----------------------------------------------------------------------------*/
00851 /*----------------------------------------------------------------------------*/
00852 int irplib_wlxcorr_catalog_plot(
00853         const cpl_bivector      *   cat,
00854         double                      wmin,
00855         double                      wmax) 
00856 {
00857     int                 start, stop ;
00858     cpl_bivector    *   subcat ;
00859     cpl_vector      *   subcat_x ;
00860     cpl_vector      *   subcat_y ;
00861     const double    *   pwave ;
00862     int                 nvals, nvals_tot ;
00863     int                 i ;
00864 
00865     /* Test entries */
00866     if (cat == NULL) return -1 ;
00867     if (wmax <= wmin) return -1 ;
00868 
00869     /* Initialise */
00870     nvals_tot = cpl_bivector_get_size(cat) ;
00871 
00872     /* Count the nb of values */
00873     pwave = cpl_bivector_get_x_data_const(cat) ;
00874     if (pwave[0] >= wmin) start = 0 ;
00875     else start = -1 ;
00876     if (pwave[nvals_tot-1] <= wmax) stop = nvals_tot-1 ;
00877     else stop = -1 ;
00878     i=0 ;
00879     while ((pwave[i] < wmin) && (i<nvals_tot-1)) i++ ;
00880     start = i ;
00881     i= nvals_tot-1 ;
00882     while ((pwave[i] > wmax) && (i>0)) i-- ;
00883     stop = i ;
00884 
00885     if (start>=stop) {
00886         cpl_msg_error(cpl_func, "Cannot plot the catalog") ;
00887         return -1 ;
00888     }
00889     nvals = start - stop + 1 ;
00890 
00891     /* Create the bivector to plot */
00892     subcat_x = cpl_vector_extract(cpl_bivector_get_x_const(cat),start,stop, 1) ;
00893     subcat_y = cpl_vector_extract(cpl_bivector_get_y_const(cat),start,stop, 1) ;
00894     subcat = cpl_bivector_wrap_vectors(subcat_x, subcat_y) ;
00895 
00896     /* Plot */
00897     if (nvals > 500) {
00898         irplib_bivector_plot(
00899                 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00900                 "t 'Catalog Spectrum' w lines", "", subcat);
00901     } else {
00902         irplib_bivector_plot(
00903                 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00904                 "t 'Catalog Spectrum' w impulses", "", subcat);
00905     }
00906     cpl_bivector_unwrap_vectors(subcat) ;
00907     cpl_vector_delete(subcat_x) ;
00908     cpl_vector_delete(subcat_y) ;
00909 
00910     return 0 ;
00911 }
00912    
00915 /*----------------------------------------------------------------------------*/
00930 /*----------------------------------------------------------------------------*/
00931 static void irplib_wlxcorr_estimate(cpl_vector           * vxc,
00932                                     cpl_vector           * model,
00933                                     const cpl_vector     * spectrum,
00934                                     const cpl_bivector   * lines_catalog,
00935                                     const cpl_vector     * conv_kernel,
00936                                     const cpl_polynomial * poly_candi,
00937                                     double                 slitw,
00938                                     double                 fwhm)
00939 {
00940     cpl_errorstate prestate = cpl_errorstate_get();
00941     const int hsize = cpl_vector_get_size(vxc) / 2;
00942 
00943     if (conv_kernel != NULL) {
00944         irplib_wlcalib_fill_spectrum(model, lines_catalog, conv_kernel,
00945                                   poly_candi, hsize);
00946     } else {
00947         const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00948 
00949         irplib_vector_fill_line_spectrum_model(model, NULL, poly_candi,
00950                                                lines_catalog, slitw, fwhm,
00951                                                xtrunc, 0);
00952     }
00953 
00954     if (cpl_errorstate_is_equal(prestate))
00955         cpl_vector_correlate(vxc, model, spectrum);
00956 
00957     if (!cpl_errorstate_is_equal(prestate)) {
00958         cpl_vector_fill(vxc, 0.0);
00959 
00960         /* cpl_errorstate_dump(prestate, CPL_FALSE, NULL); */
00961         cpl_errorstate_set(prestate);
00962 
00963     }
00964 
00965     return;
00966 }
00967 
00968 
00969 /*----------------------------------------------------------------------------*/
00979 /*----------------------------------------------------------------------------*/
00980 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector * wavelengths,
00981                                         const cpl_polynomial * disp1d,
00982                                         int spec_sz,
00983                                         double tol)
00984 {
00985     const int nlines = cpl_vector_get_size(wavelengths);
00986     /* The dispersion on the detector center */
00987 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00988     const double dispersion = cpl_polynomial_eval_1d_diff(disp1d,
00989                                                           0.5 * spec_sz + 1.0,
00990                                                           0.5 * spec_sz,
00991                                                           NULL);
00992 #else
00993     const double dispersion
00994         =  cpl_polynomial_eval_1d(disp1d, 0.5 * spec_sz + 1.0, NULL)
00995         -  cpl_polynomial_eval_1d(disp1d, 0.5 * spec_sz      , NULL);
00996 #endif
00997     const double range = cpl_vector_get(wavelengths, nlines-1)
00998         - cpl_vector_get(wavelengths, 0);
00999 
01000     cpl_ensure(wavelengths != NULL, CPL_ERROR_NULL_INPUT,    CPL_FALSE);
01001     cpl_ensure(disp1d      != NULL, CPL_ERROR_NULL_INPUT,    CPL_FALSE);
01002     cpl_ensure(cpl_polynomial_get_dimension(disp1d) == 1,
01003                CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01004     cpl_ensure(range > 0.0,      CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01005 
01006     return nlines * fabs(dispersion) <= tol * fabs(range) ? CPL_TRUE
01007         : CPL_FALSE;
01008 
01009 }
01010 
01011 /*----------------------------------------------------------------------------*/
01026 /*----------------------------------------------------------------------------*/
01027 static
01028 cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector           * self,
01029                                          const cpl_bivector   * lines_catalog,
01030                                          const cpl_vector     * conv_kernel,
01031                                          const cpl_polynomial * poly,
01032                                          int                    search_hs)
01033 {
01034 
01035 
01036     const int          size = cpl_vector_get_size(self);
01037     const int          nlines = cpl_bivector_get_size(lines_catalog);
01038     const cpl_vector * xlines  = cpl_bivector_get_x_const(lines_catalog);
01039     const double     * dxlines = cpl_vector_get_data_const(xlines);
01040     cpl_bivector     * sub_cat ;
01041     cpl_vector       * sub_cat_x;
01042     cpl_vector       * sub_cat_y;
01043     cpl_vector       * wl_limits;
01044     double             wave_min, wave_max;
01045     int                wave_min_id, wave_max_id;
01046     int                nsub;
01047     int                error;
01048 
01049     cpl_ensure_code(self          != NULL, CPL_ERROR_NULL_INPUT);
01050     cpl_ensure_code(lines_catalog != NULL, CPL_ERROR_NULL_INPUT);
01051     cpl_ensure_code(conv_kernel   != NULL, CPL_ERROR_NULL_INPUT);
01052     cpl_ensure_code(poly          != NULL, CPL_ERROR_NULL_INPUT);
01053     cpl_ensure_code(size > 0,              CPL_ERROR_ILLEGAL_INPUT);
01054 
01055 
01056     /* Resample the spectrum */
01057     wl_limits = cpl_vector_new(size + 1);
01058     cpl_vector_fill_polynomial(wl_limits, poly, 0.5 - search_hs, 1);
01059 
01060     /* The spectrum wavelength bounds */
01061     wave_min = cpl_vector_get(wl_limits, 0);
01062     wave_max = cpl_vector_get(wl_limits, size);
01063 
01064     /* Find the 1st line */
01065     wave_min_id = cpl_vector_find(xlines, wave_min);
01066     /* The first line must be less than or equal to wave_min */
01067     if (dxlines[wave_min_id] > wave_min) wave_min_id--;
01068 
01069     if (wave_min_id < 0) {
01070         cpl_vector_delete(wl_limits);
01071         return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01072                                            __FILE__, __LINE__, "The %d-line "
01073                                            "catalogue only has lines above %g",
01074                                            nlines, wave_min);
01075     }
01076 
01077     /* Find the last line */
01078     wave_max_id = cpl_vector_find(xlines, wave_max);
01079     /* The last line must be greater than or equal to wave_max */
01080     if (dxlines[wave_max_id] < wave_max) wave_max_id++;
01081 
01082     if (wave_max_id == nlines) {
01083         cpl_vector_delete(wl_limits);
01084         return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01085                                            __FILE__, __LINE__, "The %d-line "
01086                                            "catalogue only has lines below %g",
01087                                            nlines, wave_max);
01088     }
01089 
01090     /* Checking the wavelength range at this point via the indices also
01091        verifies that they were not found using non-increasing wavelengths */
01092     nsub = 1 + wave_max_id - wave_min_id;
01093     cpl_ensure_code(nsub > 1, CPL_ERROR_ILLEGAL_INPUT);
01094 
01095     /* Wrap a new bivector around the relevant part of the catalog */
01096     /* The data is _not_ modified */
01097     sub_cat_x = cpl_vector_wrap(nsub, wave_min_id + (double*)dxlines);
01098     sub_cat_y = cpl_vector_wrap(nsub, wave_min_id + (double*)
01099                                 cpl_bivector_get_y_data_const(lines_catalog));
01100     sub_cat = cpl_bivector_wrap_vectors(sub_cat_x, sub_cat_y);
01101 
01102     /* High resolution catalog */
01103     error = irplib_wlxcorr_signal_resample(self, wl_limits, sub_cat);
01104 
01105     cpl_vector_delete(wl_limits);
01106     cpl_bivector_unwrap_vectors(sub_cat);
01107     (void)cpl_vector_unwrap(sub_cat_x);
01108     (void)cpl_vector_unwrap(sub_cat_y);
01109 
01110     cpl_ensure_code(!error, CPL_ERROR_ILLEGAL_INPUT);
01111 
01112     /* Smooth the instrument resolution */
01113     cpl_ensure_code(!irplib_wlxcorr_convolve(self, conv_kernel),
01114                     cpl_error_get_code());
01115 
01116     return CPL_ERROR_NONE;
01117 }
01118 
01119 
01120 /*----------------------------------------------------------------------------*/
01130 /*----------------------------------------------------------------------------*/
01131 static int irplib_wlxcorr_signal_resample(
01132         cpl_vector          *   resampled, 
01133         const cpl_vector    *   xbounds,
01134         const cpl_bivector  *   hires)
01135 {
01136     const int           hrsize = cpl_bivector_get_size(hires);
01137     const cpl_vector*   xhires ;
01138     const cpl_vector*   yhires ;
01139     const double    *   pxhires ;
01140     const double    *   pyhires ;
01141     const double    *   pxbounds ;
01142     cpl_vector      *   ybounds ;
01143     cpl_bivector    *   boundary ;
01144     double          *   pybounds ;
01145     double          *   presampled ;
01146     int                 nsamples ;
01147     int                 i, itt ;
01148    
01149     /* Test entries */
01150     if ((!resampled) || (!xbounds) || (!hires)) return -1 ;
01151 
01152     /* Initialise */
01153     nsamples = cpl_vector_get_size(resampled) ;
01154 
01155     /* Initialise */
01156     presampled = cpl_vector_get_data(resampled) ;
01157     pxbounds = cpl_vector_get_data_const(xbounds) ;
01158     xhires = cpl_bivector_get_x_const(hires) ;
01159     yhires = cpl_bivector_get_y_const(hires) ;
01160     pxhires = cpl_vector_get_data_const(xhires) ;
01161     pyhires = cpl_vector_get_data_const(yhires) ;
01162     
01163     /* Create a new vector */
01164     ybounds = cpl_vector_new(cpl_vector_get_size(xbounds)) ;
01165     boundary = cpl_bivector_wrap_vectors((cpl_vector*)xbounds,ybounds) ;
01166     pybounds = cpl_vector_get_data(ybounds) ;
01167 
01168     /* Test entries */
01169     if (cpl_bivector_get_size(boundary) != nsamples + 1) {
01170         cpl_bivector_unwrap_vectors(boundary) ;
01171         cpl_vector_delete(ybounds) ;
01172         return -1 ;
01173     }
01174 
01175     /* Get the ind  */
01176     itt = cpl_vector_find(xhires, pxbounds[0]);
01177 
01178     /* Interpolate the signal */
01179     if (cpl_bivector_interpolate_linear(boundary, hires)) {
01180         cpl_bivector_unwrap_vectors(boundary) ;
01181         cpl_vector_delete(ybounds) ;
01182         return -1 ;
01183     }
01184 
01185     /* At this point itt most likely points to element just below
01186        pxbounds[0] */
01187     while (pxhires[itt] < pxbounds[0]) itt++;
01188 
01189     for (i=0; i < nsamples; i++) {
01190         /* The i'th signal is the weighted average of the two interpolated
01191            signals at the pixel boundaries and those table signals in
01192            between */
01193 
01194         double xlow  = pxbounds[i];
01195         double x     = pxhires[itt];
01196 
01197         if (x > pxbounds[i+1]) x = pxbounds[i+1];
01198         /* Contribution from interpolated value at wavelength at lower pixel
01199            boundary */
01200         presampled[i] = pybounds[i] * (x - xlow);
01201 
01202         /* Contribution from table values in between pixel boundaries */
01203         while ((pxhires[itt] < pxbounds[i+1]) && (itt < hrsize)) {
01204             const double xprev = x;
01205             x = pxhires[itt+1];
01206             if (x > pxbounds[i+1]) x = pxbounds[i+1];
01207             presampled[i] += pyhires[itt] * (x - xlow);
01208             xlow = xprev;
01209             itt++;
01210         }
01211 
01212         /* Contribution from interpolated value at wavelength at upper pixel
01213            boundary */
01214         presampled[i] += pybounds[i+1] * (pxbounds[i+1] - xlow);
01215 
01216         /* Compute average by dividing integral by length of pixel range
01217            (the factor 2 comes from the contributions) */
01218         presampled[i] /= 2 * (pxbounds[i+1] - pxbounds[i]);
01219     }
01220     cpl_bivector_unwrap_vectors(boundary) ;
01221     cpl_vector_delete(ybounds) ;
01222     return 0 ;
01223 }
01224 
01225 
01226 
01227 /*----------------------------------------------------------------------------*/
01248 /*----------------------------------------------------------------------------*/
01249 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector * self,
01250                                                             double  slitw,
01251                                                             double  fwhm)
01252 {
01253 
01254     const double sigma = fwhm * CPL_MATH_SIG_FWHM;
01255     const int    n     = cpl_vector_get_size(self);
01256     int          i;
01257 
01258 
01259     cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01260     cpl_ensure_code(slitw > 0.0,  CPL_ERROR_ILLEGAL_INPUT);
01261     cpl_ensure_code(fwhm  > 0.0,  CPL_ERROR_ILLEGAL_INPUT);
01262 
01263     /* Cannot fail now */
01264 
01265     /* Special case for i = 0 */
01266     (void)cpl_vector_set(self, 0,
01267                          (irplib_erf_antideriv(0.5*slitw + 0.5, sigma) -
01268                           irplib_erf_antideriv(0.5*slitw - 0.5, sigma)) / slitw);
01269 
01270     for (i = 1; i < n; i++) {
01271         /* FIXME: Reuse two irplib_erf_antideriv() calls from previous value */
01272         const double x1p = i + 0.5*slitw + 0.5;
01273         const double x1n = i - 0.5*slitw + 0.5;
01274         const double x0p = i + 0.5*slitw - 0.5;
01275         const double x0n = i - 0.5*slitw - 0.5;
01276         const double val = 0.5/slitw *
01277             (irplib_erf_antideriv(x1p, sigma) - irplib_erf_antideriv(x1n, sigma) -
01278              irplib_erf_antideriv(x0p, sigma) + irplib_erf_antideriv(x0n, sigma));
01279         (void)cpl_vector_set(self, i, val);
01280     }
01281 
01282     return CPL_ERROR_NONE;
01283 }

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