irplib_wlxcorr.c

00001 /* $Id: irplib_wlxcorr.c,v 1.34 2007/05/10 08:58:05 yjung 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: yjung $
00023  * $Date: 2007/05/10 08:58:05 $
00024  * $Revision: 1.34 $
00025  * $Name: uves-3_3_1 $
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 <cpl.h>
00038 
00039 #include "irplib_wlxcorr.h"
00040 #include "irplib_plot.h"
00041 
00042 /*----------------------------------------------------------------------------*/
00047 /*----------------------------------------------------------------------------*/
00048 
00049 static cpl_bivector * irplib_wlxcorr_gen_signal(const cpl_bivector *, double, 
00050         double, const cpl_polynomial *, int, int, int *) ;
00051 static int irplib_wlxcorr_signal_resample(cpl_vector *, const cpl_vector *, 
00052         const cpl_bivector *) ;
00053 
00056 /*----------------------------------------------------------------------------*/
00076 /*----------------------------------------------------------------------------*/
00077 cpl_polynomial * irplib_wlxcorr_best_poly(
00078         const cpl_vector        *   spectrum,
00079         const cpl_bivector      *   lines_catalog,
00080         int                         degree,
00081         const cpl_polynomial    *   guess_poly,
00082         const cpl_vector        *   wl_error,
00083         int                         nsamples,
00084         double                      slitw,
00085         double                      fwhm,
00086         double                  *   xc,
00087         cpl_table               **  wlres,
00088         cpl_vector              **  xcorrs)
00089 {
00090     int                 ntests ;
00091     int                 spec_sz ;
00092     cpl_polynomial  **  candidates ;
00093     double              xpos, wl_pos ;
00094     cpl_vector      *   init_pts_wl ;
00095     cpl_vector      *   init_pts_x ;
00096     cpl_vector      *   pts_wl ;
00097     cpl_vector      *   vxcorrs ;
00098     int                 best_ind ;
00099     cpl_polynomial  *   poly_sol ;
00100     cpl_table       *   spc_table ;
00101     double              xc_cur ;
00102     cpl_vector      *   vxc ;
00103     cpl_bivector    *   gen_init ;
00104     double          *   pwl_error ; 
00105     int                 i, j, k, l ;
00106 
00107     /* Test entries */
00108     if (!spectrum || !lines_catalog || !guess_poly || !xc || !wl_error) 
00109         return NULL;
00110     if (degree < 1 || degree > 3) return NULL ;
00111     if (cpl_vector_get_size(wl_error) != degree+1) return NULL ;
00112 
00113     /* Initialise */
00114     ntests = (int)pow(nsamples, (degree + 1)) ;
00115     spec_sz = cpl_vector_get_size(spectrum) ;
00116     pwl_error = cpl_vector_get_data(wl_error) ;
00117     if (wlres != NULL) *wlres = NULL ;
00118     if (xcorrs != NULL) *xcorrs = NULL ;
00119    
00120     /* Create initial test points */
00121     init_pts_x = cpl_vector_new(degree + 1) ;
00122     init_pts_wl = cpl_vector_new(degree + 1) ;
00123     for (i=0 ; i<degree + 1 ; i++) {
00124         xpos = i*spec_sz/degree ;
00125         cpl_vector_set(init_pts_x, i, xpos) ;
00126         cpl_vector_set(init_pts_wl, i, 
00127                 cpl_polynomial_eval_1d(guess_poly, xpos, NULL)) ;
00128     }
00129     
00130     /* Create the polynomial candidates */
00131     candidates = cpl_malloc(ntests * sizeof(cpl_polynomial*)) ;
00132     pts_wl = cpl_vector_new(degree + 1) ;
00133     for (i=0 ; i<nsamples ; i++) {
00134         wl_pos = cpl_vector_get(init_pts_wl, 0) 
00135             - pwl_error[0]/2 + i*pwl_error[0]/nsamples ;
00136         cpl_vector_set(pts_wl, 0, wl_pos) ;
00137         for (j=0 ; j<nsamples ; j++) {
00138             wl_pos = cpl_vector_get(init_pts_wl, 1)
00139                 - pwl_error[1]/2 + j*pwl_error[1]/nsamples ;
00140             cpl_vector_set(pts_wl, 1, wl_pos) ;
00141             if (degree == 1) {
00142                 candidates[j+i*nsamples] = 
00143                     cpl_polynomial_fit_1d_create(init_pts_x, pts_wl, degree, 
00144                             NULL);
00145             } else {
00146                 for (k=0 ; k<nsamples ; k++) {
00147                     wl_pos = cpl_vector_get(init_pts_wl, 2)
00148                         - pwl_error[2]/2 + k*pwl_error[2]/nsamples ;
00149                     cpl_vector_set(pts_wl, 2, wl_pos) ;
00150                     if (degree == 2) {
00151                         candidates[k+(j+i*nsamples)*nsamples] = 
00152                             cpl_polynomial_fit_1d_create(init_pts_x, 
00153                                     pts_wl, degree, NULL);
00154                     } else {
00155                         for (l=0 ; l<nsamples ; l++) {
00156                             wl_pos = cpl_vector_get(init_pts_wl, 3) 
00157                                 - pwl_error[3]/2 + l*pwl_error[3]/nsamples ;
00158                             cpl_vector_set(pts_wl, 3, wl_pos) ;
00159                             if (degree == 3) {
00160                             candidates[l+(k+(j+i*nsamples)*nsamples)*nsamples]=
00161                                     cpl_polynomial_fit_1d_create(init_pts_x, 
00162                                             pts_wl, degree, NULL);
00163                             } else {
00164                                 /* Should never come here */
00165                             }
00166                         }
00167                     }
00168                 }
00169             }
00170         }
00171     }
00172     cpl_vector_delete(pts_wl) ;
00173     cpl_vector_delete(init_pts_x) ;
00174     cpl_vector_delete(init_pts_wl) ;
00175     
00176     /* Loop on the polynomial and select the best */
00177     best_ind = 0 ;
00178     *xc = -1 ;
00179     vxc = cpl_vector_new(1) ;
00180     vxcorrs = cpl_vector_new(ntests) ;
00181     for (i=0 ; i<ntests ; i++) {
00182         /* Get the emission at those wavelengths */
00183         if ((gen_init=irplib_wlxcorr_gen_signal(lines_catalog, slitw, fwhm, 
00184                 candidates[i], spec_sz, 0, NULL)) != NULL) {
00185             /* Apply the correlation */
00186             cpl_vector_correlate(vxc, cpl_bivector_get_y(gen_init),spectrum);
00187             cpl_bivector_delete(gen_init);
00188             xc_cur = cpl_vector_get(vxc, 0);
00189             if (xc_cur > *xc) {
00190                 *xc = xc_cur ;
00191                 best_ind = i ;
00192             }
00193             cpl_vector_set(vxcorrs, i, xc_cur) ;
00194         } else {
00195             cpl_msg_error(cpl_func, "Cannot generate the signal - abort") ;
00196             cpl_vector_delete(vxcorrs) ;
00197             cpl_vector_delete(vxc) ;
00198             for (i=0 ; i<ntests ; i++) {
00199                 cpl_polynomial_delete(candidates[i]) ;
00200             }
00201             cpl_free(candidates) ;
00202             return NULL ;
00203         }
00204     }
00205     cpl_vector_delete(vxc) ;
00206 
00207     /* Get the best polynomial */
00208     poly_sol = cpl_polynomial_duplicate(candidates[best_ind]) ;
00209        
00210     for (i=0 ; i<ntests ; i++) {
00211         cpl_polynomial_delete(candidates[i]) ;
00212     }
00213     cpl_free(candidates) ;
00214 
00215     /* Create the spc_table  */
00216     if ((spc_table = irplib_wlxcorr_gen_spc_table(spectrum, lines_catalog, 
00217                     slitw, fwhm, guess_poly, poly_sol)) == NULL) {
00218         cpl_msg_error(cpl_func, "Cannot generate infos table") ;
00219         cpl_polynomial_delete(poly_sol) ;
00220         cpl_vector_delete(vxcorrs) ;
00221         return NULL ;
00222     } 
00223    
00224     /* Return */
00225     if (wlres != NULL) *wlres = spc_table ;
00226     else cpl_table_delete(spc_table) ;
00227     
00228     if (xcorrs != NULL) *xcorrs = vxcorrs ;
00229     else cpl_vector_delete(vxcorrs) ;
00230 
00231     return poly_sol ;
00232 }
00233 
00234 /*----------------------------------------------------------------------------*/
00247 /*----------------------------------------------------------------------------*/
00248 cpl_table * irplib_wlxcorr_gen_spc_table(
00249         const cpl_vector        *   spectrum,
00250         const cpl_bivector      *   lines_catalog,
00251         double                      slitw,
00252         double                      fwhm,
00253         const cpl_polynomial    *   guess_poly,
00254         const cpl_polynomial    *   corr_poly)
00255 {
00256     cpl_bivector    *   gen_init ;
00257     cpl_bivector    *   gen_corr ;
00258     int                 nsamples ;
00259     cpl_table       *   spc_table ;
00260     double          *   pgen ;
00261 
00262     /* Test inputs */
00263     if (spectrum == NULL) return NULL ;
00264     if (lines_catalog == NULL) return NULL ;
00265     if (guess_poly == NULL) return NULL ;
00266     if (corr_poly == NULL) return NULL ;
00267 
00268     /* Initialise */
00269     nsamples = cpl_vector_get_size(spectrum) ;
00270     
00271     /* Get the emission at initial wavelengths */
00272     if ((gen_init=irplib_wlxcorr_gen_signal(lines_catalog, slitw, fwhm,
00273                     guess_poly, nsamples, 0, NULL)) == NULL) {
00274         cpl_msg_error(cpl_func, "Cannot get the emission spectrum") ;
00275         return NULL ;
00276     }
00277  
00278     /* Get the emission at corrected wavelengths */
00279     if ((gen_corr=irplib_wlxcorr_gen_signal(lines_catalog, slitw, fwhm,
00280                     corr_poly, nsamples, 0, NULL)) == NULL) {
00281         cpl_msg_error(cpl_func, "Cannot get the emission spectrum") ;
00282         cpl_bivector_delete(gen_init) ;
00283         return NULL ;
00284     }
00285 
00286     /* Create the ouput table */
00287     spc_table = cpl_table_new(nsamples);
00288     cpl_table_new_column(spc_table, IRPLIB_COL_XC_WAVELENGTH, CPL_TYPE_DOUBLE);
00289     cpl_table_new_column(spc_table, IRPLIB_COL_XC_CAT_INIT, CPL_TYPE_DOUBLE);
00290     cpl_table_new_column(spc_table, IRPLIB_COL_XC_CAT_FINAL, CPL_TYPE_DOUBLE);
00291     cpl_table_new_column(spc_table, IRPLIB_COL_XC_OBS, CPL_TYPE_DOUBLE);
00292     
00293     /* Update table */
00294     pgen = cpl_bivector_get_x_data(gen_corr) ;
00295     cpl_table_copy_data_double(spc_table, IRPLIB_COL_XC_WAVELENGTH, pgen) ;
00296     pgen = cpl_bivector_get_y_data(gen_corr) ;
00297     cpl_table_copy_data_double(spc_table, IRPLIB_COL_XC_CAT_FINAL, pgen) ;
00298     pgen = cpl_vector_get_data(spectrum) ;
00299     cpl_table_copy_data_double(spc_table, IRPLIB_COL_XC_OBS, pgen) ;
00300     pgen = cpl_bivector_get_y_data(gen_init) ;
00301     cpl_table_copy_data_double(spc_table, IRPLIB_COL_XC_CAT_INIT, pgen);
00302     cpl_bivector_delete(gen_init);
00303     cpl_bivector_delete(gen_corr);
00304 
00305     return spc_table ;
00306 }
00307 
00308 /*----------------------------------------------------------------------------*/
00316 /*----------------------------------------------------------------------------*/
00317 cpl_bivector * irplib_wlxcorr_cat_extract(
00318         const cpl_bivector  *   lines_catalog,
00319         double                  wave_min,
00320         double                  wave_max)
00321 {
00322     int                 wave_min_id, wave_max_id ;
00323     double              wave_cur ;
00324     cpl_vector      *   sub_cat_wl ;
00325     cpl_vector      *   sub_cat_int ;
00326     cpl_bivector    *   sub_cat ;
00327     int                 i ;
00328 
00329     wave_min_id = wave_max_id = -1 ;
00330     for (i=0 ; i<cpl_bivector_get_size(lines_catalog) ; i++) {
00331         wave_cur = cpl_vector_get(cpl_bivector_get_x(lines_catalog), i) ;
00332         if ((wave_min_id<0) && (wave_cur>wave_min)) wave_min_id = i ; 
00333         if (wave_cur<wave_max) wave_max_id = i ;
00334     } 
00335     if (wave_min_id<0 || wave_max_id<0) {
00336         cpl_msg_error(cpl_func, "Cannot extract from the catalog spectrum") ;
00337         return NULL ;
00338     }
00339     if (wave_min_id >= wave_max_id) return NULL ;
00340     sub_cat_wl = cpl_vector_extract(cpl_bivector_get_x(lines_catalog), 
00341             wave_min_id, wave_max_id, 1) ;
00342     sub_cat_int = cpl_vector_extract(cpl_bivector_get_y(lines_catalog), 
00343             wave_min_id, wave_max_id, 1) ;
00344     sub_cat = cpl_bivector_wrap_vectors(sub_cat_wl, sub_cat_int) ;
00345  
00346     return sub_cat ;
00347 }
00348 
00349 /*----------------------------------------------------------------------------*/
00359 /*----------------------------------------------------------------------------*/
00360 int irplib_wlxcorr_plot_solution(
00361         const cpl_polynomial    *   init,
00362         const cpl_polynomial    *   comp,
00363         const cpl_polynomial    *   sol,
00364         int                         pix_start,
00365         int                         pix_stop) 
00366 {
00367     int                 nsamples, nplots ;
00368     cpl_vector      **  vectors ;
00369     cpl_bivector    *   bivector ;
00370     double              diff ;
00371     int                 i ;
00372     
00373     /* Test entries */
00374     if (init == NULL || comp == NULL) return -1 ;
00375     
00376     /* Initialise */
00377     nsamples = pix_stop - pix_start + 1 ;
00378     if (sol != NULL)    nplots = 3 ;
00379     else                nplots = 2 ;
00380     
00381     /* Create vectors */
00382     vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00383     for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00384 
00385     /* First plot with the lambda/pixel relation */
00386     /* Fill vectors */
00387     for (i=0 ; i<nsamples ; i++) {
00388         cpl_vector_set(vectors[0], i, pix_start+i) ;
00389         cpl_vector_set(vectors[1], i, 
00390                 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL)) ;
00391         cpl_vector_set(vectors[2], i, 
00392                 cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL)) ;
00393         if (sol != NULL) 
00394             cpl_vector_set(vectors[3], i, 
00395                     cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL)) ;
00396     }
00397 
00398     /* Plot */
00399     irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';", 
00400         "t '1-Initial / 2-Computed / 3-Solution' w lines", 
00401         "", (const cpl_vector **)vectors, nplots+1);
00402 
00403     /* Free vectors */
00404     for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00405     cpl_free(vectors) ;
00406 
00407     /* Allocate vectors */
00408     nplots -- ;
00409     vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00410     for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00411     
00412     /* Second plot with the delta-lambda/pixel relation */
00413     /* Fill vectors */
00414     for (i=0 ; i<nsamples ; i++) {
00415         cpl_vector_set(vectors[0], i, pix_start+i) ;
00416         diff = cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL) -
00417             cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00418         cpl_vector_set(vectors[1], i, diff) ;
00419         if (sol != NULL) {
00420             diff = cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL) -
00421                 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00422             cpl_vector_set(vectors[2], i, diff) ;
00423         }
00424     }
00425 
00426     /* Plot */
00427     if (sol == NULL) {
00428         bivector = cpl_bivector_wrap_vectors(vectors[0], vectors[1]) ;
00429         irplib_bivector_plot(
00430 "set grid;set xlabel 'Position (pixels)';set ylabel 'Wavelength difference';", 
00431             "t 'Computed-Initial wavelenth' w lines", "", bivector);
00432         cpl_bivector_unwrap_vectors(bivector) ;
00433     } else {
00434         irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';", 
00435             "t '1-Computed - Initial / 2--Solution - Initial' w lines", 
00436             "", (const cpl_vector **)vectors, nplots+1);
00437     }
00438     
00439     /* Free vectors */
00440     for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00441     cpl_free(vectors) ;
00442 
00443     /* Return */
00444     return 0 ;
00445 }
00446 
00447 /*----------------------------------------------------------------------------*/
00454 /*----------------------------------------------------------------------------*/
00455 int irplib_wlxcorr_plot_spc_table(
00456         const cpl_table     *   spc_table, 
00457         const char          *   title) 
00458 {
00459     char                title_loc[1024] ;
00460     cpl_vector      **  vectors ;
00461     cpl_vector      **  sub_vectors ;
00462     cpl_vector      *   tmp_vec ;
00463     int                 nsamples ;
00464     double              hsize_nm, max, mean1, mean3 ;
00465     int                 start_ind, stop_ind, nblines, hsize_pix ;
00466     int                 i, j ;
00467 
00468     /* Test entries */
00469     if (spc_table == NULL) return -1 ;
00470     
00471     /* Initialise */
00472     nsamples = cpl_table_get_nrow(spc_table) ;
00473     hsize_nm = 0.2 ;
00474     hsize_pix = 10 ;
00475     nblines = 0 ;
00476     sprintf(title_loc, 
00477         "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed' w lines",
00478         title) ;
00479     title_loc[1023] = (char)0 ;
00480     
00481     vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00482     vectors[0] = cpl_vector_wrap(nsamples, 
00483             cpl_table_get_data_double(spc_table, IRPLIB_COL_XC_WAVELENGTH)) ;
00484     vectors[1] = cpl_vector_wrap(nsamples, 
00485             cpl_table_get_data_double(spc_table, IRPLIB_COL_XC_CAT_INIT)) ;
00486     vectors[2] = cpl_vector_wrap(nsamples, 
00487             cpl_table_get_data_double(spc_table, IRPLIB_COL_XC_CAT_FINAL)) ;
00488     vectors[3] = cpl_vector_wrap(nsamples, 
00489             cpl_table_get_data_double(spc_table, IRPLIB_COL_XC_OBS)) ;
00490 
00491     /* Scale the signal for a bettre display */
00492     mean1 = cpl_vector_get_mean(vectors[1]) ;
00493     mean3 = cpl_vector_get_mean(vectors[3]) ;
00494     if (fabs(mean3) > 1)
00495         cpl_vector_multiply_scalar(vectors[3], fabs(mean1/mean3)) ;
00496 
00497     irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00498         "", (const cpl_vector **)vectors, 4);
00499 
00500     /* Unscale the signal */
00501     if (fabs(mean3) > 1)
00502         cpl_vector_multiply_scalar(vectors[3], mean3/mean1) ;
00503 
00504     /* Loop on the brightest lines and zoom on them */
00505     sprintf(title_loc, 
00506 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed (ZOOMED)' w lines",
00507         title) ;
00508     title_loc[1023] = (char)0 ;
00509     tmp_vec = cpl_vector_duplicate(vectors[2]) ;
00510     for (i=0 ; i<nblines ; i++) {
00511         /* Find the brightest line */
00512         if ((max = cpl_vector_get_max(tmp_vec)) <= 0.0) break ;
00513         for (j=0 ; i<nsamples ; j++) {
00514             if (cpl_vector_get(tmp_vec, j) == max) break ;
00515         }
00516         if (j-hsize_pix < 0) start_ind = 0 ;
00517         else start_ind = j-hsize_pix ;
00518         if (j+hsize_pix > nsamples-1) stop_ind = nsamples-1 ;
00519         else stop_ind = j+hsize_pix ;
00520         for (j=start_ind ; j<=stop_ind ; j++) cpl_vector_set(tmp_vec, j, 0.0) ;
00521 
00522         sub_vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00523         sub_vectors[0]=cpl_vector_extract(vectors[0],start_ind,stop_ind,1);
00524         sub_vectors[1]=cpl_vector_extract(vectors[1],start_ind,stop_ind,1);
00525         sub_vectors[2]=cpl_vector_extract(vectors[2],start_ind,stop_ind,1);
00526         sub_vectors[3]=cpl_vector_extract(vectors[3],start_ind,stop_ind,1);
00527 
00528         irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00529             "", (const cpl_vector **)sub_vectors, 4);
00530 
00531         cpl_vector_delete(sub_vectors[0]) ;
00532         cpl_vector_delete(sub_vectors[1]) ;
00533         cpl_vector_delete(sub_vectors[2]) ;
00534         cpl_vector_delete(sub_vectors[3]) ;
00535         cpl_free(sub_vectors) ;
00536     }
00537     cpl_vector_delete(tmp_vec) ;
00538     
00539     cpl_vector_unwrap(vectors[0]) ;
00540     cpl_vector_unwrap(vectors[1]) ;
00541     cpl_vector_unwrap(vectors[2]) ;
00542     cpl_vector_unwrap(vectors[3]) ;
00543     cpl_free(vectors) ;
00544 
00545     return 0 ;
00546 }
00547 
00548 /*----------------------------------------------------------------------------*/
00556 /*----------------------------------------------------------------------------*/
00557 int irplib_wlxcorr_catalog_plot(
00558         const cpl_bivector      *   cat,
00559         double                      wmin,
00560         double                      wmax) 
00561 {
00562     int                 start, stop ;
00563     cpl_bivector    *   subcat ;
00564     cpl_vector      *   subcat_x ;
00565     cpl_vector      *   subcat_y ;
00566     double          *   pwave ;
00567     int                 nvals, nvals_tot ;
00568     int                 i ;
00569 
00570     /* Test entries */
00571     if (cat == NULL) return -1 ;
00572     if (wmax <= wmin) return -1 ;
00573 
00574     /* Initialise */
00575     nvals_tot = cpl_bivector_get_size(cat) ;
00576 
00577     /* Count the nb of values */
00578     pwave = cpl_bivector_get_x_data(cat) ;
00579     if (pwave[0] >= wmin) start = 0 ;
00580     else start = -1 ;
00581     if (pwave[nvals_tot-1] <= wmax) stop = nvals_tot-1 ;
00582     else stop = -1 ;
00583     i=0 ;
00584     while ((pwave[i] < wmin) && (i<nvals_tot-1)) i++ ;
00585     start = i ;
00586     i= nvals_tot-1 ;
00587     while ((pwave[i] > wmax) && (i>0)) i-- ;
00588     stop = i ;
00589 
00590     if (start>=stop) {
00591         cpl_msg_error(cpl_func, "Cannot plot the catalog") ;
00592         return -1 ;
00593     }
00594     nvals = start - stop + 1 ;
00595 
00596     /* Create the bivector to plot */
00597     subcat_x = cpl_vector_extract(cpl_bivector_get_x(cat), start, stop, 1) ;
00598     subcat_y = cpl_vector_extract(cpl_bivector_get_y(cat), start, stop, 1) ;
00599     subcat = cpl_bivector_wrap_vectors(subcat_x, subcat_y) ;
00600 
00601     /* Plot */
00602     irplib_bivector_plot(
00603             "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00604             "t 'Catalog Spectrum' w lines", "", subcat);
00605     cpl_bivector_unwrap_vectors(subcat) ;
00606     cpl_vector_delete(subcat_x) ;
00607     cpl_vector_delete(subcat_y) ;
00608 
00609     return 0 ;
00610 }
00611    
00612 /*----------------------------------------------------------------------------*/
00626 /*----------------------------------------------------------------------------*/
00627 cpl_vector * irplib_wlxcorr_convolve_create_kernel(
00628         double  slitw,
00629         double  fwhm)
00630 {
00631     double          sigma ;
00632     int             ihtophat, gausshlen, convolen ;
00633     cpl_vector  *   self ;
00634     cpl_vector  *   tophat ;
00635     cpl_image   *   iself ;
00636     int             i ;
00637     
00638     /* Initialise */
00639     sigma  = fwhm / (2.0 * sqrt(2.0*log(2.0)));
00640     ihtophat  = (int)slitw/2 ;
00641     gausshlen = 1 + 5 * sigma + ihtophat ;
00642 
00643     /* convolen must be at least twice the gausshlen */
00644     convolen  = 1 + 10 * sigma + 8 * ihtophat ;
00645 
00646     /* Test entries */
00647     if ((slitw <= 0.0) || (fwhm  <= 0.0) ||(convolen < 2 * gausshlen)) 
00648         return NULL ;
00649     
00650     /* Create the vectorss */
00651     self = cpl_vector_new(gausshlen) ;
00652     tophat = cpl_vector_new(convolen) ;
00653     
00654     /* Easiest way to fill with a Gaussian is via a CPL image */
00655     iself = cpl_image_wrap_double(gausshlen, 1, cpl_vector_get_data(self));
00656 
00657     /* Place the top point of the Gaussian on left-most pixel */
00658     cpl_image_fill_gaussian(iself, 1.0, 1.0, sqrt(2.0*atan(1.0)*4.0),sigma,1.0);
00659     cpl_image_unwrap(iself) ;
00660 
00661     /* The number of non-zero elements is 1+2*ihtophat */
00662     cpl_vector_fill(tophat, 0.0);
00663 
00664     for (i = convolen/2-ihtophat; i < 1+convolen/2+ihtophat; i++)
00665         cpl_vector_set(tophat, i, 1.0/(1.0+2.0*ihtophat));
00666 
00667     /* Convolve the Top-hat with the Gaussian */
00668     if (irplib_wlxcorr_convolve(tophat, self)) {
00669         cpl_msg_error(cpl_func, "Cannot convolve") ;
00670         cpl_vector_delete(self) ;
00671         cpl_vector_delete(tophat) ;
00672         return NULL ;
00673     }
00674 
00675     /* Overwrite the Gaussian with the Right Half of the convolution of the
00676        Top-hat + Gausssian */
00677     for (i = 0 ; i < gausshlen; i++)
00678         cpl_vector_set(self, i, cpl_vector_get(tophat, i + convolen/2));
00679     cpl_vector_delete(tophat) ;
00680 
00681     return self;
00682 }
00683 
00684 /*----------------------------------------------------------------------------*/
00693 /*----------------------------------------------------------------------------*/
00694 int irplib_wlxcorr_convolve(
00695         cpl_vector          *   smoothed,
00696         const cpl_vector    *   conv_kernel)
00697 {
00698     int             nsamples ;
00699     int             ihwidth ;
00700     cpl_vector  *   raw ;
00701     double      *   psmoothe ;
00702     double      *   praw ;
00703     double      *   psymm ;
00704     int             i, j ;
00705 
00706     /* Test entries */
00707     if ((!smoothed) || (!conv_kernel)) return -1 ;
00708 
00709     /* Initialise */
00710     nsamples = cpl_vector_get_size(smoothed) ;
00711     ihwidth = cpl_vector_get_size(conv_kernel) - 1 ;
00712     if (ihwidth >= nsamples) return -1 ;
00713     psymm = cpl_vector_get_data(conv_kernel) ;
00714     psmoothe = cpl_vector_get_data(smoothed) ;
00715     
00716     /* Create raw vector */
00717     raw = cpl_vector_duplicate(smoothed) ;
00718     praw = cpl_vector_get_data(raw) ;
00719 
00720     /* Convolve with the symmetric function */
00721     for (i=0 ; i<ihwidth ; i++) {
00722         psmoothe[i] = praw[i] * psymm[0];
00723         for (j=1 ; j <= ihwidth ; j++) {
00724             const int k = i-j < 0 ? 0 : i-j;
00725             psmoothe[i] += (praw[k]+praw[i+j]) * psymm[j];
00726         }
00727     }
00728 
00729     for (i=ihwidth ; i<nsamples-ihwidth ; i++) {
00730         psmoothe[i] = praw[i] * psymm[0];
00731         for (j=1 ; j<=ihwidth ; j++)
00732             psmoothe[i] += (praw[i-j]+praw[i+j]) * psymm[j];
00733     }
00734     for (i=nsamples-ihwidth ; i<nsamples ; i++) {
00735         psmoothe[i] = praw[i] * psymm[0];
00736         for (j=1 ; j<=ihwidth ; j++) {
00737             const int k = i+j > nsamples-1 ? nsamples - 1 : i+j;
00738             psmoothe[i] += (praw[k]+praw[i-j]) * psymm[j];
00739         }
00740     }
00741     cpl_vector_delete(raw) ;
00742     return 0 ;
00743 }
00744 
00747 /*----------------------------------------------------------------------------*/
00763 /*----------------------------------------------------------------------------*/
00764 static cpl_bivector * irplib_wlxcorr_gen_signal(
00765         const cpl_bivector      *   lines_catalog,
00766         double                      slitw,
00767         double                      fwhm,
00768         const cpl_polynomial    *   poly,
00769         int                         nsamples,
00770         int                         search_hs,
00771         int                     *   nb_lines)
00772 {
00773     int                 size, nlines ;
00774     cpl_vector      *   conv_kernel ;
00775     cpl_bivector    *   gen_spectrum ;
00776     cpl_bivector    *   sub_cat ;
00777     double              wave_min, wave_max ;
00778     cpl_vector      *   wl_limits ;
00779     int                 ind ;
00780     double              new_val, wl ;
00781     int                 i ;
00782 
00783     /* Initialise */
00784     size = nsamples + 2 * search_hs ;
00785     
00786     /* Test entries */
00787     if (!lines_catalog || !poly) return NULL ;
00788     if (size <= 1) return NULL ;
00789    
00790     /* Create the gen_spectrum X values */
00791     gen_spectrum = cpl_bivector_new(size) ;
00792     cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_spectrum), poly, 
00793             -search_hs+1, 1) ;
00794 
00795     /* Extract the relevant part of the catalog */
00796     wave_min = cpl_vector_get(cpl_bivector_get_x(gen_spectrum), 0) ;
00797     wave_max = cpl_vector_get(cpl_bivector_get_x(gen_spectrum), size-1) ;
00798     sub_cat = irplib_wlxcorr_cat_extract(lines_catalog, wave_min, wave_max) ;
00799     if (sub_cat == NULL) {
00800         cpl_bivector_delete(gen_spectrum) ;
00801         return NULL ;
00802     }
00803     nlines = cpl_bivector_get_size(sub_cat) ;
00804     if (nb_lines) *nb_lines = nlines ;
00805 
00806     /* Resample the spectrum */
00807     wl_limits = cpl_vector_new(size + 1);
00808     cpl_vector_fill_polynomial(wl_limits, poly, -search_hs+0.5, 1) ;
00809     if (nlines < size) {
00810         /* A few lines in catalog */
00811         cpl_vector_fill(cpl_bivector_get_y(gen_spectrum), 0.0) ;
00812         for (i=0 ; i<nlines ; i++) {
00813             wl = cpl_vector_get(cpl_bivector_get_x(sub_cat), i) ;
00814             ind = 0 ;
00815             while (wl>cpl_vector_get(wl_limits, ind) && ind<size-1) 
00816                 ind++ ;
00817             new_val = cpl_vector_get(cpl_bivector_get_y(gen_spectrum), ind) ;
00818             new_val += cpl_vector_get(cpl_bivector_get_y(sub_cat), i) ;
00819             cpl_vector_set(cpl_bivector_get_y(gen_spectrum), ind, new_val) ;
00820         }
00821     } else {
00822         /* High resolution catalog */
00823         if (irplib_wlxcorr_signal_resample(cpl_bivector_get_y(gen_spectrum),
00824                     wl_limits, lines_catalog)) {
00825             cpl_msg_error(cpl_func, "Cannot resample the signal") ;
00826             cpl_bivector_delete(gen_spectrum) ;
00827             cpl_vector_delete(wl_limits) ;
00828             cpl_bivector_delete(sub_cat) ;
00829             return NULL ;
00830         }
00831     }
00832     cpl_bivector_delete(sub_cat) ;
00833     cpl_vector_delete(wl_limits) ;
00834 
00835     /* Create convolution kernel */
00836     if ((conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, 
00837                     fwhm)) == NULL) {
00838         cpl_msg_error(cpl_func, "Cannot create convolution kernel") ;
00839         cpl_bivector_delete(gen_spectrum) ;
00840         return NULL ;
00841     }
00842  
00843     /* Smooth the instrument resolution */
00844     if (irplib_wlxcorr_convolve(cpl_bivector_get_y(gen_spectrum),conv_kernel)) {
00845         cpl_msg_error(cpl_func, "Cannot smoothe the signal");
00846         cpl_bivector_delete(gen_spectrum) ;
00847         return NULL ;
00848     }
00849     cpl_vector_delete(conv_kernel) ;
00850 
00851     return gen_spectrum ;
00852 }
00853 
00854 /*----------------------------------------------------------------------------*/
00864 /*----------------------------------------------------------------------------*/
00865 static int irplib_wlxcorr_signal_resample(
00866         cpl_vector          *   resampled, 
00867         const cpl_vector    *   xbounds,
00868         const cpl_bivector  *   hires)
00869 {
00870     cpl_vector      *   xhires ;
00871     cpl_vector      *   yhires ;
00872     double          *   pxhires ;
00873     double          *   pyhires ;
00874     double          *   pxbounds ;
00875     cpl_vector      *   ybounds ;
00876     cpl_bivector    *   boundary ;
00877     double          *   pybounds ;
00878     double          *   presampled ;
00879     int                 nsamples ;
00880     int                 i, itt ;
00881    
00882     /* Test entries */
00883     if ((!resampled) || (!xbounds) || (!hires)) return -1 ;
00884 
00885     /* Initialise */
00886     nsamples = cpl_vector_get_size(resampled) ;
00887 
00888     /* Initialise */
00889     presampled = cpl_vector_get_data(resampled) ;
00890     pxbounds = cpl_vector_get_data(xbounds) ;
00891     xhires = cpl_bivector_get_x(hires) ;
00892     yhires = cpl_bivector_get_y(hires) ;
00893     pxhires = cpl_vector_get_data(xhires) ;
00894     pyhires = cpl_vector_get_data(yhires) ;
00895     
00896     /* Create a new vector */
00897     ybounds = cpl_vector_new(cpl_vector_get_size(xbounds)) ;
00898     boundary = cpl_bivector_wrap_vectors((cpl_vector*)xbounds,ybounds) ;
00899     pybounds = cpl_vector_get_data(ybounds) ;
00900 
00901     /* Test entries */
00902     if (cpl_bivector_get_size(boundary) != nsamples + 1) {
00903         cpl_bivector_unwrap_vectors(boundary) ;
00904         cpl_vector_delete(ybounds) ;
00905         return -1 ;
00906     }
00907 
00908     /* Get the ind  */
00909     itt = cpl_vector_find(xhires, pxbounds[0]);
00910 
00911     /* Interpolate the signal */
00912     if (cpl_bivector_interpolate_linear(boundary, hires)) {
00913         cpl_msg_error(cpl_func, "Cannot interpolate the signal") ;
00914         cpl_bivector_unwrap_vectors(boundary) ;
00915         cpl_vector_delete(ybounds) ;
00916         return -1 ;
00917     }
00918 
00919     /* At this point itt most likely points to element just below
00920        pxbounds[0] */
00921     while (pxhires[itt] < pxbounds[0]) itt++;
00922 
00923     for (i=0; i < nsamples; i++) {
00924         /* The i'th signal is the weighted average of the two interpolated
00925            signals at the pixel boundaries and those table signals in
00926            between */
00927 
00928         double xlow  = pxbounds[i];
00929         double x     = pxhires[itt];
00930 
00931         if (x > pxbounds[i+1]) x = pxbounds[i+1];
00932         /* Contribution from interpolated value at wavelength at lower pixel
00933            boundary */
00934         presampled[i] = pybounds[i] * (x - xlow);
00935 
00936         /* Contribution from table values in between pixel boundaries */
00937         while ((pxhires[itt] < pxbounds[i+1]) && 
00938                 (itt < cpl_bivector_get_size(hires))) {
00939             const double xprev = x;
00940             x = pxhires[itt+1];
00941             if (x > pxbounds[i+1]) x = pxbounds[i+1];
00942             presampled[i] += pyhires[itt] * (x - xlow);
00943             xlow = xprev;
00944             itt++;
00945         }
00946 
00947         /* Contribution from interpolated value at wavelength at upper pixel
00948            boundary */
00949         presampled[i] += pybounds[i+1] * (pxbounds[i+1] - xlow);
00950 
00951         /* Compute average by dividing integral by length of pixel range
00952            (the factor 2 comes from the contributions) */
00953         presampled[i] /= 2 * (pxbounds[i+1] - pxbounds[i]);
00954     }
00955     cpl_bivector_unwrap_vectors(boundary) ;
00956     cpl_vector_delete(ybounds) ;
00957     return 0 ;
00958 }
00959 

Generated on Tue Jun 19 14:39:14 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6