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_plot.h"
00042
00043
00044
00045
00046
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
00050
00054
00055
00058
00075
00076 cpl_polynomial * irplib_ppm_engine(
00077 const cpl_vector * spectrum,
00078 const cpl_bivector * lines_catalog,
00079 const cpl_polynomial * poly_init,
00080 double slitw,
00081 double fwhm,
00082 double thresh,
00083 int degree,
00084 int doplot,
00085 cpl_table ** tab_infos)
00086 {
00087 cpl_vector * spec_conv ;
00088 int spec_sz ;
00089 cpl_vector * det_lines ;
00090 cpl_vector * cat_lines ;
00091 double * pcat_lines ;
00092 double wmin, wmax ;
00093 double disp_min, disp_max, disp ;
00094 int nlines_cat, nlines ;
00095 const double * plines_catalog_x ;
00096 const double * plines_catalog_y ;
00097 cpl_bivector * matched ;
00098 double * pmatched ;
00099 cpl_polynomial * fitted ;
00100 cpl_table * spc_table ;
00101 cpl_vector ** vectors_plot ;
00102 cpl_vector * plot_cat_x ;
00103 cpl_vector * plot_cat_y ;
00104 cpl_vector * plot_y ;
00105 int wl_ind, start_ind, stop_ind ;
00106 int i ;
00107
00108
00109 if (spectrum == NULL) return NULL ;
00110 if (lines_catalog == NULL) return NULL ;
00111 if (poly_init == NULL) return NULL ;
00112
00113
00114 spec_sz = cpl_vector_get_size(spectrum) ;
00115
00116
00117 if ((spec_conv = irplib_ppm_convolve_line(spectrum, slitw, fwhm)) == NULL) {
00118 cpl_msg_error(cpl_func, "Cannot convolve the signal") ;
00119 return NULL ;
00120 }
00121
00122
00123 if (doplot) {
00124 irplib_vector_plot(
00125 "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00126 "t 'Spectrum' w lines", "", spectrum) ;
00127 irplib_vector_plot(
00128 "set grid;set xlabel 'Position (Pixel)';set ylabel 'Correlation';",
00129 "t 'Spectrum convolved with the line profile' w lines", "", spec_conv) ;
00130 }
00131
00132
00133 if ((det_lines = irplib_ppm_detect_lines(spec_conv, thresh)) == NULL) {
00134 cpl_msg_error(cpl_func, "Cannot detect lines") ;
00135 cpl_vector_delete(spec_conv) ;
00136 return NULL ;
00137 }
00138 cpl_vector_delete(spec_conv) ;
00139
00140
00141 wmin = cpl_polynomial_eval_1d(poly_init, 1.0, NULL) ;
00142 wmax = cpl_polynomial_eval_1d(poly_init, spec_sz, NULL) ;
00143 plines_catalog_x = cpl_bivector_get_x_data_const(lines_catalog) ;
00144 plines_catalog_y = cpl_bivector_get_y_data_const(lines_catalog) ;
00145 nlines = cpl_bivector_get_size(lines_catalog) ;
00146 nlines_cat = 0 ;
00147 start_ind = stop_ind = -1 ;
00148 for (i=0 ; i<nlines ; i++) {
00149 if (plines_catalog_x[i] > wmin && plines_catalog_x[i] < wmax &&
00150 plines_catalog_y[i] > 0.0) {
00151 nlines_cat++ ;
00152 if (start_ind<0) start_ind = i ;
00153 stop_ind = i ;
00154 }
00155 }
00156 if (nlines_cat == 0) {
00157 cpl_msg_error(cpl_func, "No lines in catalog") ;
00158 cpl_vector_delete(det_lines) ;
00159 return NULL ;
00160 }
00161 cat_lines = cpl_vector_new(nlines_cat) ;
00162 pcat_lines = cpl_vector_get_data(cat_lines) ;
00163 nlines_cat = 0 ;
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 pcat_lines[nlines_cat] = plines_catalog_x[i] ;
00168 nlines_cat++ ;
00169 }
00170 }
00171
00172
00173 disp = (wmax-wmin) / spec_sz ;
00174 disp_min = disp - (disp/10) ;
00175 disp_max = disp + (disp/10) ;
00176 if ((matched = cpl_ppm_match_positions(det_lines, cat_lines,
00177 disp_min, disp_max, 0.05, NULL, NULL)) == NULL) {
00178 cpl_msg_error(cpl_func, "Cannot apply the point pattern matching") ;
00179 cpl_vector_delete(det_lines) ;
00180 cpl_vector_delete(cat_lines) ;
00181 return NULL ;
00182 }
00183 cpl_vector_delete(det_lines) ;
00184 cpl_vector_delete(cat_lines) ;
00185 if (cpl_bivector_get_size(matched) <= degree) {
00186 cpl_msg_error(cpl_func, "Not enough match for the fit") ;
00187 cpl_bivector_delete(matched) ;
00188 return NULL ;
00189 }
00190 cpl_msg_info(cpl_func, "Matched %d lines", cpl_bivector_get_size(matched)) ;
00191
00192
00193 if (doplot) {
00194
00195 plot_y = cpl_vector_duplicate(spectrum) ;
00196 cpl_vector_fill(plot_y, 0.0) ;
00197 pmatched = cpl_bivector_get_x_data(matched) ;
00198 for (i=0 ; i<cpl_bivector_get_size(matched) ; i++) {
00199 cpl_vector_set(plot_y, (int)pmatched[i], 10.0) ;
00200 }
00201 vectors_plot = cpl_malloc(3*sizeof(cpl_vector*)) ;
00202 vectors_plot[0] = NULL ;
00203 vectors_plot[1] = (cpl_vector*)spectrum ;
00204 vectors_plot[2] = plot_y ;
00205 irplib_vectors_plot(
00206 "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00207 "t 'Spectrum with matched lines' w lines", "",
00208 (const cpl_vector **)vectors_plot, 3) ;
00209 cpl_vector_delete(plot_y) ;
00210
00211
00212 plot_cat_x=cpl_vector_extract(cpl_bivector_get_x_const(lines_catalog),
00213 start_ind, stop_ind, 1) ;
00214 plot_cat_y=cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog),
00215 start_ind, stop_ind, 1) ;
00216 vectors_plot[0] = plot_cat_x ;
00217 vectors_plot[1] = plot_cat_y ;
00218 plot_y = cpl_vector_duplicate(vectors_plot[1]) ;
00219 cpl_vector_fill(plot_y, 0.0) ;
00220 pmatched = cpl_bivector_get_y_data(matched) ;
00221 for (i=0 ; i<cpl_bivector_get_size(matched) ; i++) {
00222 wl_ind = 0 ;
00223 while (pmatched[i] > cpl_vector_get(vectors_plot[0], wl_ind)
00224 && wl_ind < spec_sz) wl_ind++ ;
00225 if (wl_ind < spec_sz) cpl_vector_set(plot_y, wl_ind, 100.0) ;
00226 }
00227 vectors_plot[2] = plot_y ;
00228 irplib_vectors_plot(
00229 "set grid;set xlabel 'Position (Pixel)';set ylabel 'Intensity (ADU/sec)';",
00230 "t 'Catalog with matched lines' w lines", "",
00231 (const cpl_vector **)vectors_plot, 3) ;
00232 cpl_vector_delete(plot_cat_x) ;
00233 cpl_vector_delete(plot_cat_y) ;
00234 cpl_vector_delete(plot_y) ;
00235 cpl_free(vectors_plot) ;
00236 }
00237
00238
00239 if ((fitted=cpl_polynomial_fit_1d_create(
00240 cpl_bivector_get_x(matched),
00241 cpl_bivector_get_y(matched),
00242 degree, NULL)) == NULL) {
00243 cpl_msg_error(cpl_func, "Cannot fit the polynomial") ;
00244 cpl_bivector_delete(matched) ;
00245 return NULL ;
00246 }
00247 cpl_bivector_delete(matched) ;
00248
00249
00250 if ((spc_table = cpl_wlcalib_xc_gen_spc_table(spectrum,
00251 lines_catalog, slitw, fwhm, poly_init, fitted)) == NULL) {
00252 cpl_msg_error(cpl_func, "Cannot generate the infos table") ;
00253 cpl_polynomial_delete(fitted) ;
00254 return NULL ;
00255 }
00256
00257
00258 if (doplot) {
00259 irplib_wlxcorr_plot_spc_table(spc_table, "PPM") ;
00260 }
00261
00262 if (tab_infos != NULL) *tab_infos = spc_table ;
00263 else cpl_table_delete(spc_table) ;
00264 return fitted ;
00265 }
00266
00269
00280
00281 static cpl_vector * irplib_ppm_convolve_line(
00282 const cpl_vector * spectrum,
00283 double slitw,
00284 double fwhm)
00285 {
00286 cpl_vector * conv_kernel ;
00287 cpl_vector * line_profile ;
00288 cpl_vector * xcorrs ;
00289 cpl_vector * spec_ext ;
00290 cpl_vector * xc_single ;
00291 int hs, line_sz, sp_sz ;
00292 int i ;
00293
00294
00295 if (spectrum == NULL) return NULL ;
00296
00297
00298 if ((conv_kernel = cpl_wlcalib_xc_convolve_create_kernel(slitw,
00299 fwhm)) == NULL) {
00300 cpl_msg_error(cpl_func, "Cannot create kernel") ;
00301 return NULL ;
00302 }
00303 hs = cpl_vector_get_size(conv_kernel) ;
00304 line_sz = 2 * hs + 1 ;
00305
00306
00307 line_profile = cpl_vector_new(line_sz) ;
00308 cpl_vector_fill(line_profile, 0.0) ;
00309 cpl_vector_set(line_profile, hs, 1.0) ;
00310 if (cpl_wlcalib_xc_convolve(line_profile, conv_kernel) != 0) {
00311 cpl_msg_error(cpl_func, "Cannot create line profile") ;
00312 cpl_vector_delete(line_profile) ;
00313 cpl_vector_delete(conv_kernel) ;
00314 return NULL ;
00315 }
00316 cpl_vector_delete(conv_kernel) ;
00317
00318
00319 sp_sz = cpl_vector_get_size(spectrum) ;
00320 xcorrs = cpl_vector_new(sp_sz) ;
00321 cpl_vector_fill(xcorrs, 0.0) ;
00322 xc_single = cpl_vector_new(1) ;
00323
00324
00325 for (i=hs ; i<sp_sz-hs ; i++) {
00326
00327 if ((spec_ext = cpl_vector_extract(spectrum, i-hs, i+hs, 1)) == NULL) {
00328 cpl_msg_error(cpl_func, "Cannot extract spectrum") ;
00329 cpl_vector_delete(xc_single) ;
00330 cpl_vector_delete(line_profile) ;
00331 return NULL ;
00332 }
00333 if (cpl_vector_correlate(xc_single, spec_ext, line_profile) < 0) {
00334 cpl_msg_error(cpl_func, "Cannot correlate") ;
00335 cpl_vector_delete(xc_single) ;
00336 cpl_vector_delete(line_profile) ;
00337 cpl_vector_delete(spec_ext) ;
00338 return NULL ;
00339 }
00340 cpl_vector_set(xcorrs, i, cpl_vector_get(xc_single, 0)) ;
00341 cpl_vector_delete(spec_ext) ;
00342 }
00343 cpl_vector_delete(xc_single) ;
00344 cpl_vector_delete(line_profile) ;
00345
00346 return xcorrs ;
00347 }
00348
00349
00358
00359 static cpl_vector * irplib_ppm_detect_lines(
00360 const cpl_vector * spec,
00361 double threshold)
00362 {
00363 cpl_vector * spec_loc ;
00364 double * pspec_loc ;
00365 cpl_vector * lines ;
00366 double * plines ;
00367 int spec_loc_sz, max_ind, nlines ;
00368 double max ;
00369 int i ;
00370
00371
00372 if (spec == NULL) return NULL ;
00373 if (threshold<0.0 || threshold > 1.0) return NULL ;
00374
00375
00376 spec_loc = cpl_vector_duplicate(spec) ;
00377 pspec_loc = cpl_vector_get_data(spec_loc) ;
00378 spec_loc_sz = cpl_vector_get_size(spec_loc) ;
00379
00380
00381 for (i=0 ; i<spec_loc_sz ; i++)
00382 if (pspec_loc[i] < threshold) pspec_loc[i] = 0.0 ;
00383
00384
00385 lines = cpl_vector_new(spec_loc_sz) ;
00386 plines = cpl_vector_get_data(lines) ;
00387 nlines = 0 ;
00388
00389
00390 while ((max = cpl_vector_get_max(spec_loc)) > threshold) {
00391
00392 max_ind = 0 ;
00393 while (pspec_loc[max_ind]<max && max_ind<spec_loc_sz) max_ind++ ;
00394 if (max_ind == spec_loc_sz) {
00395 cpl_msg_error(cpl_func, "Cannot find maximum") ;
00396 cpl_vector_delete(spec_loc) ;
00397 cpl_vector_delete(lines) ;
00398 return NULL ;
00399 }
00400 if (max_ind == 0 || max_ind == spec_loc_sz-1) {
00401 pspec_loc[max_ind] = 0 ;
00402 continue ;
00403 }
00404
00405
00406 plines[nlines] = pspec_loc[max_ind] * max_ind +
00407 pspec_loc[max_ind-1] * (max_ind-1) +
00408 pspec_loc[max_ind+1] * (max_ind+1) ;
00409 plines[nlines] /= pspec_loc[max_ind] + pspec_loc[max_ind+1] +
00410 pspec_loc[max_ind-1] ;
00411 plines[nlines] ++ ;
00412 nlines ++ ;
00413
00414
00415 i = max_ind ;
00416 while (i>=0 && pspec_loc[i] > threshold) {
00417 pspec_loc[i] = 0.0 ;
00418 i-- ;
00419 }
00420 i = max_ind+1 ;
00421 while (i<spec_loc_sz && pspec_loc[i] > threshold) {
00422 pspec_loc[i] = 0.0 ;
00423 i++ ;
00424 }
00425 }
00426 cpl_vector_delete(spec_loc) ;
00427
00428
00429 if (nlines == 0) {
00430 cpl_msg_error(cpl_func, "Cannot detect any line") ;
00431 cpl_vector_delete(lines) ;
00432 return NULL ;
00433 }
00434
00435
00436 cpl_vector_set_size(lines, nlines) ;
00437
00438
00439 cpl_vector_sort(lines, 1) ;
00440
00441 return lines ;
00442 }
00443
00444
00445
00446