00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024
00025
00026
00027
00028 #include "irplib_wavecal_impl.h"
00029
00030 #include "irplib_wlxcorr.h"
00031
00032 #include <cpl.h>
00033
00034 #include <math.h>
00035 #include <string.h>
00036
00037
00047
00048
00049
00050
00051
00052
00053 #ifndef inline
00054 #define inline
00055 #endif
00056
00057 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
00058 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
00059
00060 #define IRPLIB_PTR_SWAP(a,b) \
00061 do { void * irplib_ptr_swap =(a);(a)=(b);(b)=irplib_ptr_swap; } while (0)
00062
00063
00064
00065
00066
00067 static void irplib_wlxcorr_estimate(cpl_vector *, cpl_vector *,
00068 const cpl_vector *,
00069 const cpl_bivector *,
00070 const cpl_vector *,
00071 const cpl_polynomial *,
00072 double, double);
00073
00074 static int irplib_wlxcorr_signal_resample(cpl_vector *, const cpl_vector *,
00075 const cpl_bivector *) ;
00076 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector *,
00077 double, double);
00078 static cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector *,
00079 const cpl_bivector *,
00080 const cpl_vector *,
00081 const cpl_polynomial *, int);
00082
00083 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector *,
00084 const cpl_polynomial *,
00085 int, double);
00086
00090
00126
00127 cpl_polynomial * irplib_wlxcorr_best_poly(const cpl_vector * spectrum,
00128 const cpl_bivector * lines_catalog,
00129 int degree,
00130 const cpl_polynomial * guess_poly,
00131 const cpl_vector * wl_error,
00132 int nsamples,
00133 double slitw,
00134 double fwhm,
00135 double * xc,
00136 cpl_table ** wlres,
00137 cpl_vector ** xcorrs)
00138 {
00139 const int spec_sz = cpl_vector_get_size(spectrum);
00140 const int nfree = cpl_vector_get_size(wl_error);
00141 int ntests = 1;
00142 cpl_vector * model;
00143 cpl_vector * vxc;
00144 cpl_vector * init_pts_wl;
00145 cpl_matrix * init_pts_x;
00146 cpl_vector * pts_wl;
00147 cpl_vector * vxcorrs;
00148 cpl_vector * conv_kernel = NULL;
00149 cpl_polynomial * poly_sol;
00150 cpl_polynomial * poly_candi;
00151 const double * pwl_error = cpl_vector_get_data_const(wl_error);
00152 const double * dxc;
00153 cpl_size degree_loc ;
00154 const cpl_boolean symsamp = CPL_TRUE;
00155 const cpl_boolean is_lines
00156 = irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00157 guess_poly, spec_sz, 1.0);
00158 int i;
00159
00160
00161
00162
00163 if (wlres != NULL) *wlres = NULL;
00164 if (xcorrs != NULL) *xcorrs = NULL;
00165
00166
00167 cpl_msg_debug(cpl_func, "Checking %d^%d dispersion polynomials (slitw=%g, "
00168 "fwhm=%g) against %d-point observed spectrum with%s "
00169 "catalog resampling", nsamples, nfree, slitw, fwhm, spec_sz,
00170 is_lines ? "out" : "");
00171
00172 cpl_ensure(xc != NULL, CPL_ERROR_NULL_INPUT, NULL);
00173 *xc = -1.0;
00174 cpl_ensure(spectrum != NULL, CPL_ERROR_NULL_INPUT, NULL);
00175 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
00176 cpl_ensure(guess_poly != NULL, CPL_ERROR_NULL_INPUT, NULL);
00177 cpl_ensure(wl_error != NULL, CPL_ERROR_NULL_INPUT, NULL);
00178 cpl_ensure(nfree >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
00179 cpl_ensure(nsamples > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00180
00181 cpl_ensure(1 + degree == nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00182
00183 cpl_ensure(cpl_polynomial_get_dimension(guess_poly) == 1,
00184 CPL_ERROR_ILLEGAL_INPUT, NULL);
00185
00186 if (nsamples > 1) {
00187
00188
00189 for (i = 0; i < nfree; i++) {
00190 if (pwl_error[i] != 0.0) break;
00191 }
00192 cpl_ensure(i < nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00193 }
00194
00195 if (!is_lines) {
00196
00197 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00198 cpl_ensure(conv_kernel != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00199 }
00200
00201
00202 init_pts_x = cpl_matrix_new(1, nfree);
00203 init_pts_wl = cpl_vector_new(nfree);
00204 pts_wl = cpl_vector_new(nfree);
00205 for (i = 0; i < nfree; i++) {
00206 const double xpos = spec_sz * i / (double)degree;
00207 const double wlpos = cpl_polynomial_eval_1d(guess_poly, xpos, NULL)
00208 - 0.5 * pwl_error[i];
00209
00210 cpl_matrix_set(init_pts_x, 0, i, xpos);
00211 cpl_vector_set(init_pts_wl, i, wlpos);
00212
00213 ntests *= nsamples;
00214
00215 }
00216
00217 vxcorrs = xcorrs != NULL ? cpl_vector_new(ntests) : NULL;
00218
00219 poly_sol = cpl_polynomial_new(1);
00220 poly_candi = cpl_polynomial_new(1);
00221 model = cpl_vector_new(spec_sz);
00222 vxc = cpl_vector_new(1);
00223 dxc = cpl_vector_get_data_const(vxc);
00224
00225
00226 for (i=0; i < ntests; i++) {
00227 int idiv = i;
00228 int deg;
00229
00230
00231
00232 for (deg = degree; deg >= 0; deg--, idiv /= nsamples) {
00233 const int imod = idiv % nsamples;
00234 const double wlpos = cpl_vector_get(init_pts_wl, deg)
00235 + imod * pwl_error[deg] / nsamples;
00236
00237
00238
00239
00240 cpl_vector_set(pts_wl, deg, wlpos);
00241
00242 if (imod > 0) break;
00243 }
00244
00245
00246 degree_loc = (cpl_size)degree ;
00247 cpl_polynomial_fit(poly_candi, init_pts_x, &symsamp, pts_wl,
00248 NULL, CPL_FALSE, NULL, °ree_loc);
00249
00250 irplib_wlxcorr_estimate(vxc, model, spectrum, lines_catalog,
00251 conv_kernel, poly_candi, slitw, fwhm);
00252 if (vxcorrs != NULL) cpl_vector_set(vxcorrs, i, *dxc);
00253 if (*dxc > *xc) {
00254
00255 *xc = *dxc;
00256 IRPLIB_PTR_SWAP(poly_sol, poly_candi);
00257 }
00258 }
00259
00260 cpl_vector_delete(model);
00261 cpl_vector_delete(vxc);
00262 cpl_vector_delete(conv_kernel);
00263 cpl_vector_delete(pts_wl);
00264 cpl_matrix_delete(init_pts_x);
00265 cpl_vector_delete(init_pts_wl);
00266 cpl_polynomial_delete(poly_candi);
00267
00268 #ifdef CPL_WLCALIB_FAIL_ON_CONSTANT
00269
00270 if (cpl_polynomial_get_degree(poly_sol) == 0) {
00271 cpl_polynomial_delete(poly_sol);
00272 cpl_vector_delete(vxcorrs);
00273 *xc = 0.0;
00274 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00275 __FILE__, __LINE__, "Found a constant "
00276 "dispersion");
00277 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00278 return NULL;
00279 }
00280 #endif
00281
00282 if (wlres != NULL) {
00283
00284
00285
00286 cpl_errorstate prestate = cpl_errorstate_get();
00287
00288 *wlres = irplib_wlxcorr_gen_spc_table(spectrum, lines_catalog, slitw,
00289 fwhm, guess_poly, poly_sol);
00290 if (*wlres == NULL) {
00291 cpl_polynomial_delete(poly_sol);
00292 cpl_vector_delete(vxcorrs);
00293 *xc = -1.0;
00294 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00295 __FILE__, __LINE__, "Cannot generate "
00296 "infos table");
00297
00298 cpl_errorstate_set(prestate);
00299 return NULL;
00300 }
00301 }
00302
00303 if (xcorrs != NULL) {
00304 *xcorrs = vxcorrs;
00305 } else {
00306
00307 }
00308
00309 return poly_sol;
00310 }
00311
00312
00330
00331 cpl_table * irplib_wlxcorr_gen_spc_table(
00332 const cpl_vector * spectrum,
00333 const cpl_bivector * lines_catalog,
00334 double slitw,
00335 double fwhm,
00336 const cpl_polynomial * guess_poly,
00337 const cpl_polynomial * corr_poly)
00338 {
00339
00340 cpl_vector * conv_kernel = NULL;
00341 cpl_bivector * gen_init ;
00342 cpl_bivector * gen_corr ;
00343 cpl_table * spc_table ;
00344 const double * pgen ;
00345 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00346 const int spec_sz = cpl_vector_get_size(spectrum);
00347 const cpl_boolean guess_resamp
00348 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00349 guess_poly, spec_sz, 1.0);
00350 const cpl_boolean corr_resamp
00351 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00352 corr_poly, spec_sz, 1.0);
00353 cpl_error_code error;
00354
00355 cpl_msg_debug(cpl_func, "Tabel for guess dispersion polynomial (slitw=%g, "
00356 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00357 "sampling", slitw, fwhm, spec_sz, guess_resamp ? "out" : "");
00358 cpl_msg_debug(cpl_func, "Tabel for corr. dispersion polynomial (slitw=%g, "
00359 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00360 "sampling", slitw, fwhm, spec_sz, corr_resamp ? "out" : "");
00361
00362
00363 cpl_ensure(spectrum, CPL_ERROR_NULL_INPUT, NULL) ;
00364 cpl_ensure(lines_catalog, CPL_ERROR_NULL_INPUT, NULL) ;
00365 cpl_ensure(guess_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00366 cpl_ensure(corr_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00367
00368
00369 if (guess_resamp || corr_resamp) {
00370 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00371
00372 if (conv_kernel == NULL) {
00373 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00374 __FILE__, __LINE__, "Cannot create "
00375 "convolution kernel") ;
00376 return NULL ;
00377 }
00378 }
00379
00380
00381 gen_init = cpl_bivector_new(spec_sz);
00382 if (guess_resamp) {
00383 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_init),
00384 lines_catalog, conv_kernel,
00385 guess_poly, 0);
00386 } else {
00387 error = irplib_vector_fill_line_spectrum_model
00388 (cpl_bivector_get_y(gen_init), NULL, NULL,
00389 guess_poly, lines_catalog,
00390 slitw, fwhm, xtrunc, 0, CPL_FALSE, CPL_FALSE, NULL);
00391 }
00392
00393 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_init),
00394 guess_poly, 1, 1)) {
00395 cpl_vector_delete(conv_kernel);
00396 cpl_bivector_delete(gen_init);
00397 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00398 __FILE__, __LINE__, "Cannot get the "
00399 "emission spectrum");
00400 return NULL;
00401 }
00402
00403
00404 gen_corr = cpl_bivector_new(spec_sz);
00405 if (corr_resamp) {
00406 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_corr),
00407 lines_catalog, conv_kernel,
00408 corr_poly, 0);
00409 } else {
00410 error = irplib_vector_fill_line_spectrum_model
00411 (cpl_bivector_get_y(gen_corr), NULL, NULL,
00412 corr_poly, lines_catalog,
00413 slitw, fwhm, xtrunc, 0, CPL_FALSE, CPL_FALSE, NULL);
00414 }
00415
00416 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_corr),
00417 corr_poly, 1, 1)) {
00418 cpl_vector_delete(conv_kernel);
00419 cpl_bivector_delete(gen_init);
00420 cpl_bivector_delete(gen_corr) ;
00421 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00422 __FILE__, __LINE__, "Cannot get the "
00423 "emission spectrum");
00424 return NULL;
00425 }
00426 cpl_vector_delete(conv_kernel) ;
00427
00428
00429 spc_table = cpl_table_new(spec_sz);
00430 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH,
00431 CPL_TYPE_DOUBLE);
00432 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT,
00433 CPL_TYPE_DOUBLE);
00434 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL,
00435 CPL_TYPE_DOUBLE);
00436 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_OBS, CPL_TYPE_DOUBLE);
00437
00438
00439 pgen = cpl_bivector_get_x_data_const(gen_corr) ;
00440 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH, pgen) ;
00441 pgen = cpl_bivector_get_y_data_const(gen_corr) ;
00442 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL, pgen) ;
00443 pgen = cpl_vector_get_data_const(spectrum) ;
00444 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_OBS, pgen) ;
00445 pgen = cpl_bivector_get_y_data_const(gen_init) ;
00446 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT, pgen);
00447 cpl_bivector_delete(gen_init);
00448 cpl_bivector_delete(gen_corr);
00449
00450 return spc_table ;
00451 }
00452
00453
00465
00466 cpl_bivector * irplib_wlxcorr_cat_extract(
00467 const cpl_bivector * lines_catalog,
00468 double wave_min,
00469 double wave_max)
00470 {
00471 const int nlines = cpl_bivector_get_size(lines_catalog);
00472 int wave_min_id, wave_max_id ;
00473 cpl_vector * sub_cat_wl ;
00474 cpl_vector * sub_cat_int ;
00475 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
00476 const double * dxlines = cpl_vector_get_data_const(xlines);
00477
00478 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
00479
00480
00481 wave_min_id = (int)cpl_vector_find(xlines, wave_min);
00482 if (wave_min_id < 0) {
00483 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00484 __FILE__, __LINE__,
00485 "The starting wavelength cannot be found") ;
00486 return NULL ;
00487 }
00488
00489
00490 if (dxlines[wave_min_id] <= wave_min) wave_min_id++;
00491
00492
00493 wave_max_id = (int)cpl_vector_find(xlines, wave_max);
00494 if (wave_max_id < 0) {
00495 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00496 __FILE__, __LINE__,
00497 "The ending wavelength cannot be found") ;
00498 return NULL ;
00499 }
00500
00501 if (dxlines[wave_max_id] >= wave_min) wave_max_id--;
00502
00503
00504
00505 cpl_ensure(wave_min_id <= wave_max_id, CPL_ERROR_ILLEGAL_INPUT, NULL);
00506
00507 if (wave_min_id < 0 || wave_max_id == nlines) {
00508 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00509 __FILE__, __LINE__, "The %d-line catalogue "
00510 "has no lines in the range %g -> %g",
00511 nlines, wave_min, wave_max);
00512 return NULL ;
00513 }
00514
00515 sub_cat_wl = cpl_vector_extract(xlines, wave_min_id, wave_max_id, 1);
00516 sub_cat_int = cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog),
00517 wave_min_id, wave_max_id, 1);
00518
00519 return cpl_bivector_wrap_vectors(sub_cat_wl, sub_cat_int);
00520 }
00521
00522
00539
00540 cpl_vector * irplib_wlxcorr_convolve_create_kernel(double slitw,
00541 double fwhm)
00542 {
00543 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
00544 const int size = 1 + (int)(5.0 * sigma + 0.5*slitw);
00545 cpl_vector * kernel = cpl_vector_new(size);
00546
00547
00548 if (cpl_vector_fill_lss_profile_symmetric(kernel, slitw, fwhm)) {
00549 cpl_vector_delete(kernel);
00550 cpl_ensure(0, cpl_error_get_code(), NULL);
00551 }
00552
00553 return kernel;
00554 }
00555
00556
00569
00570 int irplib_wlxcorr_convolve(
00571 cpl_vector * smoothed,
00572 const cpl_vector * conv_kernel)
00573 {
00574 int nsamples ;
00575 int ihwidth ;
00576 cpl_vector * raw ;
00577 double * psmoothe ;
00578 double * praw ;
00579 const double* psymm ;
00580 int i, j ;
00581
00582
00583 cpl_ensure(smoothed, CPL_ERROR_NULL_INPUT, -1) ;
00584 cpl_ensure(conv_kernel, CPL_ERROR_NULL_INPUT, -1) ;
00585
00586
00587 nsamples = cpl_vector_get_size(smoothed) ;
00588 ihwidth = cpl_vector_get_size(conv_kernel) - 1 ;
00589 cpl_ensure(ihwidth<nsamples, CPL_ERROR_ILLEGAL_INPUT, -1) ;
00590 psymm = cpl_vector_get_data_const(conv_kernel) ;
00591 psmoothe = cpl_vector_get_data(smoothed) ;
00592
00593
00594 raw = cpl_vector_duplicate(smoothed) ;
00595 praw = cpl_vector_get_data(raw) ;
00596
00597
00598 for (i=0 ; i<ihwidth ; i++) {
00599 psmoothe[i] = praw[i] * psymm[0];
00600 for (j=1 ; j <= ihwidth ; j++) {
00601 const int k = i-j < 0 ? 0 : i-j;
00602 psmoothe[i] += (praw[k]+praw[i+j]) * psymm[j];
00603 }
00604 }
00605
00606 for (i=ihwidth ; i<nsamples-ihwidth ; i++) {
00607 psmoothe[i] = praw[i] * psymm[0];
00608 for (j=1 ; j<=ihwidth ; j++)
00609 psmoothe[i] += (praw[i-j]+praw[i+j]) * psymm[j];
00610 }
00611 for (i=nsamples-ihwidth ; i<nsamples ; i++) {
00612 psmoothe[i] = praw[i] * psymm[0];
00613 for (j=1 ; j<=ihwidth ; j++) {
00614 const int k = i+j > nsamples-1 ? nsamples - 1 : i+j;
00615 psmoothe[i] += (praw[k]+praw[i-j]) * psymm[j];
00616 }
00617 }
00618 cpl_vector_delete(raw) ;
00619 return 0 ;
00620 }
00621
00622
00632
00633 int irplib_wlxcorr_plot_solution(
00634 const cpl_polynomial * init,
00635 const cpl_polynomial * comp,
00636 const cpl_polynomial * sol,
00637 int pix_start,
00638 int pix_stop)
00639 {
00640 int nsamples, nplots ;
00641 cpl_vector ** vectors ;
00642 int i ;
00643
00644
00645 if (init == NULL || comp == NULL) return -1 ;
00646
00647
00648 nsamples = pix_stop - pix_start + 1 ;
00649 if (sol != NULL) nplots = 3 ;
00650 else nplots = 2 ;
00651
00652
00653 vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00654 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00655
00656
00657
00658 for (i=0 ; i<nsamples ; i++) {
00659 cpl_vector_set(vectors[0], i, pix_start+i) ;
00660 cpl_vector_set(vectors[1], i,
00661 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL)) ;
00662 cpl_vector_set(vectors[2], i,
00663 cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL)) ;
00664 if (sol != NULL)
00665 cpl_vector_set(vectors[3], i,
00666 cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL)) ;
00667 }
00668
00669
00670 cpl_plot_vectors("set grid;set xlabel 'Position (pixels)';",
00671 "t '1-Initial / 2-Computed / 3-Solution' w lines",
00672 "", (const cpl_vector **)vectors, nplots+1);
00673
00674
00675 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00676 cpl_free(vectors) ;
00677
00678
00679 nplots -- ;
00680 vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00681 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00682
00683
00684
00685 for (i=0 ; i<nsamples ; i++) {
00686 double diff ;
00687 cpl_vector_set(vectors[0], i, pix_start+i) ;
00688 diff = cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL) -
00689 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00690 cpl_vector_set(vectors[1], i, diff) ;
00691 if (sol != NULL) {
00692 diff = cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL) -
00693 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00694 cpl_vector_set(vectors[2], i, diff) ;
00695 }
00696 }
00697
00698
00699 if (sol == NULL) {
00700 cpl_bivector * bivector ;
00701 bivector = cpl_bivector_wrap_vectors(vectors[0], vectors[1]) ;
00702 cpl_plot_bivector(
00703 "set grid;set xlabel 'Position (pixels)';set ylabel 'Wavelength difference';",
00704 "t 'Computed-Initial wavelenth' w lines", "", bivector);
00705 cpl_bivector_unwrap_vectors(bivector) ;
00706 } else {
00707 cpl_plot_vectors("set grid;set xlabel 'Position (pixels)';",
00708 "t '1-Computed - Initial / 2--Solution - Initial' w lines",
00709 "", (const cpl_vector **)vectors, nplots+1);
00710 }
00711
00712
00713 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00714 cpl_free(vectors) ;
00715
00716
00717 return 0 ;
00718 }
00719
00720
00731
00732 int irplib_wlxcorr_plot_spc_table(
00733 const cpl_table * spc_table,
00734 const char * title,
00735 int first_plotted_line,
00736 int last_plotted_line)
00737 {
00738 char title_loc[1024] ;
00739 cpl_vector ** vectors ;
00740 cpl_vector ** sub_vectors ;
00741 cpl_vector * tmp_vec ;
00742 int nsamples ;
00743 double mean1, mean3 ;
00744 int start_ind, stop_ind, hsize_pix ;
00745 int i, j ;
00746
00747
00748 if (first_plotted_line > last_plotted_line) return -1 ;
00749 if (spc_table == NULL) return -1 ;
00750
00751
00752 nsamples = cpl_table_get_nrow(spc_table) ;
00753 hsize_pix = 10 ;
00754
00755 sprintf(title_loc,
00756 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed' w lines",
00757 title) ;
00758 title_loc[1023] = (char)0 ;
00759
00760 vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00761 vectors[0] = cpl_vector_wrap(nsamples,
00762 cpl_table_get_data_double((cpl_table*)spc_table,
00763 IRPLIB_WLXCORR_COL_WAVELENGTH));
00764 vectors[1] = cpl_vector_wrap(nsamples,
00765 cpl_table_get_data_double((cpl_table*)spc_table,
00766 IRPLIB_WLXCORR_COL_CAT_INIT));
00767 vectors[2] = cpl_vector_wrap(nsamples,
00768 cpl_table_get_data_double((cpl_table*)spc_table,
00769 IRPLIB_WLXCORR_COL_CAT_FINAL));
00770 vectors[3] = cpl_vector_wrap(nsamples,
00771 cpl_table_get_data_double((cpl_table*)spc_table,
00772 IRPLIB_WLXCORR_COL_OBS)) ;
00773
00774
00775 mean1 = cpl_vector_get_mean(vectors[1]) ;
00776 mean3 = cpl_vector_get_mean(vectors[3]) ;
00777 if (fabs(mean3) > 1)
00778 cpl_vector_multiply_scalar(vectors[3], fabs(mean1/mean3)) ;
00779
00780 cpl_plot_vectors("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00781 "", (const cpl_vector **)vectors, 4);
00782
00783
00784 if (fabs(mean3) > 1)
00785 cpl_vector_multiply_scalar(vectors[3], mean3/mean1) ;
00786
00787
00788 sprintf(title_loc,
00789 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed (ZOOMED)' w lines",
00790 title) ;
00791 title_loc[1023] = (char)0 ;
00792 tmp_vec = cpl_vector_duplicate(vectors[2]) ;
00793 for (i=0 ; i<last_plotted_line ; i++) {
00794 double max;
00795
00796 if ((max = cpl_vector_get_max(tmp_vec)) <= 0.0) break ;
00797 for (j=0 ; j<nsamples ; j++) {
00798 if (cpl_vector_get(tmp_vec, j) == max) break ;
00799 }
00800 if (j-hsize_pix < 0) start_ind = 0 ;
00801 else start_ind = j-hsize_pix ;
00802 if (j+hsize_pix > nsamples-1) stop_ind = nsamples-1 ;
00803 else stop_ind = j+hsize_pix ;
00804 for (j=start_ind ; j<=stop_ind ; j++) cpl_vector_set(tmp_vec, j, 0.0) ;
00805
00806 if (i+1 >= first_plotted_line) {
00807 sub_vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00808 sub_vectors[0]=cpl_vector_extract(vectors[0],start_ind,stop_ind,1);
00809 sub_vectors[1]=cpl_vector_extract(vectors[1],start_ind,stop_ind,1);
00810 sub_vectors[2]=cpl_vector_extract(vectors[2],start_ind,stop_ind,1);
00811 sub_vectors[3]=cpl_vector_extract(vectors[3],start_ind,stop_ind,1);
00812
00813 cpl_plot_vectors("set grid;set xlabel 'Wavelength (nm)';",
00814 title_loc, "", (const cpl_vector **)sub_vectors, 4);
00815
00816 cpl_vector_delete(sub_vectors[0]) ;
00817 cpl_vector_delete(sub_vectors[1]) ;
00818 cpl_vector_delete(sub_vectors[2]) ;
00819 cpl_vector_delete(sub_vectors[3]) ;
00820 cpl_free(sub_vectors) ;
00821 }
00822 }
00823 cpl_vector_delete(tmp_vec) ;
00824
00825 cpl_vector_unwrap(vectors[0]) ;
00826 cpl_vector_unwrap(vectors[1]) ;
00827 cpl_vector_unwrap(vectors[2]) ;
00828 cpl_vector_unwrap(vectors[3]) ;
00829 cpl_free(vectors) ;
00830
00831 return 0 ;
00832 }
00833
00834
00842
00843 int irplib_wlxcorr_catalog_plot(
00844 const cpl_bivector * cat,
00845 double wmin,
00846 double wmax)
00847 {
00848 int start, stop ;
00849 cpl_bivector * subcat ;
00850 cpl_vector * subcat_x ;
00851 cpl_vector * subcat_y ;
00852 const double * pwave ;
00853 int nvals, nvals_tot ;
00854 int i ;
00855
00856
00857 if (cat == NULL) return -1 ;
00858 if (wmax <= wmin) return -1 ;
00859
00860
00861 nvals_tot = cpl_bivector_get_size(cat) ;
00862
00863
00864 pwave = cpl_bivector_get_x_data_const(cat) ;
00865 if (pwave[0] >= wmin) start = 0 ;
00866 else start = -1 ;
00867 if (pwave[nvals_tot-1] <= wmax) stop = nvals_tot-1 ;
00868 else stop = -1 ;
00869 i=0 ;
00870 while ((i<nvals_tot-1) && (pwave[i] < wmin)) i++ ;
00871 start = i ;
00872 i= nvals_tot-1 ;
00873 while ((i>0) && (pwave[i] > wmax)) i-- ;
00874 stop = i ;
00875
00876 if (start>=stop) {
00877 cpl_msg_error(cpl_func, "Cannot plot the catalog") ;
00878 return -1 ;
00879 }
00880 nvals = stop - start + 1 ;
00881
00882
00883 subcat_x = cpl_vector_extract(cpl_bivector_get_x_const(cat),start,stop, 1) ;
00884 subcat_y = cpl_vector_extract(cpl_bivector_get_y_const(cat),start,stop, 1) ;
00885 subcat = cpl_bivector_wrap_vectors(subcat_x, subcat_y) ;
00886
00887
00888 if (nvals > 500) {
00889 cpl_plot_bivector(
00890 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00891 "t 'Catalog Spectrum' w lines", "", subcat);
00892 } else {
00893 cpl_plot_bivector(
00894 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00895 "t 'Catalog Spectrum' w impulses", "", subcat);
00896 }
00897 cpl_bivector_unwrap_vectors(subcat) ;
00898 cpl_vector_delete(subcat_x) ;
00899 cpl_vector_delete(subcat_y) ;
00900
00901 return 0 ;
00902 }
00903
00906
00921
00922 static void irplib_wlxcorr_estimate(cpl_vector * vxc,
00923 cpl_vector * model,
00924 const cpl_vector * spectrum,
00925 const cpl_bivector * lines_catalog,
00926 const cpl_vector * conv_kernel,
00927 const cpl_polynomial * poly_candi,
00928 double slitw,
00929 double fwhm)
00930 {
00931 cpl_errorstate prestate = cpl_errorstate_get();
00932 const int hsize = cpl_vector_get_size(vxc) / 2;
00933
00934 if (conv_kernel != NULL) {
00935 irplib_wlcalib_fill_spectrum(model, lines_catalog, conv_kernel,
00936 poly_candi, hsize);
00937 } else {
00938 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00939
00940 irplib_vector_fill_line_spectrum_model(model, NULL, NULL, poly_candi,
00941 lines_catalog, slitw, fwhm,
00942 xtrunc, 0, CPL_FALSE, CPL_FALSE,
00943 NULL);
00944 }
00945
00946 if (cpl_errorstate_is_equal(prestate))
00947 cpl_vector_correlate(vxc, model, spectrum);
00948
00949 if (!cpl_errorstate_is_equal(prestate)) {
00950 cpl_vector_fill(vxc, 0.0);
00951
00952
00953 cpl_errorstate_set(prestate);
00954
00955 }
00956
00957 return;
00958 }
00959
00960
00961
00971
00972 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector * wavelengths,
00973 const cpl_polynomial * disp1d,
00974 int spec_sz,
00975 double tol)
00976 {
00977 const int nlines = cpl_vector_get_size(wavelengths);
00978
00979 const double dispersion = cpl_polynomial_eval_1d_diff(disp1d,
00980 0.5 * spec_sz + 1.0,
00981 0.5 * spec_sz,
00982 NULL);
00983 const double range = cpl_vector_get(wavelengths, nlines-1)
00984 - cpl_vector_get(wavelengths, 0);
00985
00986 cpl_ensure(wavelengths != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
00987 cpl_ensure(disp1d != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
00988 cpl_ensure(cpl_polynomial_get_dimension(disp1d) == 1,
00989 CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
00990 cpl_ensure(range > 0.0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
00991
00992 return nlines * fabs(dispersion) <= tol * fabs(range) ? CPL_TRUE
00993 : CPL_FALSE;
00994
00995 }
00996
00997
01012
01013 static
01014 cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector * self,
01015 const cpl_bivector * lines_catalog,
01016 const cpl_vector * conv_kernel,
01017 const cpl_polynomial * poly,
01018 int search_hs)
01019 {
01020
01021
01022 const int size = cpl_vector_get_size(self);
01023 const int nlines = cpl_bivector_get_size(lines_catalog);
01024 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
01025 const double * dxlines = cpl_vector_get_data_const(xlines);
01026 cpl_bivector * sub_cat ;
01027 cpl_vector * sub_cat_x;
01028 cpl_vector * sub_cat_y;
01029 cpl_vector * wl_limits;
01030 double wave_min, wave_max;
01031 int wave_min_id, wave_max_id;
01032 int nsub;
01033 int error;
01034
01035 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01036 cpl_ensure_code(lines_catalog != NULL, CPL_ERROR_NULL_INPUT);
01037 cpl_ensure_code(conv_kernel != NULL, CPL_ERROR_NULL_INPUT);
01038 cpl_ensure_code(poly != NULL, CPL_ERROR_NULL_INPUT);
01039 cpl_ensure_code(size > 0, CPL_ERROR_ILLEGAL_INPUT);
01040
01041
01042
01043 wl_limits = cpl_vector_new(size + 1);
01044 cpl_vector_fill_polynomial(wl_limits, poly, 0.5 - search_hs, 1);
01045
01046
01047 wave_min = cpl_vector_get(wl_limits, 0);
01048 wave_max = cpl_vector_get(wl_limits, size);
01049
01050
01051 wave_min_id = cpl_vector_find(xlines, wave_min);
01052
01053 if (dxlines[wave_min_id] > wave_min) wave_min_id--;
01054
01055 if (wave_min_id < 0) {
01056 cpl_vector_delete(wl_limits);
01057 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01058 __FILE__, __LINE__, "The %d-line "
01059 "catalogue only has lines above %g",
01060 nlines, wave_min);
01061 }
01062
01063
01064 wave_max_id = cpl_vector_find(xlines, wave_max);
01065
01066 if (dxlines[wave_max_id] < wave_max) wave_max_id++;
01067
01068 if (wave_max_id == nlines) {
01069 cpl_vector_delete(wl_limits);
01070 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01071 __FILE__, __LINE__, "The %d-line "
01072 "catalogue only has lines below %g",
01073 nlines, wave_max);
01074 }
01075
01076
01077
01078 nsub = 1 + wave_max_id - wave_min_id;
01079 cpl_ensure_code(nsub > 1, CPL_ERROR_ILLEGAL_INPUT);
01080
01081
01082
01083 sub_cat_x = cpl_vector_wrap(nsub, wave_min_id + (double*)dxlines);
01084 sub_cat_y = cpl_vector_wrap(nsub, wave_min_id + (double*)
01085 cpl_bivector_get_y_data_const(lines_catalog));
01086 sub_cat = cpl_bivector_wrap_vectors(sub_cat_x, sub_cat_y);
01087
01088
01089 error = irplib_wlxcorr_signal_resample(self, wl_limits, sub_cat);
01090
01091 cpl_vector_delete(wl_limits);
01092 cpl_bivector_unwrap_vectors(sub_cat);
01093 (void)cpl_vector_unwrap(sub_cat_x);
01094 (void)cpl_vector_unwrap(sub_cat_y);
01095
01096 cpl_ensure_code(!error, CPL_ERROR_ILLEGAL_INPUT);
01097
01098
01099 cpl_ensure_code(!irplib_wlxcorr_convolve(self, conv_kernel),
01100 cpl_error_get_code());
01101
01102 return CPL_ERROR_NONE;
01103 }
01104
01105
01106
01116
01117 static int irplib_wlxcorr_signal_resample(
01118 cpl_vector * resampled,
01119 const cpl_vector * xbounds,
01120 const cpl_bivector * hires)
01121 {
01122 const int hrsize = cpl_bivector_get_size(hires);
01123 const cpl_vector* xhires ;
01124 const cpl_vector* yhires ;
01125 const double * pxhires ;
01126 const double * pyhires ;
01127 const double * pxbounds ;
01128 cpl_vector * ybounds ;
01129 cpl_bivector * boundary ;
01130 double * pybounds ;
01131 double * presampled ;
01132 int nsamples ;
01133 int i, itt ;
01134
01135
01136 if ((!resampled) || (!xbounds) || (!hires)) return -1 ;
01137
01138
01139 nsamples = cpl_vector_get_size(resampled) ;
01140
01141
01142 presampled = cpl_vector_get_data(resampled) ;
01143 pxbounds = cpl_vector_get_data_const(xbounds) ;
01144 xhires = cpl_bivector_get_x_const(hires) ;
01145 yhires = cpl_bivector_get_y_const(hires) ;
01146 pxhires = cpl_vector_get_data_const(xhires) ;
01147 pyhires = cpl_vector_get_data_const(yhires) ;
01148
01149
01150 ybounds = cpl_vector_new(cpl_vector_get_size(xbounds)) ;
01151 boundary = cpl_bivector_wrap_vectors((cpl_vector*)xbounds,ybounds) ;
01152 pybounds = cpl_vector_get_data(ybounds) ;
01153
01154
01155 if (cpl_bivector_get_size(boundary) != nsamples + 1) {
01156 cpl_bivector_unwrap_vectors(boundary) ;
01157 cpl_vector_delete(ybounds) ;
01158 return -1 ;
01159 }
01160
01161
01162 itt = cpl_vector_find(xhires, pxbounds[0]);
01163
01164
01165 if (cpl_bivector_interpolate_linear(boundary, hires)) {
01166 cpl_bivector_unwrap_vectors(boundary) ;
01167 cpl_vector_delete(ybounds) ;
01168 return -1 ;
01169 }
01170
01171
01172
01173 while (pxhires[itt] < pxbounds[0]) itt++;
01174
01175 for (i=0; i < nsamples; i++) {
01176
01177
01178
01179
01180 double xlow = pxbounds[i];
01181 double x = pxhires[itt];
01182
01183 if (x > pxbounds[i+1]) x = pxbounds[i+1];
01184
01185
01186 presampled[i] = pybounds[i] * (x - xlow);
01187
01188
01189 while ((pxhires[itt] < pxbounds[i+1]) && (itt < hrsize)) {
01190 const double xprev = x;
01191 x = pxhires[itt+1];
01192 if (x > pxbounds[i+1]) x = pxbounds[i+1];
01193 presampled[i] += pyhires[itt] * (x - xlow);
01194 xlow = xprev;
01195 itt++;
01196 }
01197
01198
01199
01200 presampled[i] += pybounds[i+1] * (pxbounds[i+1] - xlow);
01201
01202
01203
01204 presampled[i] /= 2 * (pxbounds[i+1] - pxbounds[i]);
01205 }
01206 cpl_bivector_unwrap_vectors(boundary) ;
01207 cpl_vector_delete(ybounds) ;
01208 return 0 ;
01209 }
01210
01211
01212
01213
01234
01235 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector * self,
01236 double slitw,
01237 double fwhm)
01238 {
01239
01240 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
01241 const int n = cpl_vector_get_size(self);
01242 int i;
01243
01244
01245 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01246 cpl_ensure_code(slitw > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01247 cpl_ensure_code(fwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01248
01249
01250
01251
01252 (void)cpl_vector_set(self, 0,
01253 (irplib_erf_antideriv(0.5*slitw + 0.5, sigma) -
01254 irplib_erf_antideriv(0.5*slitw - 0.5, sigma)) / slitw);
01255
01256 for (i = 1; i < n; i++) {
01257
01258 const double x1p = i + 0.5*slitw + 0.5;
01259 const double x1n = i - 0.5*slitw + 0.5;
01260 const double x0p = i + 0.5*slitw - 0.5;
01261 const double x0n = i - 0.5*slitw - 0.5;
01262 const double val = 0.5/slitw *
01263 (irplib_erf_antideriv(x1p, sigma) - irplib_erf_antideriv(x1n, sigma) -
01264 irplib_erf_antideriv(x0p, sigma) + irplib_erf_antideriv(x0n, sigma));
01265 (void)cpl_vector_set(self, i, val);
01266 }
01267
01268 return CPL_ERROR_NONE;
01269 }