irplib_ppm.c

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