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 #include "irplib_plot.h"
00043
00044
00045
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
00116 if (spectrum == NULL) return NULL ;
00117 if (lines_catalog == NULL) return NULL ;
00118 if (poly_init == NULL) return NULL ;
00119
00120
00121 spec_sz = cpl_vector_get_size(spectrum) ;
00122
00123 #ifdef IRPLIB_PPM_USE_METHOD2
00124
00125
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
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
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
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
00181 if (doplot) {
00182
00183 irplib_wlxcorr_catalog_plot(lines_catalog, wmin, wmax) ;
00184
00185
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
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
00228 if (doplot) {
00229
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
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
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
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
00332 if (spectrum == NULL) return NULL ;
00333
00334
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
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
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
00362 for (i=hs ; i<sp_sz-hs ; i++) {
00363
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
00409 if (spec == NULL) return NULL ;
00410
00411
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
00417 for (i=0 ; i<spec_loc_sz ; i++)
00418 if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
00419
00420
00421 lines = cpl_vector_new(spec_loc_sz) ;
00422 plines = cpl_vector_get_data(lines) ;
00423 nlines = 0 ;
00424
00425
00426 while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
00427
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
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
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
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
00472 cpl_vector_set_size(lines, nlines) ;
00473
00474
00475 cpl_vector_sort(lines, 1) ;
00476
00477 return lines ;
00478 }
00479
00480 #endif