41 #include "irplib_wavecal_impl.h"
43 #include "irplib_wlxcorr.h"
62 #ifndef CPL_SIZE_FORMAT
63 #define CPL_SIZE_FORMAT "d"
72 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
73 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
75 #define IRPLIB_PTR_SWAP(a,b) \
76 do { void * irplib_ptr_swap =(a);(a)=(b);(b)=irplib_ptr_swap; } while (0)
82 static void irplib_wlxcorr_estimate(cpl_vector *, cpl_vector *,
86 const cpl_polynomial *,
89 static int irplib_wlxcorr_signal_resample(cpl_vector *,
const cpl_vector *,
90 const cpl_bivector *) ;
91 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector *,
93 static cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector *,
96 const cpl_polynomial *,
int);
98 static cpl_boolean irplib_wlcalib_is_lines(
const cpl_vector *,
99 const cpl_polynomial *,
142 cpl_polynomial * irplib_wlxcorr_best_poly(
const cpl_vector * spectrum,
143 const cpl_bivector * lines_catalog,
145 const cpl_polynomial * guess_poly,
146 const cpl_vector * wl_error,
152 cpl_vector ** xcorrs)
154 const int spec_sz = cpl_vector_get_size(spectrum);
155 const int nfree = cpl_vector_get_size(wl_error);
159 cpl_vector * init_pts_wl;
160 cpl_matrix * init_pts_x;
162 cpl_vector * vxcorrs;
163 cpl_vector * conv_kernel = NULL;
164 cpl_polynomial * poly_sol;
165 cpl_polynomial * poly_candi;
166 const double * pwl_error = cpl_vector_get_data_const(wl_error);
168 cpl_size degree_loc ;
169 const cpl_boolean symsamp = CPL_TRUE;
170 const cpl_boolean is_lines
171 = irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
172 guess_poly, spec_sz, 1.0);
178 if (wlres != NULL) *wlres = NULL;
179 if (xcorrs != NULL) *xcorrs = NULL;
182 cpl_msg_debug(cpl_func,
"Checking %d^%d dispersion polynomials (slitw=%g, "
183 "fwhm=%g) against %d-point observed spectrum with%s "
184 "catalog resampling", nsamples, nfree, slitw, fwhm, spec_sz,
185 is_lines ?
"out" :
"");
187 cpl_ensure(xc != NULL, CPL_ERROR_NULL_INPUT, NULL);
189 cpl_ensure(spectrum != NULL, CPL_ERROR_NULL_INPUT, NULL);
190 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
191 cpl_ensure(guess_poly != NULL, CPL_ERROR_NULL_INPUT, NULL);
192 cpl_ensure(wl_error != NULL, CPL_ERROR_NULL_INPUT, NULL);
193 cpl_ensure(nfree >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
194 cpl_ensure(nsamples > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
196 cpl_ensure(1 + degree == nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
198 cpl_ensure(cpl_polynomial_get_dimension(guess_poly) == 1,
199 CPL_ERROR_ILLEGAL_INPUT, NULL);
204 for (i = 0; i < nfree; i++) {
205 if (pwl_error[i] != 0.0)
break;
207 cpl_ensure(i < nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
212 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
213 cpl_ensure(conv_kernel != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
217 init_pts_x = cpl_matrix_new(1, nfree);
218 init_pts_wl = cpl_vector_new(nfree);
219 pts_wl = cpl_vector_new(nfree);
220 for (i = 0; i < nfree; i++) {
221 const double xpos = spec_sz * i / (double)degree;
222 const double wlpos = cpl_polynomial_eval_1d(guess_poly, xpos, NULL)
223 - 0.5 * pwl_error[i];
225 cpl_matrix_set(init_pts_x, 0, i, xpos);
226 cpl_vector_set(init_pts_wl, i, wlpos);
232 vxcorrs = xcorrs != NULL ? cpl_vector_new(ntests) : NULL;
234 poly_sol = cpl_polynomial_new(1);
235 poly_candi = cpl_polynomial_new(1);
236 model = cpl_vector_new(spec_sz);
237 vxc = cpl_vector_new(1);
238 dxc = cpl_vector_get_data_const(vxc);
241 for (i=0; i < ntests; i++) {
247 for (deg = degree; deg >= 0; deg--, idiv /= nsamples) {
248 const int imod = idiv % nsamples;
249 const double wlpos = cpl_vector_get(init_pts_wl, deg)
250 + imod * pwl_error[deg] / nsamples;
255 cpl_vector_set(pts_wl, deg, wlpos);
261 degree_loc = (cpl_size)degree ;
262 cpl_polynomial_fit(poly_candi, init_pts_x, &symsamp, pts_wl,
263 NULL, CPL_FALSE, NULL, °ree_loc);
265 irplib_wlxcorr_estimate(vxc, model, spectrum, lines_catalog,
266 conv_kernel, poly_candi, slitw, fwhm);
267 if (vxcorrs != NULL) cpl_vector_set(vxcorrs, i, *dxc);
271 IRPLIB_PTR_SWAP(poly_sol, poly_candi);
275 cpl_vector_delete(model);
276 cpl_vector_delete(vxc);
277 cpl_vector_delete(conv_kernel);
278 cpl_vector_delete(pts_wl);
279 cpl_matrix_delete(init_pts_x);
280 cpl_vector_delete(init_pts_wl);
281 cpl_polynomial_delete(poly_candi);
283 #ifdef CPL_WLCALIB_FAIL_ON_CONSTANT
285 if (cpl_polynomial_get_degree(poly_sol) == 0) {
286 cpl_polynomial_delete(poly_sol);
287 cpl_vector_delete(vxcorrs);
289 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
290 __FILE__, __LINE__,
"Found a constant "
292 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
301 cpl_errorstate prestate = cpl_errorstate_get();
303 *wlres = irplib_wlxcorr_gen_spc_table(spectrum, lines_catalog, slitw,
304 fwhm, guess_poly, poly_sol);
305 if (*wlres == NULL) {
306 cpl_polynomial_delete(poly_sol);
307 cpl_vector_delete(vxcorrs);
309 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
310 __FILE__, __LINE__,
"Cannot generate "
313 cpl_errorstate_set(prestate);
318 if (xcorrs != NULL) {
346 cpl_table * irplib_wlxcorr_gen_spc_table(
347 const cpl_vector * spectrum,
348 const cpl_bivector * lines_catalog,
351 const cpl_polynomial * guess_poly,
352 const cpl_polynomial * corr_poly)
355 cpl_vector * conv_kernel = NULL;
356 cpl_bivector * gen_init ;
357 cpl_bivector * gen_corr ;
358 cpl_table * spc_table ;
359 const double * pgen ;
360 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
361 const int spec_sz = cpl_vector_get_size(spectrum);
362 const cpl_boolean guess_resamp
363 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
364 guess_poly, spec_sz, 1.0);
365 const cpl_boolean corr_resamp
366 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
367 corr_poly, spec_sz, 1.0);
368 cpl_error_code error;
370 cpl_msg_debug(cpl_func,
"Tabel for guess dispersion polynomial (slitw=%g, "
371 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
372 "sampling", slitw, fwhm, spec_sz, guess_resamp ?
"out" :
"");
373 cpl_msg_debug(cpl_func,
"Tabel for corr. dispersion polynomial (slitw=%g, "
374 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
375 "sampling", slitw, fwhm, spec_sz, corr_resamp ?
"out" :
"");
378 cpl_ensure(spectrum, CPL_ERROR_NULL_INPUT, NULL) ;
379 cpl_ensure(lines_catalog, CPL_ERROR_NULL_INPUT, NULL) ;
380 cpl_ensure(guess_poly, CPL_ERROR_NULL_INPUT, NULL) ;
381 cpl_ensure(corr_poly, CPL_ERROR_NULL_INPUT, NULL) ;
384 if (guess_resamp || corr_resamp) {
385 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
387 if (conv_kernel == NULL) {
388 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
389 __FILE__, __LINE__,
"Cannot create "
390 "convolution kernel") ;
396 gen_init = cpl_bivector_new(spec_sz);
398 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_init),
399 lines_catalog, conv_kernel,
403 (cpl_bivector_get_y(gen_init), NULL, NULL,
404 guess_poly, lines_catalog,
405 slitw, fwhm, xtrunc, 0, CPL_FALSE, CPL_FALSE, NULL);
408 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_init),
410 cpl_vector_delete(conv_kernel);
411 cpl_bivector_delete(gen_init);
412 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
413 __FILE__, __LINE__,
"Cannot get the "
414 "emission spectrum");
419 gen_corr = cpl_bivector_new(spec_sz);
421 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_corr),
422 lines_catalog, conv_kernel,
426 (cpl_bivector_get_y(gen_corr), NULL, NULL,
427 corr_poly, lines_catalog,
428 slitw, fwhm, xtrunc, 0, CPL_FALSE, CPL_FALSE, NULL);
431 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_corr),
433 cpl_vector_delete(conv_kernel);
434 cpl_bivector_delete(gen_init);
435 cpl_bivector_delete(gen_corr) ;
436 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
437 __FILE__, __LINE__,
"Cannot get the "
438 "emission spectrum");
441 cpl_vector_delete(conv_kernel) ;
444 spc_table = cpl_table_new(spec_sz);
445 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH,
447 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT,
449 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL,
451 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_OBS, CPL_TYPE_DOUBLE);
454 pgen = cpl_bivector_get_x_data_const(gen_corr) ;
455 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH, pgen) ;
456 pgen = cpl_bivector_get_y_data_const(gen_corr) ;
457 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL, pgen) ;
458 pgen = cpl_vector_get_data_const(spectrum) ;
459 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_OBS, pgen) ;
460 pgen = cpl_bivector_get_y_data_const(gen_init) ;
461 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT, pgen);
462 cpl_bivector_delete(gen_init);
463 cpl_bivector_delete(gen_corr);
481 cpl_bivector * irplib_wlxcorr_cat_extract(
482 const cpl_bivector * lines_catalog,
486 const int nlines = cpl_bivector_get_size(lines_catalog);
487 int wave_min_id, wave_max_id ;
488 cpl_vector * sub_cat_wl ;
489 cpl_vector * sub_cat_int ;
490 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
491 const double * dxlines = cpl_vector_get_data_const(xlines);
493 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
496 wave_min_id = (int)cpl_vector_find(xlines, wave_min);
497 if (wave_min_id < 0) {
498 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
500 "The starting wavelength cannot be found") ;
505 if (dxlines[wave_min_id] <= wave_min) wave_min_id++;
508 wave_max_id = (int)cpl_vector_find(xlines, wave_max);
509 if (wave_max_id < 0) {
510 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
512 "The ending wavelength cannot be found") ;
516 if (dxlines[wave_max_id] >= wave_min) wave_max_id--;
520 cpl_ensure(wave_min_id <= wave_max_id, CPL_ERROR_ILLEGAL_INPUT, NULL);
522 if (wave_min_id < 0 || wave_max_id == nlines) {
523 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
524 __FILE__, __LINE__,
"The %d-line catalogue "
525 "has no lines in the range %g -> %g",
526 nlines, wave_min, wave_max);
530 sub_cat_wl = cpl_vector_extract(xlines, wave_min_id, wave_max_id, 1);
531 sub_cat_int = cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog),
532 wave_min_id, wave_max_id, 1);
534 return cpl_bivector_wrap_vectors(sub_cat_wl, sub_cat_int);
555 cpl_vector * irplib_wlxcorr_convolve_create_kernel(
double slitw,
558 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
559 const int size = 1 + (int)(5.0 * sigma + 0.5*slitw);
560 cpl_vector * kernel = cpl_vector_new(size);
563 if (cpl_vector_fill_lss_profile_symmetric(kernel, slitw, fwhm)) {
564 cpl_vector_delete(kernel);
565 cpl_ensure(0, cpl_error_get_code(), NULL);
585 int irplib_wlxcorr_convolve(
586 cpl_vector * smoothed,
587 const cpl_vector * conv_kernel)
594 const double* psymm ;
598 cpl_ensure(smoothed, CPL_ERROR_NULL_INPUT, -1) ;
599 cpl_ensure(conv_kernel, CPL_ERROR_NULL_INPUT, -1) ;
602 nsamples = cpl_vector_get_size(smoothed) ;
603 ihwidth = cpl_vector_get_size(conv_kernel) - 1 ;
604 cpl_ensure(ihwidth<nsamples, CPL_ERROR_ILLEGAL_INPUT, -1) ;
605 psymm = cpl_vector_get_data_const(conv_kernel) ;
606 psmoothe = cpl_vector_get_data(smoothed) ;
609 raw = cpl_vector_duplicate(smoothed) ;
610 praw = cpl_vector_get_data(raw) ;
613 for (i=0 ; i<ihwidth ; i++) {
614 psmoothe[i] = praw[i] * psymm[0];
615 for (j=1 ; j <= ihwidth ; j++) {
616 const int k = i-j < 0 ? 0 : i-j;
617 psmoothe[i] += (praw[k]+praw[i+j]) * psymm[j];
621 for (i=ihwidth ; i<nsamples-ihwidth ; i++) {
622 psmoothe[i] = praw[i] * psymm[0];
623 for (j=1 ; j<=ihwidth ; j++)
624 psmoothe[i] += (praw[i-j]+praw[i+j]) * psymm[j];
626 for (i=nsamples-ihwidth ; i<nsamples ; i++) {
627 psmoothe[i] = praw[i] * psymm[0];
628 for (j=1 ; j<=ihwidth ; j++) {
629 const int k = i+j > nsamples-1 ? nsamples - 1 : i+j;
630 psmoothe[i] += (praw[k]+praw[i-j]) * psymm[j];
633 cpl_vector_delete(raw) ;
648 int irplib_wlxcorr_plot_solution(
649 const cpl_polynomial * init,
650 const cpl_polynomial * comp,
651 const cpl_polynomial * sol,
655 int nsamples, nplots ;
656 cpl_vector ** vectors ;
657 cpl_bivector * bivector ;
662 if (init == NULL || comp == NULL)
return -1 ;
665 nsamples = pix_stop - pix_start + 1 ;
666 if (sol != NULL) nplots = 3 ;
670 vectors = cpl_malloc((nplots+1)*
sizeof(cpl_vector*)) ;
671 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
675 for (i=0 ; i<nsamples ; i++) {
676 cpl_vector_set(vectors[0], i, pix_start+i) ;
677 cpl_vector_set(vectors[1], i,
678 cpl_polynomial_eval_1d(init, (
double)(pix_start+i), NULL)) ;
679 cpl_vector_set(vectors[2], i,
680 cpl_polynomial_eval_1d(comp, (
double)(pix_start+i), NULL)) ;
682 cpl_vector_set(vectors[3], i,
683 cpl_polynomial_eval_1d(sol, (
double)(pix_start+i), NULL)) ;
687 cpl_plot_vectors(
"set grid;set xlabel 'Position (pixels)';",
688 "t '1-Initial / 2-Computed / 3-Solution' w lines",
689 "", (
const cpl_vector **)vectors, nplots+1);
692 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
697 vectors = cpl_malloc((nplots+1)*
sizeof(cpl_vector*)) ;
698 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
702 for (i=0 ; i<nsamples ; i++) {
703 cpl_vector_set(vectors[0], i, pix_start+i) ;
704 diff = cpl_polynomial_eval_1d(comp, (
double)(pix_start+i), NULL) -
705 cpl_polynomial_eval_1d(init, (
double)(pix_start+i), NULL) ;
706 cpl_vector_set(vectors[1], i, diff) ;
708 diff = cpl_polynomial_eval_1d(sol, (
double)(pix_start+i), NULL) -
709 cpl_polynomial_eval_1d(init, (
double)(pix_start+i), NULL) ;
710 cpl_vector_set(vectors[2], i, diff) ;
716 bivector = cpl_bivector_wrap_vectors(vectors[0], vectors[1]) ;
718 "set grid;set xlabel 'Position (pixels)';set ylabel 'Wavelength difference';",
719 "t 'Computed-Initial wavelenth' w lines",
"", bivector);
720 cpl_bivector_unwrap_vectors(bivector) ;
722 cpl_plot_vectors(
"set grid;set xlabel 'Position (pixels)';",
723 "t '1-Computed - Initial / 2--Solution - Initial' w lines",
724 "", (
const cpl_vector **)vectors, nplots+1);
728 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
747 int irplib_wlxcorr_plot_spc_table(
748 const cpl_table * spc_table,
750 int first_plotted_line,
751 int last_plotted_line)
753 char title_loc[1024] ;
754 cpl_vector ** vectors ;
755 cpl_vector ** sub_vectors ;
756 cpl_vector * tmp_vec ;
758 double max, mean1, mean3 ;
759 int start_ind, stop_ind, hsize_pix ;
763 if (first_plotted_line > last_plotted_line)
return -1 ;
764 if (spc_table == NULL)
return -1 ;
767 nsamples = cpl_table_get_nrow(spc_table) ;
771 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed' w lines",
773 title_loc[1023] = (char)0 ;
775 vectors = cpl_malloc(4*
sizeof(cpl_vector*)) ;
776 vectors[0] = cpl_vector_wrap(nsamples,
777 cpl_table_get_data_double((cpl_table*)spc_table,
778 IRPLIB_WLXCORR_COL_WAVELENGTH));
779 vectors[1] = cpl_vector_wrap(nsamples,
780 cpl_table_get_data_double((cpl_table*)spc_table,
781 IRPLIB_WLXCORR_COL_CAT_INIT));
782 vectors[2] = cpl_vector_wrap(nsamples,
783 cpl_table_get_data_double((cpl_table*)spc_table,
784 IRPLIB_WLXCORR_COL_CAT_FINAL));
785 vectors[3] = cpl_vector_wrap(nsamples,
786 cpl_table_get_data_double((cpl_table*)spc_table,
787 IRPLIB_WLXCORR_COL_OBS)) ;
790 mean1 = cpl_vector_get_mean(vectors[1]) ;
791 mean3 = cpl_vector_get_mean(vectors[3]) ;
793 cpl_vector_multiply_scalar(vectors[3], fabs(mean1/mean3)) ;
795 cpl_plot_vectors(
"set grid;set xlabel 'Wavelength (nm)';", title_loc,
796 "", (
const cpl_vector **)vectors, 4);
800 cpl_vector_multiply_scalar(vectors[3], mean3/mean1) ;
804 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed (ZOOMED)' w lines",
806 title_loc[1023] = (char)0 ;
807 tmp_vec = cpl_vector_duplicate(vectors[2]) ;
808 for (i=0 ; i<last_plotted_line ; i++) {
810 if ((max = cpl_vector_get_max(tmp_vec)) <= 0.0) break ;
811 for (j=0 ; j<nsamples ; j++) {
812 if (cpl_vector_get(tmp_vec, j) == max) break ;
814 if (j-hsize_pix < 0) start_ind = 0 ;
815 else start_ind = j-hsize_pix ;
816 if (j+hsize_pix > nsamples-1) stop_ind = nsamples-1 ;
817 else stop_ind = j+hsize_pix ;
818 for (j=start_ind ; j<=stop_ind ; j++) cpl_vector_set(tmp_vec, j, 0.0) ;
820 if (i+1 >= first_plotted_line) {
821 sub_vectors = cpl_malloc(4*
sizeof(cpl_vector*)) ;
822 sub_vectors[0]=cpl_vector_extract(vectors[0],start_ind,stop_ind,1);
823 sub_vectors[1]=cpl_vector_extract(vectors[1],start_ind,stop_ind,1);
824 sub_vectors[2]=cpl_vector_extract(vectors[2],start_ind,stop_ind,1);
825 sub_vectors[3]=cpl_vector_extract(vectors[3],start_ind,stop_ind,1);
827 cpl_plot_vectors(
"set grid;set xlabel 'Wavelength (nm)';",
828 title_loc,
"", (
const cpl_vector **)sub_vectors, 4);
830 cpl_vector_delete(sub_vectors[0]) ;
831 cpl_vector_delete(sub_vectors[1]) ;
832 cpl_vector_delete(sub_vectors[2]) ;
833 cpl_vector_delete(sub_vectors[3]) ;
834 cpl_free(sub_vectors) ;
837 cpl_vector_delete(tmp_vec) ;
839 cpl_vector_unwrap(vectors[0]) ;
840 cpl_vector_unwrap(vectors[1]) ;
841 cpl_vector_unwrap(vectors[2]) ;
842 cpl_vector_unwrap(vectors[3]) ;
857 int irplib_wlxcorr_catalog_plot(
858 const cpl_bivector * cat,
863 cpl_bivector * subcat ;
864 cpl_vector * subcat_x ;
865 cpl_vector * subcat_y ;
866 const double * pwave ;
867 int nvals, nvals_tot ;
871 if (cat == NULL)
return -1 ;
872 if (wmax <= wmin)
return -1 ;
875 nvals_tot = cpl_bivector_get_size(cat) ;
878 pwave = cpl_bivector_get_x_data_const(cat) ;
879 if (pwave[0] >= wmin) start = 0 ;
881 if (pwave[nvals_tot-1] <= wmax) stop = nvals_tot-1 ;
884 while ((pwave[i] < wmin) && (i<nvals_tot-1)) i++ ;
887 while ((pwave[i] > wmax) && (i>0)) i-- ;
891 cpl_msg_error(cpl_func,
"Cannot plot the catalog") ;
894 nvals = start - stop + 1 ;
897 subcat_x = cpl_vector_extract(cpl_bivector_get_x_const(cat),start,stop, 1) ;
898 subcat_y = cpl_vector_extract(cpl_bivector_get_y_const(cat),start,stop, 1) ;
899 subcat = cpl_bivector_wrap_vectors(subcat_x, subcat_y) ;
904 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
905 "t 'Catalog Spectrum' w lines",
"", subcat);
908 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
909 "t 'Catalog Spectrum' w impulses",
"", subcat);
911 cpl_bivector_unwrap_vectors(subcat) ;
912 cpl_vector_delete(subcat_x) ;
913 cpl_vector_delete(subcat_y) ;
936 static void irplib_wlxcorr_estimate(cpl_vector * vxc,
938 const cpl_vector * spectrum,
939 const cpl_bivector * lines_catalog,
940 const cpl_vector * conv_kernel,
941 const cpl_polynomial * poly_candi,
945 cpl_errorstate prestate = cpl_errorstate_get();
946 const int hsize = cpl_vector_get_size(vxc) / 2;
948 if (conv_kernel != NULL) {
949 irplib_wlcalib_fill_spectrum(model, lines_catalog, conv_kernel,
952 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
955 lines_catalog, slitw, fwhm,
956 xtrunc, 0, CPL_FALSE, CPL_FALSE,
960 if (cpl_errorstate_is_equal(prestate))
961 cpl_vector_correlate(vxc, model, spectrum);
963 if (!cpl_errorstate_is_equal(prestate)) {
964 cpl_vector_fill(vxc, 0.0);
967 cpl_errorstate_set(prestate);
986 static cpl_boolean irplib_wlcalib_is_lines(
const cpl_vector * wavelengths,
987 const cpl_polynomial * disp1d,
991 const int nlines = cpl_vector_get_size(wavelengths);
993 const double dispersion = cpl_polynomial_eval_1d_diff(disp1d,
997 const double range = cpl_vector_get(wavelengths, nlines-1)
998 - cpl_vector_get(wavelengths, 0);
1000 cpl_ensure(wavelengths != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
1001 cpl_ensure(disp1d != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
1002 cpl_ensure(cpl_polynomial_get_dimension(disp1d) == 1,
1003 CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1004 cpl_ensure(range > 0.0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1006 return nlines * fabs(dispersion) <= tol * fabs(range) ? CPL_TRUE
1028 cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector *
self,
1029 const cpl_bivector * lines_catalog,
1030 const cpl_vector * conv_kernel,
1031 const cpl_polynomial * poly,
1036 const int size = cpl_vector_get_size(
self);
1037 const int nlines = cpl_bivector_get_size(lines_catalog);
1038 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
1039 const double * dxlines = cpl_vector_get_data_const(xlines);
1040 cpl_bivector * sub_cat ;
1041 cpl_vector * sub_cat_x;
1042 cpl_vector * sub_cat_y;
1043 cpl_vector * wl_limits;
1044 double wave_min, wave_max;
1045 int wave_min_id, wave_max_id;
1049 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1050 cpl_ensure_code(lines_catalog != NULL, CPL_ERROR_NULL_INPUT);
1051 cpl_ensure_code(conv_kernel != NULL, CPL_ERROR_NULL_INPUT);
1052 cpl_ensure_code(poly != NULL, CPL_ERROR_NULL_INPUT);
1053 cpl_ensure_code(size > 0, CPL_ERROR_ILLEGAL_INPUT);
1057 wl_limits = cpl_vector_new(size + 1);
1058 cpl_vector_fill_polynomial(wl_limits, poly, 0.5 - search_hs, 1);
1061 wave_min = cpl_vector_get(wl_limits, 0);
1062 wave_max = cpl_vector_get(wl_limits, size);
1065 wave_min_id = cpl_vector_find(xlines, wave_min);
1067 if (dxlines[wave_min_id] > wave_min) wave_min_id--;
1069 if (wave_min_id < 0) {
1070 cpl_vector_delete(wl_limits);
1071 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1072 __FILE__, __LINE__,
"The %d-line "
1073 "catalogue only has lines above %g",
1078 wave_max_id = cpl_vector_find(xlines, wave_max);
1080 if (dxlines[wave_max_id] < wave_max) wave_max_id++;
1082 if (wave_max_id == nlines) {
1083 cpl_vector_delete(wl_limits);
1084 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1085 __FILE__, __LINE__,
"The %d-line "
1086 "catalogue only has lines below %g",
1092 nsub = 1 + wave_max_id - wave_min_id;
1093 cpl_ensure_code(nsub > 1, CPL_ERROR_ILLEGAL_INPUT);
1097 sub_cat_x = cpl_vector_wrap(nsub, wave_min_id + (
double*)dxlines);
1098 sub_cat_y = cpl_vector_wrap(nsub, wave_min_id + (
double*)
1099 cpl_bivector_get_y_data_const(lines_catalog));
1100 sub_cat = cpl_bivector_wrap_vectors(sub_cat_x, sub_cat_y);
1103 error = irplib_wlxcorr_signal_resample(
self, wl_limits, sub_cat);
1105 cpl_vector_delete(wl_limits);
1106 cpl_bivector_unwrap_vectors(sub_cat);
1107 (void)cpl_vector_unwrap(sub_cat_x);
1108 (void)cpl_vector_unwrap(sub_cat_y);
1110 cpl_ensure_code(!error, CPL_ERROR_ILLEGAL_INPUT);
1113 cpl_ensure_code(!irplib_wlxcorr_convolve(
self, conv_kernel),
1114 cpl_error_get_code());
1116 return CPL_ERROR_NONE;
1131 static int irplib_wlxcorr_signal_resample(
1132 cpl_vector * resampled,
1133 const cpl_vector * xbounds,
1134 const cpl_bivector * hires)
1136 const int hrsize = cpl_bivector_get_size(hires);
1137 const cpl_vector* xhires ;
1138 const cpl_vector* yhires ;
1139 const double * pxhires ;
1140 const double * pyhires ;
1141 const double * pxbounds ;
1142 cpl_vector * ybounds ;
1143 cpl_bivector * boundary ;
1145 double * presampled ;
1150 if ((!resampled) || (!xbounds) || (!hires))
return -1 ;
1153 nsamples = cpl_vector_get_size(resampled) ;
1156 presampled = cpl_vector_get_data(resampled) ;
1157 pxbounds = cpl_vector_get_data_const(xbounds) ;
1158 xhires = cpl_bivector_get_x_const(hires) ;
1159 yhires = cpl_bivector_get_y_const(hires) ;
1160 pxhires = cpl_vector_get_data_const(xhires) ;
1161 pyhires = cpl_vector_get_data_const(yhires) ;
1164 ybounds = cpl_vector_new(cpl_vector_get_size(xbounds)) ;
1165 boundary = cpl_bivector_wrap_vectors((cpl_vector*)xbounds,ybounds) ;
1166 pybounds = cpl_vector_get_data(ybounds) ;
1169 if (cpl_bivector_get_size(boundary) != nsamples + 1) {
1170 cpl_bivector_unwrap_vectors(boundary) ;
1171 cpl_vector_delete(ybounds) ;
1176 itt = cpl_vector_find(xhires, pxbounds[0]);
1179 if (cpl_bivector_interpolate_linear(boundary, hires)) {
1180 cpl_bivector_unwrap_vectors(boundary) ;
1181 cpl_vector_delete(ybounds) ;
1187 while (pxhires[itt] < pxbounds[0]) itt++;
1189 for (i=0; i < nsamples; i++) {
1194 double xlow = pxbounds[i];
1195 double x = pxhires[itt];
1197 if (x > pxbounds[i+1]) x = pxbounds[i+1];
1200 presampled[i] = pybounds[i] * (x - xlow);
1203 while ((pxhires[itt] < pxbounds[i+1]) && (itt < hrsize)) {
1204 const double xprev = x;
1206 if (x > pxbounds[i+1]) x = pxbounds[i+1];
1207 presampled[i] += pyhires[itt] * (x - xlow);
1214 presampled[i] += pybounds[i+1] * (pxbounds[i+1] - xlow);
1218 presampled[i] /= 2 * (pxbounds[i+1] - pxbounds[i]);
1220 cpl_bivector_unwrap_vectors(boundary) ;
1221 cpl_vector_delete(ybounds) ;
1249 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector *
self,
1254 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
1255 const int n = cpl_vector_get_size(
self);
1259 cpl_ensure_code(
self != NULL, CPL_ERROR_NULL_INPUT);
1260 cpl_ensure_code(slitw > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1261 cpl_ensure_code(fwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1266 (void)cpl_vector_set(
self, 0,
1270 for (i = 1; i < n; i++) {
1272 const double x1p = i + 0.5*slitw + 0.5;
1273 const double x1n = i - 0.5*slitw + 0.5;
1274 const double x0p = i + 0.5*slitw - 0.5;
1275 const double x0n = i - 0.5*slitw - 0.5;
1276 const double val = 0.5/slitw *
1279 (void)cpl_vector_set(
self, i, val);
1282 return CPL_ERROR_NONE;