00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
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
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
00114 if (spectrum == NULL) return NULL ;
00115 if (lines_catalog == NULL) return NULL ;
00116 if (poly_init == NULL) return NULL ;
00117
00118
00119 spec_sz = cpl_vector_get_size(spectrum) ;
00120
00121 #ifdef IRPLIB_PPM_USE_METHOD2
00122
00123
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
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
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
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
00179 if (doplot) {
00180
00181 irplib_wlxcorr_catalog_plot(lines_catalog, wmin, wmax) ;
00182
00183
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
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
00227 if (doplot) {
00228 const double * pmatched ;
00229 cpl_bivector * biplot ;
00230 cpl_vector * plot_cat_x ;
00231 cpl_vector * plot_cat_y ;
00232
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
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
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, °ree);
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
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
00336 if (spectrum == NULL) return NULL ;
00337
00338
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
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
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
00366 for (i=hs ; i<sp_sz-hs ; i++) {
00367
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
00413 if (spec == NULL) return NULL ;
00414
00415
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
00421 for (i=0 ; i<spec_loc_sz ; i++)
00422 if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
00423
00424
00425 lines = cpl_vector_new(spec_loc_sz) ;
00426 plines = cpl_vector_get_data(lines) ;
00427 nlines = 0 ;
00428
00429
00430 while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
00431
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
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
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
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
00476 cpl_vector_set_size(lines, nlines) ;
00477
00478
00479 cpl_vector_sort(lines, 1) ;
00480
00481 return lines ;
00482 }
00483
00484 #endif