irplib_ppm.c

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

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1