28 #include "irplib_ppm.h"
29 #include "irplib_wlxcorr.h"
30 #include "irplib_spectrum.h"
38 #ifdef IRPLIB_PPM_USE_METHOD2
39 static cpl_vector * irplib_ppm_convolve_line(
const cpl_vector *,
double,
double);
40 static cpl_vector * irplib_ppm_detect_lines(
const cpl_vector *,
double) ;
70 const cpl_vector * spectrum,
71 const cpl_bivector * lines_catalog,
72 const cpl_polynomial * poly_init,
78 cpl_table ** tab_infos)
80 #ifdef IRPLIB_PPM_USE_METHOD2
81 cpl_vector * spec_conv ;
84 cpl_vector * det_lines ;
86 cpl_vector * cat_lines ;
89 double disp_min, disp_max, disp ;
90 int nlines_cat, nlines ;
91 const double * plines_catalog_x ;
92 const double * plines_catalog_y ;
93 cpl_bivector * matched ;
94 cpl_matrix * matchedx;
96 cpl_polynomial * fitted ;
97 cpl_table * spc_table ;
98 const cpl_vector* vectors_plot[3];
100 int wl_ind, start_ind, stop_ind ;
104 cpl_error_code error;
107 if (spectrum == NULL)
return NULL ;
108 if (lines_catalog == NULL)
return NULL ;
109 if (poly_init == NULL)
return NULL ;
112 spec_sz = cpl_vector_get_size(spectrum) ;
113 deg_loc = (cpl_size)degree ;
115 #ifdef IRPLIB_PPM_USE_METHOD2
118 if ((spec_conv = irplib_ppm_convolve_line(spectrum, slitw, fwhm)) == NULL) {
119 cpl_msg_error(cpl_func,
"Cannot convolve the signal") ;
124 if ((det_lines = irplib_ppm_detect_lines(spec_conv, 0.9)) == NULL) {
125 cpl_msg_error(cpl_func,
"Cannot detect lines") ;
126 cpl_vector_delete(spec_conv) ;
129 cpl_vector_delete(spec_conv) ;
133 thresh, 0, NULL, NULL)) == NULL) {
134 cpl_msg_error(cpl_func,
"Cannot convolve the signal") ;
138 cpl_msg_info(cpl_func,
"Detected %"CPL_SIZE_FORMAT
" lines",
139 cpl_vector_get_size(det_lines));
142 wmin = cpl_polynomial_eval_1d(poly_init, 1.0, NULL) ;
143 wmax = cpl_polynomial_eval_1d(poly_init, spec_sz, NULL) ;
144 plines_catalog_x = cpl_bivector_get_x_data_const(lines_catalog) ;
145 plines_catalog_y = cpl_bivector_get_y_data_const(lines_catalog) ;
146 nlines = cpl_bivector_get_size(lines_catalog) ;
148 start_ind = stop_ind = -1 ;
149 for (i=0 ; i<nlines ; i++) {
150 if (plines_catalog_x[i] > wmin && plines_catalog_x[i] < wmax &&
151 plines_catalog_y[i] > 0.0) {
153 if (start_ind<0) start_ind = i ;
157 if (nlines_cat == 0) {
158 cpl_msg_error(cpl_func,
"No lines in catalog") ;
159 cpl_vector_delete(det_lines) ;
162 cat_lines = cpl_vector_new(nlines_cat) ;
163 pcat_lines = cpl_vector_get_data(cat_lines) ;
165 for (i=0 ; i<nlines ; i++) {
166 if (plines_catalog_x[i] > wmin && plines_catalog_x[i] < wmax &&
167 plines_catalog_y[i] > 0.0) {
168 pcat_lines[nlines_cat] = plines_catalog_x[i] ;
176 irplib_wlxcorr_catalog_plot(lines_catalog, wmin, wmax) ;
179 fill_val = cpl_vector_get_max(spectrum) ;
180 plot_y = cpl_vector_new(spec_sz);
181 cpl_vector_fill(plot_y, 0.0) ;
182 pdet_lines = cpl_vector_get_data(det_lines) ;
183 for (i=0 ; i<cpl_vector_get_size(det_lines) ; i++) {
184 cpl_vector_set(plot_y, (
int)pdet_lines[i], fill_val) ;
186 vectors_plot[0] = NULL ;
187 vectors_plot[1] = spectrum ;
188 vectors_plot[2] = plot_y ;
190 cpl_plot_vectors(
"set grid;set xlabel 'Position (Pixel)';set ylabel "
191 "'Intensity (ADU/sec)';",
192 "t 'Spectrum with detected lines' w lines",
"",
194 cpl_vector_delete(plot_y) ;
198 disp = (wmax-wmin) / spec_sz ;
199 disp_min = disp - (disp/10) ;
200 disp_max = disp + (disp/10) ;
201 matched = cpl_ppm_match_positions(det_lines, cat_lines, disp_min,
202 disp_max, 0.05, NULL, NULL);
203 cpl_vector_delete(det_lines) ;
204 cpl_vector_delete(cat_lines) ;
206 if (matched == NULL) {
207 cpl_msg_error(cpl_func,
"Cannot apply the point pattern matching") ;
211 match_sz = cpl_bivector_get_size(matched);
213 cpl_msg_info(cpl_func,
"Matched %d lines", match_sz) ;
215 if (match_sz <= deg_loc) {
216 cpl_msg_error(cpl_func,
"Not enough match for the fit") ;
217 cpl_bivector_delete(matched) ;
223 const double * pmatched ;
224 cpl_bivector * biplot ;
225 cpl_vector * plot_cat_x ;
226 cpl_vector * plot_cat_y ;
228 fill_val = cpl_vector_get_max(spectrum) ;
229 plot_y = cpl_vector_new(spec_sz);
230 cpl_vector_fill(plot_y, 0.0) ;
231 pmatched = cpl_bivector_get_x_data_const(matched) ;
232 for (i=0 ; i < match_sz; i++) {
233 cpl_vector_set(plot_y, (
int)pmatched[i], fill_val) ;
235 vectors_plot[0] = NULL ;
236 vectors_plot[1] = spectrum ;
237 vectors_plot[2] = plot_y ;
239 cpl_plot_vectors(
"set grid;set xlabel 'Position (Pixel)';set ylabel "
240 "'Intensity (ADU/sec)';",
241 "t 'Spectrum with matched lines' w lines",
"",
243 cpl_vector_delete(plot_y) ;
246 plot_cat_x=cpl_vector_extract(cpl_bivector_get_x_const(lines_catalog),
247 start_ind, stop_ind, 1) ;
248 plot_cat_y=cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog),
249 start_ind, stop_ind, 1) ;
250 biplot = cpl_bivector_wrap_vectors(plot_cat_x, plot_cat_y) ;
251 cpl_plot_bivector(
"set grid;set xlabel 'Wavelength';set ylabel "
252 "'Emission';",
"t 'Catalog' w impulses",
"",
254 cpl_bivector_unwrap_vectors(biplot) ;
256 plot_y = cpl_vector_duplicate(plot_cat_y) ;
257 cpl_vector_fill(plot_y, 0.0) ;
258 pmatched = cpl_bivector_get_y_data_const(matched) ;
259 fill_val=cpl_vector_get_mean(plot_cat_y) ;
260 for (i=0 ; i < match_sz; i++) {
262 while (pmatched[i] > cpl_vector_get(plot_cat_x, wl_ind)
263 && wl_ind < spec_sz) wl_ind++ ;
264 if (wl_ind < spec_sz) cpl_vector_set(plot_y, wl_ind, fill_val) ;
266 biplot = cpl_bivector_wrap_vectors(plot_cat_x, plot_y) ;
267 cpl_plot_bivector(
"set grid;set xlabel 'Wavelength';set ylabel "
268 "'Emission';",
"t 'Catalog (matched lines)' w "
269 "impulses",
"", biplot) ;
270 cpl_bivector_unwrap_vectors(biplot) ;
271 cpl_vector_delete(plot_cat_x) ;
272 cpl_vector_delete(plot_cat_y) ;
273 cpl_vector_delete(plot_y) ;
277 matchedx = cpl_matrix_wrap(1, match_sz, cpl_bivector_get_x_data(matched));
278 fitted = cpl_polynomial_new(1);
279 error = cpl_polynomial_fit(fitted, matchedx, NULL,
280 cpl_bivector_get_y_const(matched), NULL,
281 CPL_FALSE, NULL, °_loc);
282 cpl_bivector_delete(matched);
283 (void)cpl_matrix_unwrap(matchedx);
285 cpl_msg_error(cpl_func,
"Cannot fit the polynomial") ;
286 cpl_polynomial_delete(fitted);
291 if ((spc_table = irplib_wlxcorr_gen_spc_table(spectrum,
292 lines_catalog, slitw, fwhm, poly_init, fitted)) == NULL) {
293 cpl_msg_error(cpl_func,
"Cannot generate the infos table") ;
294 cpl_polynomial_delete(fitted) ;
297 if (tab_infos != NULL) *tab_infos = spc_table ;
298 else cpl_table_delete(spc_table) ;
304 #ifdef IRPLIB_PPM_USE_METHOD2
317 static cpl_vector * irplib_ppm_convolve_line(
318 const cpl_vector * spectrum,
322 cpl_vector * conv_kernel ;
323 cpl_vector * line_profile ;
324 cpl_vector * xcorrs ;
325 cpl_vector * spec_ext ;
326 cpl_vector * xc_single ;
327 int hs, line_sz, sp_sz ;
331 if (spectrum == NULL)
return NULL ;
334 if ((conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw,
336 cpl_msg_error(cpl_func,
"Cannot create kernel") ;
339 hs = cpl_vector_get_size(conv_kernel) ;
340 line_sz = 2 * hs + 1 ;
343 line_profile = cpl_vector_new(line_sz) ;
344 cpl_vector_fill(line_profile, 0.0) ;
345 cpl_vector_set(line_profile, hs, 1.0) ;
346 if (irplib_wlxcorr_convolve(line_profile, conv_kernel) != 0) {
347 cpl_msg_error(cpl_func,
"Cannot create line profile") ;
348 cpl_vector_delete(line_profile) ;
349 cpl_vector_delete(conv_kernel) ;
352 cpl_vector_delete(conv_kernel) ;
355 sp_sz = cpl_vector_get_size(spectrum) ;
356 xcorrs = cpl_vector_new(sp_sz) ;
357 cpl_vector_fill(xcorrs, 0.0) ;
358 xc_single = cpl_vector_new(1) ;
361 for (i=hs ; i<sp_sz-hs ; i++) {
363 if ((spec_ext = cpl_vector_extract(spectrum, i-hs, i+hs, 1)) == NULL) {
364 cpl_msg_error(cpl_func,
"Cannot extract spectrum") ;
365 cpl_vector_delete(xc_single) ;
366 cpl_vector_delete(line_profile) ;
369 if (cpl_vector_correlate(xc_single, spec_ext, line_profile) < 0) {
370 cpl_msg_error(cpl_func,
"Cannot correlate") ;
371 cpl_vector_delete(xc_single) ;
372 cpl_vector_delete(line_profile) ;
373 cpl_vector_delete(spec_ext) ;
376 cpl_vector_set(xcorrs, i, cpl_vector_get(xc_single, 0)) ;
377 cpl_vector_delete(spec_ext) ;
379 cpl_vector_delete(xc_single) ;
380 cpl_vector_delete(line_profile) ;
395 static cpl_vector * irplib_ppm_detect_lines(
396 const cpl_vector * spec,
399 cpl_vector * spec_loc ;
403 int spec_loc_sz, max_ind, nlines ;
408 if (spec == NULL)
return NULL ;
411 spec_loc = cpl_vector_duplicate(spec) ;
412 pspec_loc = cpl_vector_get_data(spec_loc) ;
413 spec_loc_sz = cpl_vector_get_size(spec_loc) ;
416 for (i=0 ; i<spec_loc_sz ; i++)
417 if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
420 lines = cpl_vector_new(spec_loc_sz) ;
421 plines = cpl_vector_get_data(lines) ;
425 while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
428 while (max_ind < spec_loc_sz && pspec_loc[max_ind] < max) max_ind++ ;
429 if (max_ind == spec_loc_sz) {
430 cpl_msg_error(cpl_func,
"Cannot find maximum") ;
431 cpl_vector_delete(spec_loc) ;
432 cpl_vector_delete(lines) ;
435 if (max_ind == 0 || max_ind == spec_loc_sz-1) {
436 pspec_loc[max_ind] = 0 ;
441 plines[nlines] = pspec_loc[max_ind] * max_ind +
442 pspec_loc[max_ind-1] * (max_ind-1) +
443 pspec_loc[max_ind+1] * (max_ind+1) ;
444 plines[nlines] /= pspec_loc[max_ind] + pspec_loc[max_ind+1] +
445 pspec_loc[max_ind-1] ;
451 while (i>=0 && pspec_loc[i] > threshold) {
456 while (i<spec_loc_sz && pspec_loc[i] > threshold) {
461 cpl_vector_delete(spec_loc) ;
465 cpl_msg_error(cpl_func,
"Cannot detect any line") ;
466 cpl_vector_delete(lines) ;
471 cpl_vector_set_size(lines, nlines) ;
474 cpl_vector_sort(lines, 1) ;
cpl_polynomial * irplib_ppm_engine(const cpl_vector *spectrum, const cpl_bivector *lines_catalog, const cpl_polynomial *poly_init, double slitw, double fwhm, double thresh, int degree, int doplot, cpl_table **tab_infos)
The Wavelength Calibration using PPM.
cpl_vector * irplib_spectrum_detect_peaks(const cpl_vector *in, int fwhm, double sigma, int display, cpl_vector **fwhms_out, cpl_vector **areas_out)
Detect the brightest features in a spectrum.