irplib_ppm.c

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

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