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 <string.h>
00038
00039 #include <cpl.h>
00040
00041 #include "irplib_wavecal_impl.h"
00042
00043 #include "irplib_wlxcorr.h"
00044 #include "irplib_plot.h"
00045
00046
00056
00057
00058
00059
00060
00061
00062 #ifndef inline
00063 #define inline
00064 #endif
00065
00066 #define IRPLIB_MAX(A,B) ((A) > (B) ? (A) : (B))
00067 #define IRPLIB_MIN(A,B) ((A) < (B) ? (A) : (B))
00068
00069 #define IRPLIB_PTR_SWAP(a,b) \
00070 do { void * irplib_ptr_swap =(a);(a)=(b);(b)=irplib_ptr_swap; } while (0)
00071
00072
00073
00074
00075
00076 static void irplib_wlxcorr_estimate(cpl_vector *, cpl_vector *,
00077 const cpl_vector *,
00078 const cpl_bivector *,
00079 const cpl_vector *,
00080 const cpl_polynomial *,
00081 double, double);
00082
00083 static int irplib_wlxcorr_signal_resample(cpl_vector *, const cpl_vector *,
00084 const cpl_bivector *) ;
00085 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector *,
00086 double, double);
00087 static cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector *,
00088 const cpl_bivector *,
00089 const cpl_vector *,
00090 const cpl_polynomial *, int);
00091
00092 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector *,
00093 const cpl_polynomial *,
00094 int, double);
00095
00099
00135
00136 cpl_polynomial * irplib_wlxcorr_best_poly(const cpl_vector * spectrum,
00137 const cpl_bivector * lines_catalog,
00138 int degree,
00139 const cpl_polynomial * guess_poly,
00140 const cpl_vector * wl_error,
00141 int nsamples,
00142 double slitw,
00143 double fwhm,
00144 double * xc,
00145 cpl_table ** wlres,
00146 cpl_vector ** xcorrs)
00147 {
00148 const int spec_sz = cpl_vector_get_size(spectrum);
00149 const int nfree = cpl_vector_get_size(wl_error);
00150 int ntests = 1;
00151 cpl_vector * model;
00152 cpl_vector * vxc;
00153 cpl_vector * init_pts_wl;
00154 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00155 cpl_matrix * init_pts_x;
00156 #else
00157 cpl_vector * init_pts_x;
00158 #endif
00159 cpl_vector * pts_wl;
00160 cpl_vector * vxcorrs;
00161 cpl_vector * conv_kernel = NULL;
00162 cpl_polynomial * poly_sol;
00163 cpl_polynomial * poly_candi;
00164 const double * pwl_error = cpl_vector_get_data_const(wl_error);
00165 const double * dxc;
00166 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00167 const cpl_boolean symsamp = CPL_TRUE;
00168 #endif
00169 const cpl_boolean is_lines
00170 = irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00171 guess_poly, spec_sz, 1.0);
00172 int i;
00173
00174
00175
00176
00177 if (wlres != NULL) *wlres = NULL;
00178 if (xcorrs != NULL) *xcorrs = NULL;
00179
00180
00181 cpl_msg_debug(cpl_func, "Checking %d^%d dispersion polynomials (slitw=%g, "
00182 "fwhm=%g) against %d-point observed spectrum with%s "
00183 "catalog resampling", nsamples, nfree, slitw, fwhm, spec_sz,
00184 is_lines ? "out" : "");
00185
00186 cpl_ensure(xc != NULL, CPL_ERROR_NULL_INPUT, NULL);
00187 *xc = -1.0;
00188 cpl_ensure(spectrum != NULL, CPL_ERROR_NULL_INPUT, NULL);
00189 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
00190 cpl_ensure(guess_poly != NULL, CPL_ERROR_NULL_INPUT, NULL);
00191 cpl_ensure(wl_error != NULL, CPL_ERROR_NULL_INPUT, NULL);
00192 cpl_ensure(nfree >= 2, CPL_ERROR_ILLEGAL_INPUT, NULL);
00193 cpl_ensure(nsamples > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00194
00195 cpl_ensure(1 + degree == nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00196
00197 cpl_ensure(cpl_polynomial_get_dimension(guess_poly) == 1,
00198 CPL_ERROR_ILLEGAL_INPUT, NULL);
00199
00200 if (nsamples > 1) {
00201
00202
00203 for (i = 0; i < nfree; i++) {
00204 if (pwl_error[i] != 0.0) break;
00205 }
00206 cpl_ensure(i < nfree, CPL_ERROR_ILLEGAL_INPUT, NULL);
00207 }
00208
00209 if (!is_lines) {
00210
00211 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00212 cpl_ensure(conv_kernel != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00213 }
00214
00215
00216 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00217 init_pts_x = cpl_matrix_new(1, nfree);
00218 #else
00219 init_pts_x = cpl_vector_new(nfree);
00220 #endif
00221 init_pts_wl = cpl_vector_new(nfree);
00222 pts_wl = cpl_vector_new(nfree);
00223 for (i = 0; i < nfree; i++) {
00224 const double xpos = spec_sz * i / (double)degree;
00225 const double wlpos = cpl_polynomial_eval_1d(guess_poly, xpos, NULL)
00226 - 0.5 * pwl_error[i];
00227
00228 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00229 cpl_matrix_set(init_pts_x, 0, i, xpos);
00230 #else
00231 cpl_vector_set(init_pts_x, i, xpos);
00232 #endif
00233 cpl_vector_set(init_pts_wl, i, wlpos);
00234
00235 ntests *= nsamples;
00236
00237 }
00238
00239 vxcorrs = xcorrs != NULL ? cpl_vector_new(ntests) : NULL;
00240
00241 poly_sol = cpl_polynomial_new(1);
00242 poly_candi = cpl_polynomial_new(1);
00243 model = cpl_vector_new(spec_sz);
00244 vxc = cpl_vector_new(1);
00245 dxc = cpl_vector_get_data_const(vxc);
00246
00247
00248 for (i=0; i < ntests; i++) {
00249 int idiv = i;
00250 int deg;
00251
00252
00253
00254 for (deg = degree; deg >= 0; deg--, idiv /= nsamples) {
00255 const int imod = idiv % nsamples;
00256 const double wlpos = cpl_vector_get(init_pts_wl, deg)
00257 + imod * pwl_error[deg] / nsamples;
00258
00259
00260
00261
00262 cpl_vector_set(pts_wl, deg, wlpos);
00263
00264 if (imod > 0) break;
00265 }
00266
00267
00268 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00269 cpl_polynomial_fit(poly_candi, init_pts_x, &symsamp, pts_wl,
00270 NULL, CPL_FALSE, NULL, °ree);
00271 #else
00272 cpl_polynomial_delete(poly_candi);
00273 poly_candi = cpl_polynomial_fit_1d_create(init_pts_x, pts_wl, degree,
00274 NULL);
00275 #endif
00276
00277 irplib_wlxcorr_estimate(vxc, model, spectrum, lines_catalog,
00278 conv_kernel, poly_candi, slitw, fwhm);
00279 if (vxcorrs != NULL) cpl_vector_set(vxcorrs, i, *dxc);
00280 if (*dxc > *xc) {
00281
00282 *xc = *dxc;
00283 IRPLIB_PTR_SWAP(poly_sol, poly_candi);
00284 }
00285 }
00286
00287 cpl_vector_delete(model);
00288 cpl_vector_delete(vxc);
00289 cpl_vector_delete(conv_kernel);
00290 cpl_vector_delete(pts_wl);
00291 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00292 cpl_matrix_delete(init_pts_x);
00293 #else
00294 cpl_vector_delete(init_pts_x);
00295 #endif
00296 cpl_vector_delete(init_pts_wl);
00297 cpl_polynomial_delete(poly_candi);
00298
00299 #ifdef CPL_WLCALIB_FAIL_ON_CONSTANT
00300
00301 if (cpl_polynomial_get_degree(poly_sol) == 0) {
00302 cpl_polynomial_delete(poly_sol);
00303 cpl_vector_delete(vxcorrs);
00304 *xc = 0.0;
00305 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00306 __FILE__, __LINE__, "Found a constant "
00307 "dispersion");
00308 cpl_errorstate_dump(prestate, CPL_FALSE, NULL);
00309 return NULL;
00310 }
00311 #endif
00312
00313 if (wlres != NULL) {
00314
00315
00316
00317 cpl_errorstate prestate = cpl_errorstate_get();
00318
00319 *wlres = irplib_wlxcorr_gen_spc_table(spectrum, lines_catalog, slitw,
00320 fwhm, guess_poly, poly_sol);
00321 if (*wlres == NULL) {
00322 cpl_polynomial_delete(poly_sol);
00323 cpl_vector_delete(vxcorrs);
00324 *xc = -1.0;
00325 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00326 __FILE__, __LINE__, "Cannot generate "
00327 "infos table");
00328
00329 cpl_errorstate_set(prestate);
00330 return NULL;
00331 }
00332 }
00333
00334 if (xcorrs != NULL) {
00335 *xcorrs = vxcorrs;
00336 } else {
00337
00338 }
00339
00340 return poly_sol;
00341 }
00342
00343
00361
00362 cpl_table * irplib_wlxcorr_gen_spc_table(
00363 const cpl_vector * spectrum,
00364 const cpl_bivector * lines_catalog,
00365 double slitw,
00366 double fwhm,
00367 const cpl_polynomial * guess_poly,
00368 const cpl_polynomial * corr_poly)
00369 {
00370
00371 cpl_vector * conv_kernel = NULL;
00372 cpl_bivector * gen_init ;
00373 cpl_bivector * gen_corr ;
00374 cpl_table * spc_table ;
00375 const double * pgen ;
00376 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00377 const int spec_sz = cpl_vector_get_size(spectrum);
00378 const cpl_boolean guess_resamp
00379 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00380 guess_poly, spec_sz, 1.0);
00381 const cpl_boolean corr_resamp
00382 = !irplib_wlcalib_is_lines(cpl_bivector_get_x_const(lines_catalog),
00383 corr_poly, spec_sz, 1.0);
00384 cpl_error_code error;
00385
00386 cpl_msg_debug(cpl_func, "Tabel for guess dispersion polynomial (slitw=%g, "
00387 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00388 "sampling", slitw, fwhm, spec_sz, guess_resamp ? "out" : "");
00389 cpl_msg_debug(cpl_func, "Tabel for corr. dispersion polynomial (slitw=%g, "
00390 "fwhm=%g) with %d-point observed spectrum with%s catalog re"
00391 "sampling", slitw, fwhm, spec_sz, corr_resamp ? "out" : "");
00392
00393
00394 cpl_ensure(spectrum, CPL_ERROR_NULL_INPUT, NULL) ;
00395 cpl_ensure(lines_catalog, CPL_ERROR_NULL_INPUT, NULL) ;
00396 cpl_ensure(guess_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00397 cpl_ensure(corr_poly, CPL_ERROR_NULL_INPUT, NULL) ;
00398
00399
00400 if (guess_resamp || corr_resamp) {
00401 conv_kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00402
00403 if (conv_kernel == NULL) {
00404 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00405 __FILE__, __LINE__, "Cannot create "
00406 "convolution kernel") ;
00407 return NULL ;
00408 }
00409 }
00410
00411
00412 gen_init = cpl_bivector_new(spec_sz);
00413 if (guess_resamp) {
00414 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_init),
00415 lines_catalog, conv_kernel,
00416 guess_poly, 0);
00417 } else {
00418 error = irplib_vector_fill_line_spectrum_model
00419 (cpl_bivector_get_y(gen_init), NULL,
00420 guess_poly, lines_catalog,
00421 slitw, fwhm, xtrunc, 0);
00422 }
00423
00424 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_init),
00425 guess_poly, 1, 1)) {
00426 cpl_vector_delete(conv_kernel);
00427 cpl_bivector_delete(gen_init);
00428 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00429 __FILE__, __LINE__, "Cannot get the "
00430 "emission spectrum");
00431 return NULL;
00432 }
00433
00434
00435 gen_corr = cpl_bivector_new(spec_sz);
00436 if (corr_resamp) {
00437 error = irplib_wlcalib_fill_spectrum(cpl_bivector_get_y(gen_corr),
00438 lines_catalog, conv_kernel,
00439 corr_poly, 0);
00440 } else {
00441 error = irplib_vector_fill_line_spectrum_model
00442 (cpl_bivector_get_y(gen_corr), NULL,
00443 corr_poly, lines_catalog,
00444 slitw, fwhm, xtrunc, 0);
00445 }
00446
00447 if (error || cpl_vector_fill_polynomial(cpl_bivector_get_x(gen_corr),
00448 corr_poly, 1, 1)) {
00449 cpl_vector_delete(conv_kernel);
00450 cpl_bivector_delete(gen_init);
00451 cpl_bivector_delete(gen_corr) ;
00452 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00453 __FILE__, __LINE__, "Cannot get the "
00454 "emission spectrum");
00455 return NULL;
00456 }
00457 cpl_vector_delete(conv_kernel) ;
00458
00459
00460 spc_table = cpl_table_new(spec_sz);
00461 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH,
00462 CPL_TYPE_DOUBLE);
00463 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT,
00464 CPL_TYPE_DOUBLE);
00465 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL,
00466 CPL_TYPE_DOUBLE);
00467 cpl_table_new_column(spc_table, IRPLIB_WLXCORR_COL_OBS, CPL_TYPE_DOUBLE);
00468
00469
00470 pgen = cpl_bivector_get_x_data_const(gen_corr) ;
00471 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_WAVELENGTH, pgen) ;
00472 pgen = cpl_bivector_get_y_data_const(gen_corr) ;
00473 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_FINAL, pgen) ;
00474 pgen = cpl_vector_get_data_const(spectrum) ;
00475 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_OBS, pgen) ;
00476 pgen = cpl_bivector_get_y_data_const(gen_init) ;
00477 cpl_table_copy_data_double(spc_table, IRPLIB_WLXCORR_COL_CAT_INIT, pgen);
00478 cpl_bivector_delete(gen_init);
00479 cpl_bivector_delete(gen_corr);
00480
00481 return spc_table ;
00482 }
00483
00484
00496
00497 cpl_bivector * irplib_wlxcorr_cat_extract(
00498 const cpl_bivector * lines_catalog,
00499 double wave_min,
00500 double wave_max)
00501 {
00502 const int nlines = cpl_bivector_get_size(lines_catalog);
00503 int wave_min_id, wave_max_id ;
00504 cpl_vector * sub_cat_wl ;
00505 cpl_vector * sub_cat_int ;
00506 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
00507 const double * dxlines = cpl_vector_get_data_const(xlines);
00508
00509 cpl_ensure(lines_catalog != NULL, CPL_ERROR_NULL_INPUT, NULL);
00510
00511
00512 wave_min_id = cpl_vector_find(xlines, wave_min);
00513
00514 if (dxlines[wave_min_id] <= wave_min) wave_min_id++;
00515
00516
00517 wave_max_id = cpl_vector_find(xlines, wave_max);
00518
00519 if (dxlines[wave_max_id] >= wave_min) wave_max_id--;
00520
00521
00522
00523 cpl_ensure(wave_min_id <= wave_max_id, CPL_ERROR_ILLEGAL_INPUT, NULL);
00524
00525 if (wave_min_id < 0 || wave_max_id == nlines) {
00526 cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00527 __FILE__, __LINE__, "The %d-line catalogue "
00528 "has no lines in the range %g -> %g",
00529 nlines, wave_min, wave_max);
00530 return NULL ;
00531 }
00532
00533 sub_cat_wl = cpl_vector_extract(xlines, wave_min_id, wave_max_id, 1);
00534 sub_cat_int = cpl_vector_extract(cpl_bivector_get_y_const(lines_catalog),
00535 wave_min_id, wave_max_id, 1);
00536
00537 return cpl_bivector_wrap_vectors(sub_cat_wl, sub_cat_int);
00538 }
00539
00540
00557
00558 cpl_vector * irplib_wlxcorr_convolve_create_kernel(double slitw,
00559 double fwhm)
00560 {
00561 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
00562 const int size = 1 + (int)(5.0 * sigma + 0.5*slitw);
00563 cpl_vector * kernel = cpl_vector_new(size);
00564
00565
00566 if (cpl_vector_fill_lss_profile_symmetric(kernel, slitw, fwhm)) {
00567 cpl_vector_delete(kernel);
00568 cpl_ensure(0, cpl_error_get_code(), NULL);
00569 }
00570
00571 return kernel;
00572 }
00573
00574
00587
00588 int irplib_wlxcorr_convolve(
00589 cpl_vector * smoothed,
00590 const cpl_vector * conv_kernel)
00591 {
00592 int nsamples ;
00593 int ihwidth ;
00594 cpl_vector * raw ;
00595 double * psmoothe ;
00596 double * praw ;
00597 const double* psymm ;
00598 int i, j ;
00599
00600
00601 cpl_ensure(smoothed, CPL_ERROR_NULL_INPUT, -1) ;
00602 cpl_ensure(conv_kernel, CPL_ERROR_NULL_INPUT, -1) ;
00603
00604
00605 nsamples = cpl_vector_get_size(smoothed) ;
00606 ihwidth = cpl_vector_get_size(conv_kernel) - 1 ;
00607 cpl_ensure(ihwidth<nsamples, CPL_ERROR_ILLEGAL_INPUT, -1) ;
00608 psymm = cpl_vector_get_data_const(conv_kernel) ;
00609 psmoothe = cpl_vector_get_data(smoothed) ;
00610
00611
00612 raw = cpl_vector_duplicate(smoothed) ;
00613 praw = cpl_vector_get_data(raw) ;
00614
00615
00616 for (i=0 ; i<ihwidth ; i++) {
00617 psmoothe[i] = praw[i] * psymm[0];
00618 for (j=1 ; j <= ihwidth ; j++) {
00619 const int k = i-j < 0 ? 0 : i-j;
00620 psmoothe[i] += (praw[k]+praw[i+j]) * psymm[j];
00621 }
00622 }
00623
00624 for (i=ihwidth ; i<nsamples-ihwidth ; i++) {
00625 psmoothe[i] = praw[i] * psymm[0];
00626 for (j=1 ; j<=ihwidth ; j++)
00627 psmoothe[i] += (praw[i-j]+praw[i+j]) * psymm[j];
00628 }
00629 for (i=nsamples-ihwidth ; i<nsamples ; i++) {
00630 psmoothe[i] = praw[i] * psymm[0];
00631 for (j=1 ; j<=ihwidth ; j++) {
00632 const int k = i+j > nsamples-1 ? nsamples - 1 : i+j;
00633 psmoothe[i] += (praw[k]+praw[i-j]) * psymm[j];
00634 }
00635 }
00636 cpl_vector_delete(raw) ;
00637 return 0 ;
00638 }
00639
00640
00650
00651 int irplib_wlxcorr_plot_solution(
00652 const cpl_polynomial * init,
00653 const cpl_polynomial * comp,
00654 const cpl_polynomial * sol,
00655 int pix_start,
00656 int pix_stop)
00657 {
00658 int nsamples, nplots ;
00659 cpl_vector ** vectors ;
00660 cpl_bivector * bivector ;
00661 double diff ;
00662 int i ;
00663
00664
00665 if (init == NULL || comp == NULL) return -1 ;
00666
00667
00668 nsamples = pix_stop - pix_start + 1 ;
00669 if (sol != NULL) nplots = 3 ;
00670 else nplots = 2 ;
00671
00672
00673 vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00674 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00675
00676
00677
00678 for (i=0 ; i<nsamples ; i++) {
00679 cpl_vector_set(vectors[0], i, pix_start+i) ;
00680 cpl_vector_set(vectors[1], i,
00681 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL)) ;
00682 cpl_vector_set(vectors[2], i,
00683 cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL)) ;
00684 if (sol != NULL)
00685 cpl_vector_set(vectors[3], i,
00686 cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL)) ;
00687 }
00688
00689
00690 irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';",
00691 "t '1-Initial / 2-Computed / 3-Solution' w lines",
00692 "", (const cpl_vector **)vectors, nplots+1);
00693
00694
00695 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00696 cpl_free(vectors) ;
00697
00698
00699 nplots -- ;
00700 vectors = cpl_malloc((nplots+1)*sizeof(cpl_vector*)) ;
00701 for (i=0 ; i<nplots+1 ; i++) vectors[i] = cpl_vector_new(nsamples) ;
00702
00703
00704
00705 for (i=0 ; i<nsamples ; i++) {
00706 cpl_vector_set(vectors[0], i, pix_start+i) ;
00707 diff = cpl_polynomial_eval_1d(comp, (double)(pix_start+i), NULL) -
00708 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00709 cpl_vector_set(vectors[1], i, diff) ;
00710 if (sol != NULL) {
00711 diff = cpl_polynomial_eval_1d(sol, (double)(pix_start+i), NULL) -
00712 cpl_polynomial_eval_1d(init, (double)(pix_start+i), NULL) ;
00713 cpl_vector_set(vectors[2], i, diff) ;
00714 }
00715 }
00716
00717
00718 if (sol == NULL) {
00719 bivector = cpl_bivector_wrap_vectors(vectors[0], vectors[1]) ;
00720 irplib_bivector_plot(
00721 "set grid;set xlabel 'Position (pixels)';set ylabel 'Wavelength difference';",
00722 "t 'Computed-Initial wavelenth' w lines", "", bivector);
00723 cpl_bivector_unwrap_vectors(bivector) ;
00724 } else {
00725 irplib_vectors_plot("set grid;set xlabel 'Position (pixels)';",
00726 "t '1-Computed - Initial / 2--Solution - Initial' w lines",
00727 "", (const cpl_vector **)vectors, nplots+1);
00728 }
00729
00730
00731 for (i=0 ; i<nplots+1 ; i++) cpl_vector_delete(vectors[i]) ;
00732 cpl_free(vectors) ;
00733
00734
00735 return 0 ;
00736 }
00737
00738
00745
00746 int irplib_wlxcorr_plot_spc_table(
00747 const cpl_table * spc_table,
00748 const char * title)
00749 {
00750 char title_loc[1024] ;
00751 cpl_vector ** vectors ;
00752 cpl_vector ** sub_vectors ;
00753 cpl_vector * tmp_vec ;
00754 int nsamples ;
00755 double hsize_nm, max, mean1, mean3 ;
00756 int start_ind, stop_ind, nblines, hsize_pix ;
00757 int i, j ;
00758
00759
00760 if (spc_table == NULL) return -1 ;
00761
00762
00763 nsamples = cpl_table_get_nrow(spc_table) ;
00764 hsize_nm = 0.2 ;
00765 hsize_pix = 10 ;
00766 nblines = 0 ;
00767 sprintf(title_loc,
00768 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed' w lines",
00769 title) ;
00770 title_loc[1023] = (char)0 ;
00771
00772 vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00773 vectors[0] = cpl_vector_wrap(nsamples,
00774 cpl_table_get_data_double((cpl_table*)spc_table,
00775 IRPLIB_WLXCORR_COL_WAVELENGTH));
00776 vectors[1] = cpl_vector_wrap(nsamples,
00777 cpl_table_get_data_double((cpl_table*)spc_table,
00778 IRPLIB_WLXCORR_COL_CAT_INIT));
00779 vectors[2] = cpl_vector_wrap(nsamples,
00780 cpl_table_get_data_double((cpl_table*)spc_table,
00781 IRPLIB_WLXCORR_COL_CAT_FINAL));
00782 vectors[3] = cpl_vector_wrap(nsamples,
00783 cpl_table_get_data_double((cpl_table*)spc_table,
00784 IRPLIB_WLXCORR_COL_OBS)) ;
00785
00786
00787 mean1 = cpl_vector_get_mean(vectors[1]) ;
00788 mean3 = cpl_vector_get_mean(vectors[3]) ;
00789 if (fabs(mean3) > 1)
00790 cpl_vector_multiply_scalar(vectors[3], fabs(mean1/mean3)) ;
00791
00792 irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00793 "", (const cpl_vector **)vectors, 4);
00794
00795
00796 if (fabs(mean3) > 1)
00797 cpl_vector_multiply_scalar(vectors[3], mean3/mean1) ;
00798
00799
00800 sprintf(title_loc,
00801 "t '%s - 1-Initial catalog/2-Corrected catalog/3-Observed (ZOOMED)' w lines",
00802 title) ;
00803 title_loc[1023] = (char)0 ;
00804 tmp_vec = cpl_vector_duplicate(vectors[2]) ;
00805 for (i=0 ; i<nblines ; i++) {
00806
00807 if ((max = cpl_vector_get_max(tmp_vec)) <= 0.0) break ;
00808 for (j=0 ; i<nsamples ; j++) {
00809 if (cpl_vector_get(tmp_vec, j) == max) break ;
00810 }
00811 if (j-hsize_pix < 0) start_ind = 0 ;
00812 else start_ind = j-hsize_pix ;
00813 if (j+hsize_pix > nsamples-1) stop_ind = nsamples-1 ;
00814 else stop_ind = j+hsize_pix ;
00815 for (j=start_ind ; j<=stop_ind ; j++) cpl_vector_set(tmp_vec, j, 0.0) ;
00816
00817 sub_vectors = cpl_malloc(4*sizeof(cpl_vector*)) ;
00818 sub_vectors[0]=cpl_vector_extract(vectors[0],start_ind,stop_ind,1);
00819 sub_vectors[1]=cpl_vector_extract(vectors[1],start_ind,stop_ind,1);
00820 sub_vectors[2]=cpl_vector_extract(vectors[2],start_ind,stop_ind,1);
00821 sub_vectors[3]=cpl_vector_extract(vectors[3],start_ind,stop_ind,1);
00822
00823 irplib_vectors_plot("set grid;set xlabel 'Wavelength (nm)';", title_loc,
00824 "", (const cpl_vector **)sub_vectors, 4);
00825
00826 cpl_vector_delete(sub_vectors[0]) ;
00827 cpl_vector_delete(sub_vectors[1]) ;
00828 cpl_vector_delete(sub_vectors[2]) ;
00829 cpl_vector_delete(sub_vectors[3]) ;
00830 cpl_free(sub_vectors) ;
00831 }
00832 cpl_vector_delete(tmp_vec) ;
00833
00834 cpl_vector_unwrap(vectors[0]) ;
00835 cpl_vector_unwrap(vectors[1]) ;
00836 cpl_vector_unwrap(vectors[2]) ;
00837 cpl_vector_unwrap(vectors[3]) ;
00838 cpl_free(vectors) ;
00839
00840 return 0 ;
00841 }
00842
00843
00851
00852 int irplib_wlxcorr_catalog_plot(
00853 const cpl_bivector * cat,
00854 double wmin,
00855 double wmax)
00856 {
00857 int start, stop ;
00858 cpl_bivector * subcat ;
00859 cpl_vector * subcat_x ;
00860 cpl_vector * subcat_y ;
00861 const double * pwave ;
00862 int nvals, nvals_tot ;
00863 int i ;
00864
00865
00866 if (cat == NULL) return -1 ;
00867 if (wmax <= wmin) return -1 ;
00868
00869
00870 nvals_tot = cpl_bivector_get_size(cat) ;
00871
00872
00873 pwave = cpl_bivector_get_x_data_const(cat) ;
00874 if (pwave[0] >= wmin) start = 0 ;
00875 else start = -1 ;
00876 if (pwave[nvals_tot-1] <= wmax) stop = nvals_tot-1 ;
00877 else stop = -1 ;
00878 i=0 ;
00879 while ((pwave[i] < wmin) && (i<nvals_tot-1)) i++ ;
00880 start = i ;
00881 i= nvals_tot-1 ;
00882 while ((pwave[i] > wmax) && (i>0)) i-- ;
00883 stop = i ;
00884
00885 if (start>=stop) {
00886 cpl_msg_error(cpl_func, "Cannot plot the catalog") ;
00887 return -1 ;
00888 }
00889 nvals = start - stop + 1 ;
00890
00891
00892 subcat_x = cpl_vector_extract(cpl_bivector_get_x_const(cat),start,stop, 1) ;
00893 subcat_y = cpl_vector_extract(cpl_bivector_get_y_const(cat),start,stop, 1) ;
00894 subcat = cpl_bivector_wrap_vectors(subcat_x, subcat_y) ;
00895
00896
00897 if (nvals > 500) {
00898 irplib_bivector_plot(
00899 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00900 "t 'Catalog Spectrum' w lines", "", subcat);
00901 } else {
00902 irplib_bivector_plot(
00903 "set grid;set xlabel 'Wavelength (nm)';set ylabel 'Emission';",
00904 "t 'Catalog Spectrum' w impulses", "", subcat);
00905 }
00906 cpl_bivector_unwrap_vectors(subcat) ;
00907 cpl_vector_delete(subcat_x) ;
00908 cpl_vector_delete(subcat_y) ;
00909
00910 return 0 ;
00911 }
00912
00915
00930
00931 static void irplib_wlxcorr_estimate(cpl_vector * vxc,
00932 cpl_vector * model,
00933 const cpl_vector * spectrum,
00934 const cpl_bivector * lines_catalog,
00935 const cpl_vector * conv_kernel,
00936 const cpl_polynomial * poly_candi,
00937 double slitw,
00938 double fwhm)
00939 {
00940 cpl_errorstate prestate = cpl_errorstate_get();
00941 const int hsize = cpl_vector_get_size(vxc) / 2;
00942
00943 if (conv_kernel != NULL) {
00944 irplib_wlcalib_fill_spectrum(model, lines_catalog, conv_kernel,
00945 poly_candi, hsize);
00946 } else {
00947 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00948
00949 irplib_vector_fill_line_spectrum_model(model, NULL, poly_candi,
00950 lines_catalog, slitw, fwhm,
00951 xtrunc, 0);
00952 }
00953
00954 if (cpl_errorstate_is_equal(prestate))
00955 cpl_vector_correlate(vxc, model, spectrum);
00956
00957 if (!cpl_errorstate_is_equal(prestate)) {
00958 cpl_vector_fill(vxc, 0.0);
00959
00960
00961 cpl_errorstate_set(prestate);
00962
00963 }
00964
00965 return;
00966 }
00967
00968
00969
00979
00980 static cpl_boolean irplib_wlcalib_is_lines(const cpl_vector * wavelengths,
00981 const cpl_polynomial * disp1d,
00982 int spec_sz,
00983 double tol)
00984 {
00985 const int nlines = cpl_vector_get_size(wavelengths);
00986
00987 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 1, 0)
00988 const double dispersion = cpl_polynomial_eval_1d_diff(disp1d,
00989 0.5 * spec_sz + 1.0,
00990 0.5 * spec_sz,
00991 NULL);
00992 #else
00993 const double dispersion
00994 = cpl_polynomial_eval_1d(disp1d, 0.5 * spec_sz + 1.0, NULL)
00995 - cpl_polynomial_eval_1d(disp1d, 0.5 * spec_sz , NULL);
00996 #endif
00997 const double range = cpl_vector_get(wavelengths, nlines-1)
00998 - cpl_vector_get(wavelengths, 0);
00999
01000 cpl_ensure(wavelengths != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01001 cpl_ensure(disp1d != NULL, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01002 cpl_ensure(cpl_polynomial_get_dimension(disp1d) == 1,
01003 CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01004 cpl_ensure(range > 0.0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01005
01006 return nlines * fabs(dispersion) <= tol * fabs(range) ? CPL_TRUE
01007 : CPL_FALSE;
01008
01009 }
01010
01011
01026
01027 static
01028 cpl_error_code irplib_wlcalib_fill_spectrum(cpl_vector * self,
01029 const cpl_bivector * lines_catalog,
01030 const cpl_vector * conv_kernel,
01031 const cpl_polynomial * poly,
01032 int search_hs)
01033 {
01034
01035
01036 const int size = cpl_vector_get_size(self);
01037 const int nlines = cpl_bivector_get_size(lines_catalog);
01038 const cpl_vector * xlines = cpl_bivector_get_x_const(lines_catalog);
01039 const double * dxlines = cpl_vector_get_data_const(xlines);
01040 cpl_bivector * sub_cat ;
01041 cpl_vector * sub_cat_x;
01042 cpl_vector * sub_cat_y;
01043 cpl_vector * wl_limits;
01044 double wave_min, wave_max;
01045 int wave_min_id, wave_max_id;
01046 int nsub;
01047 int error;
01048
01049 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01050 cpl_ensure_code(lines_catalog != NULL, CPL_ERROR_NULL_INPUT);
01051 cpl_ensure_code(conv_kernel != NULL, CPL_ERROR_NULL_INPUT);
01052 cpl_ensure_code(poly != NULL, CPL_ERROR_NULL_INPUT);
01053 cpl_ensure_code(size > 0, CPL_ERROR_ILLEGAL_INPUT);
01054
01055
01056
01057 wl_limits = cpl_vector_new(size + 1);
01058 cpl_vector_fill_polynomial(wl_limits, poly, 0.5 - search_hs, 1);
01059
01060
01061 wave_min = cpl_vector_get(wl_limits, 0);
01062 wave_max = cpl_vector_get(wl_limits, size);
01063
01064
01065 wave_min_id = cpl_vector_find(xlines, wave_min);
01066
01067 if (dxlines[wave_min_id] > wave_min) wave_min_id--;
01068
01069 if (wave_min_id < 0) {
01070 cpl_vector_delete(wl_limits);
01071 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01072 __FILE__, __LINE__, "The %d-line "
01073 "catalogue only has lines above %g",
01074 nlines, wave_min);
01075 }
01076
01077
01078 wave_max_id = cpl_vector_find(xlines, wave_max);
01079
01080 if (dxlines[wave_max_id] < wave_max) wave_max_id++;
01081
01082 if (wave_max_id == nlines) {
01083 cpl_vector_delete(wl_limits);
01084 return cpl_error_set_message_macro(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
01085 __FILE__, __LINE__, "The %d-line "
01086 "catalogue only has lines below %g",
01087 nlines, wave_max);
01088 }
01089
01090
01091
01092 nsub = 1 + wave_max_id - wave_min_id;
01093 cpl_ensure_code(nsub > 1, CPL_ERROR_ILLEGAL_INPUT);
01094
01095
01096
01097 sub_cat_x = cpl_vector_wrap(nsub, wave_min_id + (double*)dxlines);
01098 sub_cat_y = cpl_vector_wrap(nsub, wave_min_id + (double*)
01099 cpl_bivector_get_y_data_const(lines_catalog));
01100 sub_cat = cpl_bivector_wrap_vectors(sub_cat_x, sub_cat_y);
01101
01102
01103 error = irplib_wlxcorr_signal_resample(self, wl_limits, sub_cat);
01104
01105 cpl_vector_delete(wl_limits);
01106 cpl_bivector_unwrap_vectors(sub_cat);
01107 (void)cpl_vector_unwrap(sub_cat_x);
01108 (void)cpl_vector_unwrap(sub_cat_y);
01109
01110 cpl_ensure_code(!error, CPL_ERROR_ILLEGAL_INPUT);
01111
01112
01113 cpl_ensure_code(!irplib_wlxcorr_convolve(self, conv_kernel),
01114 cpl_error_get_code());
01115
01116 return CPL_ERROR_NONE;
01117 }
01118
01119
01120
01130
01131 static int irplib_wlxcorr_signal_resample(
01132 cpl_vector * resampled,
01133 const cpl_vector * xbounds,
01134 const cpl_bivector * hires)
01135 {
01136 const int hrsize = cpl_bivector_get_size(hires);
01137 const cpl_vector* xhires ;
01138 const cpl_vector* yhires ;
01139 const double * pxhires ;
01140 const double * pyhires ;
01141 const double * pxbounds ;
01142 cpl_vector * ybounds ;
01143 cpl_bivector * boundary ;
01144 double * pybounds ;
01145 double * presampled ;
01146 int nsamples ;
01147 int i, itt ;
01148
01149
01150 if ((!resampled) || (!xbounds) || (!hires)) return -1 ;
01151
01152
01153 nsamples = cpl_vector_get_size(resampled) ;
01154
01155
01156 presampled = cpl_vector_get_data(resampled) ;
01157 pxbounds = cpl_vector_get_data_const(xbounds) ;
01158 xhires = cpl_bivector_get_x_const(hires) ;
01159 yhires = cpl_bivector_get_y_const(hires) ;
01160 pxhires = cpl_vector_get_data_const(xhires) ;
01161 pyhires = cpl_vector_get_data_const(yhires) ;
01162
01163
01164 ybounds = cpl_vector_new(cpl_vector_get_size(xbounds)) ;
01165 boundary = cpl_bivector_wrap_vectors((cpl_vector*)xbounds,ybounds) ;
01166 pybounds = cpl_vector_get_data(ybounds) ;
01167
01168
01169 if (cpl_bivector_get_size(boundary) != nsamples + 1) {
01170 cpl_bivector_unwrap_vectors(boundary) ;
01171 cpl_vector_delete(ybounds) ;
01172 return -1 ;
01173 }
01174
01175
01176 itt = cpl_vector_find(xhires, pxbounds[0]);
01177
01178
01179 if (cpl_bivector_interpolate_linear(boundary, hires)) {
01180 cpl_bivector_unwrap_vectors(boundary) ;
01181 cpl_vector_delete(ybounds) ;
01182 return -1 ;
01183 }
01184
01185
01186
01187 while (pxhires[itt] < pxbounds[0]) itt++;
01188
01189 for (i=0; i < nsamples; i++) {
01190
01191
01192
01193
01194 double xlow = pxbounds[i];
01195 double x = pxhires[itt];
01196
01197 if (x > pxbounds[i+1]) x = pxbounds[i+1];
01198
01199
01200 presampled[i] = pybounds[i] * (x - xlow);
01201
01202
01203 while ((pxhires[itt] < pxbounds[i+1]) && (itt < hrsize)) {
01204 const double xprev = x;
01205 x = pxhires[itt+1];
01206 if (x > pxbounds[i+1]) x = pxbounds[i+1];
01207 presampled[i] += pyhires[itt] * (x - xlow);
01208 xlow = xprev;
01209 itt++;
01210 }
01211
01212
01213
01214 presampled[i] += pybounds[i+1] * (pxbounds[i+1] - xlow);
01215
01216
01217
01218 presampled[i] /= 2 * (pxbounds[i+1] - pxbounds[i]);
01219 }
01220 cpl_bivector_unwrap_vectors(boundary) ;
01221 cpl_vector_delete(ybounds) ;
01222 return 0 ;
01223 }
01224
01225
01226
01227
01248
01249 static cpl_error_code cpl_vector_fill_lss_profile_symmetric(cpl_vector * self,
01250 double slitw,
01251 double fwhm)
01252 {
01253
01254 const double sigma = fwhm * CPL_MATH_SIG_FWHM;
01255 const int n = cpl_vector_get_size(self);
01256 int i;
01257
01258
01259 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
01260 cpl_ensure_code(slitw > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01261 cpl_ensure_code(fwhm > 0.0, CPL_ERROR_ILLEGAL_INPUT);
01262
01263
01264
01265
01266 (void)cpl_vector_set(self, 0,
01267 (irplib_erf_antideriv(0.5*slitw + 0.5, sigma) -
01268 irplib_erf_antideriv(0.5*slitw - 0.5, sigma)) / slitw);
01269
01270 for (i = 1; i < n; i++) {
01271
01272 const double x1p = i + 0.5*slitw + 0.5;
01273 const double x1n = i - 0.5*slitw + 0.5;
01274 const double x0p = i + 0.5*slitw - 0.5;
01275 const double x0n = i - 0.5*slitw - 0.5;
01276 const double val = 0.5/slitw *
01277 (irplib_erf_antideriv(x1p, sigma) - irplib_erf_antideriv(x1n, sigma) -
01278 irplib_erf_antideriv(x0p, sigma) + irplib_erf_antideriv(x0n, sigma));
01279 (void)cpl_vector_set(self, i, val);
01280 }
01281
01282 return CPL_ERROR_NONE;
01283 }