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 #ifndef CPL_SIZE_FORMAT
00045 #define CPL_SIZE_FORMAT "d"
00046 #define cpl_size int
00047 #endif
00048
00049
00050
00051
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
00122 if (spectrum == NULL) return NULL ;
00123 if (lines_catalog == NULL) return NULL ;
00124 if (poly_init == NULL) return NULL ;
00125
00126
00127 spec_sz = cpl_vector_get_size(spectrum) ;
00128 deg_loc = (cpl_size)degree ;
00129
00130 #ifdef IRPLIB_PPM_USE_METHOD2
00131
00132
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
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
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
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
00189 if (doplot) {
00190
00191 irplib_wlxcorr_catalog_plot(lines_catalog, wmin, wmax) ;
00192
00193
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
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
00237 if (doplot) {
00238 const double * pmatched ;
00239 cpl_bivector * biplot ;
00240 cpl_vector * plot_cat_x ;
00241 cpl_vector * plot_cat_y ;
00242
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
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
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, °_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
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
00346 if (spectrum == NULL) return NULL ;
00347
00348
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
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
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
00376 for (i=hs ; i<sp_sz-hs ; i++) {
00377
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
00423 if (spec == NULL) return NULL ;
00424
00425
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
00431 for (i=0 ; i<spec_loc_sz ; i++)
00432 if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
00433
00434
00435 lines = cpl_vector_new(spec_loc_sz) ;
00436 plines = cpl_vector_get_data(lines) ;
00437 nlines = 0 ;
00438
00439
00440 while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
00441
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
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
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
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
00486 cpl_vector_set_size(lines, nlines) ;
00487
00488
00489 cpl_vector_sort(lines, 1) ;
00490
00491 return lines ;
00492 }
00493
00494 #endif