irplib_ppm.c

00001 /* $Id: irplib_ppm.c,v 1.14 2007/07/24 08:28:58 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., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: yjung $
00023  * $Date: 2007/07/24 08:28:58 $
00024  * $Revision: 1.14 $
00025  * $Name: uves-3_9_0 $
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_ppm.h"
00040 #include "irplib_wlxcorr.h"
00041 #include "irplib_plot.h"
00042 
00043 /*-----------------------------------------------------------------------------
00044                                    Includes
00045  -----------------------------------------------------------------------------*/
00046 
00047 static cpl_vector * irplib_ppm_convolve_line(const cpl_vector *, double,double);
00048 static cpl_vector * irplib_ppm_detect_lines(const cpl_vector *, double) ;
00049 
00050 /*----------------------------------------------------------------------------*/
00054 /*----------------------------------------------------------------------------*/
00055 
00058 /*----------------------------------------------------------------------------*/
00075 /*----------------------------------------------------------------------------*/
00076 cpl_polynomial * irplib_ppm_engine(
00077         const cpl_vector        *   spectrum,
00078         const cpl_bivector      *   lines_catalog,
00079         const cpl_polynomial    *   poly_init,
00080         double                      slitw,
00081         double                      fwhm,
00082         double                      thresh,
00083         int                         degree,
00084         int                         doplot,
00085         cpl_table               **  tab_infos)
00086 {
00087     cpl_vector      *   spec_conv ;
00088     int                 spec_sz ;
00089     cpl_vector      *   det_lines ;
00090     cpl_vector      *   cat_lines ;
00091     double          *   pcat_lines ;
00092     double              wmin, wmax ;
00093     double              disp_min, disp_max, disp ;
00094     int                 nlines_cat, nlines ;
00095     const double    *   plines_catalog_x ;
00096     const double    *   plines_catalog_y ;
00097     cpl_bivector    *   matched ;
00098     double          *   pmatched ;
00099     cpl_polynomial  *   fitted ;
00100     cpl_table       *   spc_table ;
00101     cpl_vector      **  vectors_plot ;
00102     cpl_vector      *   plot_cat_x ;
00103     cpl_vector      *   plot_cat_y ;
00104     cpl_vector      *   plot_y ;
00105     int                 wl_ind, start_ind, stop_ind ;
00106     int                 i ;
00107 
00108     /* Check entries */
00109     if (spectrum == NULL) return NULL ;
00110     if (lines_catalog == NULL) return NULL ;
00111     if (poly_init == NULL) return NULL ;
00112 
00113     /* Initialise */
00114     spec_sz = cpl_vector_get_size(spectrum) ;
00115     
00116     /* Correlate the spectrum with the line profile */
00117     if ((spec_conv = irplib_ppm_convolve_line(spectrum, slitw, fwhm)) == NULL) {
00118         cpl_msg_error(cpl_func, "Cannot convolve the signal") ;
00119         return NULL ;
00120     }
00121 
00122     /* Plot if requested */
00123     if (doplot) {
00124         irplib_vector_plot(
00125     "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00126     "t 'Spectrum' w lines", "", spectrum) ;
00127         irplib_vector_plot(
00128     "set grid;set xlabel 'Position (Pixel)';set ylabel 'Correlation';",
00129     "t 'Spectrum convolved with the line profile' w lines", "", spec_conv) ;
00130     }
00131     
00132     /* Apply the lines detection */
00133     if ((det_lines = irplib_ppm_detect_lines(spec_conv, thresh)) == NULL) {
00134         cpl_msg_error(cpl_func, "Cannot detect lines") ;
00135         cpl_vector_delete(spec_conv) ;
00136         return NULL ;
00137     }
00138     cpl_vector_delete(spec_conv) ;
00139 
00140     /* Get the catalog lines */
00141     wmin = cpl_polynomial_eval_1d(poly_init, 1.0, NULL) ;
00142     wmax = cpl_polynomial_eval_1d(poly_init, spec_sz, NULL) ;
00143     plines_catalog_x = cpl_bivector_get_x_data_const(lines_catalog) ;
00144     plines_catalog_y = cpl_bivector_get_y_data_const(lines_catalog) ;
00145     nlines = cpl_bivector_get_size(lines_catalog) ;
00146     nlines_cat = 0 ;
00147     start_ind = stop_ind = -1 ;
00148     for (i=0 ; i<nlines ; i++) {
00149         if (plines_catalog_x[i] > wmin && plines_catalog_x[i] < wmax &&
00150                 plines_catalog_y[i] > 0.0) {
00151             nlines_cat++ ;
00152             if (start_ind<0) start_ind = i ;
00153             stop_ind = i ;
00154         }
00155     }
00156     if (nlines_cat == 0) {
00157         cpl_msg_error(cpl_func, "No lines in catalog") ;
00158         cpl_vector_delete(det_lines) ;
00159         return NULL ;
00160     }
00161     cat_lines = cpl_vector_new(nlines_cat) ;
00162     pcat_lines = cpl_vector_get_data(cat_lines) ;
00163     nlines_cat = 0 ;
00164     for (i=0 ; i<nlines ; i++) {
00165         if (plines_catalog_x[i] > wmin && plines_catalog_x[i] < wmax &&
00166                 plines_catalog_y[i] > 0.0) {
00167             pcat_lines[nlines_cat] = plines_catalog_x[i] ; 
00168             nlines_cat++ ;
00169         }
00170     }
00171     
00172     /* Apply the point pattern matching */
00173     disp = (wmax-wmin) / spec_sz ;
00174     disp_min = disp - (disp/10) ;
00175     disp_max = disp + (disp/10) ;
00176     if ((matched = cpl_ppm_match_positions(det_lines, cat_lines,
00177                     disp_min, disp_max, 0.05, NULL, NULL)) == NULL) {
00178         cpl_msg_error(cpl_func, "Cannot apply the point pattern matching") ;
00179         cpl_vector_delete(det_lines) ;
00180         cpl_vector_delete(cat_lines) ;
00181         return NULL ;
00182     }
00183     cpl_vector_delete(det_lines) ;
00184     cpl_vector_delete(cat_lines) ;
00185     if (cpl_bivector_get_size(matched) <= degree) {
00186         cpl_msg_error(cpl_func, "Not enough match for the fit") ;
00187         cpl_bivector_delete(matched) ;
00188         return NULL ;
00189     }
00190     cpl_msg_info(cpl_func, "Matched %d lines", cpl_bivector_get_size(matched)) ;
00191     
00192     /* Plot if requested */
00193     if (doplot) {
00194         /* Spectrum with matched lines */
00195         plot_y = cpl_vector_duplicate(spectrum) ;
00196         cpl_vector_fill(plot_y, 0.0) ;
00197         pmatched = cpl_bivector_get_x_data(matched) ;
00198         for (i=0 ; i<cpl_bivector_get_size(matched) ; i++) {
00199             cpl_vector_set(plot_y, (int)pmatched[i], 10.0) ;
00200         }
00201         vectors_plot = cpl_malloc(3*sizeof(cpl_vector*)) ;
00202         vectors_plot[0] = NULL ;
00203         vectors_plot[1] = (cpl_vector*)spectrum ;
00204         vectors_plot[2] = plot_y ;
00205         irplib_vectors_plot(
00206     "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00207     "t 'Spectrum with matched lines' w lines", "", 
00208     (const cpl_vector **)vectors_plot, 3) ;
00209         cpl_vector_delete(plot_y) ;
00210 
00211         /* Catalog with matched lines */
00212         plot_cat_x=cpl_vector_extract(cpl_bivector_get_x_const(lines_catalog), 
00213                 start_ind, stop_ind, 1) ;
00214         plot_cat_y=cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog), 
00215                 start_ind, stop_ind, 1) ;
00216         vectors_plot[0] = plot_cat_x ;
00217         vectors_plot[1] = plot_cat_y ;
00218         plot_y = cpl_vector_duplicate(vectors_plot[1]) ;
00219         cpl_vector_fill(plot_y, 0.0) ;
00220         pmatched = cpl_bivector_get_y_data(matched) ;
00221         for (i=0 ; i<cpl_bivector_get_size(matched) ; i++) {
00222             wl_ind = 0 ;
00223             while (pmatched[i] > cpl_vector_get(vectors_plot[0], wl_ind) 
00224                     && wl_ind < spec_sz) wl_ind++ ;
00225             if (wl_ind < spec_sz) cpl_vector_set(plot_y, wl_ind, 100.0) ;
00226         }
00227         vectors_plot[2] = plot_y ;
00228         irplib_vectors_plot(
00229     "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00230     "t 'Catalog with matched lines' w lines", "", 
00231     (const cpl_vector **)vectors_plot, 3) ;
00232         cpl_vector_delete(plot_cat_x) ;
00233         cpl_vector_delete(plot_cat_y) ;
00234         cpl_vector_delete(plot_y) ;
00235         cpl_free(vectors_plot) ;
00236     }
00237     
00238     /* Apply the fit */
00239     if ((fitted=cpl_polynomial_fit_1d_create(
00240                     cpl_bivector_get_x(matched),
00241                     cpl_bivector_get_y(matched),
00242                     degree, NULL)) == NULL) {
00243         cpl_msg_error(cpl_func, "Cannot fit the polynomial") ;
00244         cpl_bivector_delete(matched) ;
00245         return NULL ;
00246     }
00247     cpl_bivector_delete(matched) ;
00248    
00249     /* Create the infos table */
00250     if ((spc_table = cpl_wlcalib_xc_gen_spc_table(spectrum,
00251                     lines_catalog, slitw, fwhm, poly_init, fitted)) == NULL) {
00252         cpl_msg_error(cpl_func, "Cannot generate the infos table") ;
00253         cpl_polynomial_delete(fitted) ;
00254         return NULL ;
00255     }
00256     
00257     /* Plot the result */
00258     if (doplot) {
00259         irplib_wlxcorr_plot_spc_table(spc_table, "PPM") ;
00260     }
00261 
00262     if (tab_infos != NULL) *tab_infos = spc_table ;
00263     else cpl_table_delete(spc_table) ;
00264     return fitted ;
00265 }
00266 
00269 /*----------------------------------------------------------------------------*/
00280 /*----------------------------------------------------------------------------*/
00281 static cpl_vector * irplib_ppm_convolve_line(
00282         const cpl_vector        *   spectrum,
00283         double                      slitw,
00284         double                      fwhm)
00285 {
00286     cpl_vector  *   conv_kernel ;
00287     cpl_vector  *   line_profile ;
00288     cpl_vector  *   xcorrs ;
00289     cpl_vector  *   spec_ext ;
00290     cpl_vector  *   xc_single ;
00291     int             hs, line_sz, sp_sz ;
00292     int             i ;
00293 
00294     /* Test entries */
00295     if (spectrum == NULL) return NULL ;
00296 
00297     /* Create the convolution kernel */
00298     if ((conv_kernel = cpl_wlcalib_xc_convolve_create_kernel(slitw,
00299                     fwhm)) == NULL) {
00300         cpl_msg_error(cpl_func, "Cannot create kernel") ;
00301         return NULL ;
00302     }
00303     hs = cpl_vector_get_size(conv_kernel) ;
00304     line_sz = 2 * hs + 1 ;
00305     
00306     /* Create the line profile */
00307     line_profile = cpl_vector_new(line_sz) ;
00308     cpl_vector_fill(line_profile, 0.0) ;
00309     cpl_vector_set(line_profile, hs, 1.0) ;
00310     if (cpl_wlcalib_xc_convolve(line_profile, conv_kernel) != 0) {
00311         cpl_msg_error(cpl_func, "Cannot create line profile") ;
00312         cpl_vector_delete(line_profile) ;
00313         cpl_vector_delete(conv_kernel) ;
00314         return NULL ;
00315     }
00316     cpl_vector_delete(conv_kernel) ;
00317     
00318     /* Create the correlations values vector */
00319     sp_sz = cpl_vector_get_size(spectrum) ;
00320     xcorrs = cpl_vector_new(sp_sz) ;
00321     cpl_vector_fill(xcorrs, 0.0) ;
00322     xc_single = cpl_vector_new(1) ;
00323 
00324     /* Loop on the pixels of the spectrum */
00325     for (i=hs ; i<sp_sz-hs ; i++) {
00326         /* Extract the current spectrum part */
00327         if ((spec_ext = cpl_vector_extract(spectrum, i-hs, i+hs, 1)) == NULL) {
00328             cpl_msg_error(cpl_func, "Cannot extract spectrum") ;
00329             cpl_vector_delete(xc_single) ;
00330             cpl_vector_delete(line_profile) ;
00331             return NULL ;
00332         }
00333         if (cpl_vector_correlate(xc_single, spec_ext, line_profile) < 0) {
00334             cpl_msg_error(cpl_func, "Cannot correlate") ;
00335             cpl_vector_delete(xc_single) ;
00336             cpl_vector_delete(line_profile) ;
00337             cpl_vector_delete(spec_ext) ;
00338             return NULL ;
00339         }
00340         cpl_vector_set(xcorrs, i, cpl_vector_get(xc_single, 0)) ;
00341         cpl_vector_delete(spec_ext) ;
00342     }
00343     cpl_vector_delete(xc_single) ;
00344     cpl_vector_delete(line_profile) ;
00345 
00346     return xcorrs ;
00347 } 
00348 
00349 /*----------------------------------------------------------------------------*/
00358 /*----------------------------------------------------------------------------*/
00359 static cpl_vector * irplib_ppm_detect_lines(
00360         const cpl_vector    *   spec,
00361         double                  threshold)
00362 {
00363     cpl_vector  *   spec_loc ;
00364     double      *   pspec_loc ;
00365     cpl_vector  *   lines ;
00366     double      *   plines ;
00367     int             spec_loc_sz, max_ind, nlines ;
00368     double          max ;
00369     int             i ;
00370 
00371     /* Test inputs */
00372     if (spec == NULL) return NULL ;
00373     if (threshold<0.0 || threshold > 1.0) return NULL ;
00374 
00375     /* Local spectrum */
00376     spec_loc = cpl_vector_duplicate(spec) ;
00377     pspec_loc = cpl_vector_get_data(spec_loc) ;
00378     spec_loc_sz = cpl_vector_get_size(spec_loc) ;
00379 
00380     /* Threshold the local spectrum */
00381     for (i=0 ; i<spec_loc_sz ; i++) 
00382         if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
00383     
00384     /* Allocate lines container */
00385     lines = cpl_vector_new(spec_loc_sz) ;
00386     plines = cpl_vector_get_data(lines) ;
00387     nlines = 0 ;
00388     
00389     /* Loop as long as there are lines */
00390     while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
00391         /* Find the max position */
00392         max_ind = 0 ;
00393         while (pspec_loc[max_ind]<max && max_ind<spec_loc_sz) max_ind++ ;
00394         if (max_ind == spec_loc_sz) {
00395             cpl_msg_error(cpl_func, "Cannot find maximum") ;
00396             cpl_vector_delete(spec_loc) ;
00397             cpl_vector_delete(lines) ;
00398             return NULL ;
00399         }
00400         if (max_ind == 0 || max_ind == spec_loc_sz-1) {
00401             pspec_loc[max_ind] = 0 ;
00402             continue ;
00403         }
00404 
00405         /* Get the precise position from the neighbours values */
00406         plines[nlines] =    pspec_loc[max_ind] * max_ind + 
00407                             pspec_loc[max_ind-1] * (max_ind-1) +
00408                             pspec_loc[max_ind+1] * (max_ind+1) ; 
00409         plines[nlines] /= pspec_loc[max_ind] + pspec_loc[max_ind+1] +
00410             pspec_loc[max_ind-1] ;
00411         plines[nlines] ++ ;
00412         nlines ++ ;
00413 
00414         /* Clean the line */
00415         i = max_ind ;
00416         while (i>=0 && pspec_loc[i] > threshold) {
00417             pspec_loc[i] = 0.0 ;
00418             i-- ;
00419         }
00420         i = max_ind+1 ;
00421         while (i<spec_loc_sz && pspec_loc[i] > threshold) {
00422             pspec_loc[i] = 0.0 ;
00423             i++ ;
00424         }
00425     }
00426     cpl_vector_delete(spec_loc) ;
00427    
00428     /* Check if there are lines */
00429     if (nlines == 0) {
00430         cpl_msg_error(cpl_func, "Cannot detect any line") ;
00431         cpl_vector_delete(lines) ;
00432         return NULL ;
00433     }
00434     
00435     /* Resize the vector */
00436     cpl_vector_set_size(lines, nlines) ;
00437 
00438     /* Sort the lines */
00439     cpl_vector_sort(lines, 1) ;
00440     
00441     return lines ;
00442 }
00443 
00444 
00445 
00446 

Generated on Fri Apr 18 14:11:41 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1