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
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #include <irplib_wlxcorr.h>
00037
00038 #include <irplib_wavecal_impl.h>
00039
00040 #include <cpl_plot.h>
00041
00042 #include <math.h>
00043 #include <float.h>
00044
00045
00046 #ifndef CPL_SIZE_FORMAT
00047 #define CPL_SIZE_FORMAT "d"
00048 #define cpl_size int
00049 #endif
00050
00051
00052
00053
00054
00058
00059
00060
00061
00062
00063
00064
00065 static void irplib_wlxcorr_best_poly_test(void);
00066 static void irplib_wlxcorr_best_poly_test_one(int, int, cpl_boolean, int, int);
00067 static void irplib_wlxcorr_convolve_create_kernel_test(void);
00068 static void irplib_wlxcorr_convolve_create_kernel_test_one(double, double);
00069 static double irplib_wlcalib_lss(double, double, double);
00070 static void irplib_wavecal_profile_compare(int, double, double);
00071
00072
00073
00077
00078
00079
00080
00081
00082 int main(void)
00083 {
00084
00085 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
00086
00087 irplib_wavecal_profile_compare(100, 4.0, 4.0);
00088 irplib_wlxcorr_convolve_create_kernel_test();
00089 irplib_wlxcorr_best_poly_test();
00090
00091 return cpl_test_end(0);
00092 }
00093
00094
00095 static void irplib_wlxcorr_best_poly_test(void)
00096 {
00097 cpl_polynomial * poly;
00098 const cpl_boolean do_bench = cpl_msg_get_level() <= CPL_MSG_INFO
00099 ? CPL_TRUE : CPL_FALSE;
00100 const int spec_size = do_bench ? 1024 : 256;
00101 const int nreps = do_bench ? 3 : 1;
00102 const int nsamples = do_bench ? 30 : 10;
00103
00104
00105
00106 poly = irplib_wlxcorr_best_poly(NULL, NULL, 1, NULL, NULL, 1, 1.0, 1.0,
00107 NULL, NULL, NULL);
00108 cpl_test_error(CPL_ERROR_NULL_INPUT);
00109 cpl_test_null( poly );
00110
00111 #if 1
00112
00113 irplib_wlxcorr_best_poly_test_one(spec_size, spec_size*10, CPL_TRUE,
00114 nsamples, nreps);
00115 #endif
00116
00117
00118 irplib_wlxcorr_best_poly_test_one(spec_size, spec_size/50, CPL_FALSE,
00119 nsamples, nreps);
00120 }
00121
00122 static void irplib_wlxcorr_best_poly_test_one(int spec_size, int cat_size,
00123 cpl_boolean do_resample,
00124 int nsamples, int nreps)
00125 {
00126 const int degree = 2;
00127 cpl_vector * spectrum = cpl_vector_new(spec_size);
00128 cpl_bivector * catalog = cpl_bivector_new(cat_size);
00129 cpl_polynomial * true_poly = cpl_polynomial_new(1);
00130 cpl_polynomial * guess_poly = cpl_polynomial_new(1);
00131 cpl_vector * wl_err = cpl_vector_new(degree+1);
00132 double xc;
00133 const double slitw = 2.0;
00134 const double fwhm = 2.0;
00135 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00136 const double rel_error = 0.05;
00137
00138
00139 const double temp_bb = 253.0;
00140
00141 const double b_true = 2e-6;
00142 const double a_true = 48e-6 / spec_size;
00143
00144 const double a_error = a_true * rel_error;
00145 const double b_error = b_true * rel_error;
00146 const double a = a_true + a_error;
00147 const double b = b_true + b_error;
00148 double wl_errmax;
00149 cpl_size pow_ind;
00150 int i;
00151 FILE * stream = cpl_msg_get_level() > CPL_MSG_INFO
00152 ? fopen("/dev/null", "a") : stdout;
00153
00154
00155 cpl_test_nonnull( stream );
00156
00157
00158
00159 pow_ind = 1;
00160 cpl_polynomial_set_coeff(true_poly, &pow_ind, a_true);
00161 cpl_polynomial_set_coeff(guess_poly, &pow_ind, a);
00162 pow_ind = 0;
00163 cpl_polynomial_set_coeff(true_poly, &pow_ind, b_true);
00164 cpl_polynomial_set_coeff(guess_poly, &pow_ind, b);
00165
00166 cpl_msg_info(cpl_func, "First guess polynomial:");
00167 cpl_polynomial_dump(guess_poly, stream);
00168
00169
00170 cpl_test_zero(cpl_polynomial_shift_1d(guess_poly, 0, 25.0));
00171
00172 cpl_msg_info(cpl_func, "True polynomial:");
00173 cpl_polynomial_dump(true_poly, stream);
00174
00175
00176 if (do_resample) {
00177 cpl_vector * evalpoints = cpl_vector_new(spec_size);
00178
00179
00180 cpl_vector_fill_polynomial(evalpoints, true_poly, 1.0, 1.0);
00181
00182
00183
00184 cpl_vector_fill_polynomial(cpl_bivector_get_x(catalog), true_poly,
00185 -1.0, 1.5 * spec_size / cat_size);
00186
00187 cpl_photom_fill_blackbody(cpl_bivector_get_y(catalog), CPL_UNIT_LESS,
00188 cpl_bivector_get_x_const(catalog),
00189 CPL_UNIT_LENGTH, temp_bb);
00190
00191 cpl_photom_fill_blackbody(spectrum, CPL_UNIT_LESS,
00192 evalpoints, CPL_UNIT_LENGTH, temp_bb);
00193
00194 cpl_vector_delete(evalpoints);
00195
00196 } else {
00197
00198 double * dx = cpl_bivector_get_x_data(catalog);
00199 double * dy = cpl_bivector_get_y_data(catalog);
00200
00201 for (i = 0; i < cat_size; i++) {
00202 const double wli = cpl_polynomial_eval_1d(true_poly, 3.0 * i * i
00203 -10.0, NULL);
00204
00205 dx[i] = wli;
00206 dy[i] = sin(i * CPL_MATH_PI / cat_size);
00207
00208 }
00209
00210 irplib_vector_fill_line_spectrum_model(spectrum, NULL, NULL, true_poly,
00211 catalog, slitw, fwhm, xtrunc,
00212 0, CPL_FALSE, CPL_FALSE, NULL);
00213 cpl_test_error(CPL_ERROR_NONE);
00214 }
00215
00216
00217
00218 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00219 cpl_plot_bivector( "", "t 'Catalog' w lines", "", catalog);
00220 cpl_plot_vector( "", "t 'Spectrum' w lines", "", spectrum);
00221 }
00222
00223
00224
00225
00226 wl_errmax = cpl_polynomial_eval_1d(guess_poly, spec_size, NULL)
00227 - cpl_polynomial_eval_1d(true_poly, spec_size, NULL);
00228 cpl_vector_fill(wl_err, 2.0 * wl_errmax);
00229
00230
00231
00232 for (i=0; i < nreps; i++) {
00233 cpl_table * wl_res;
00234 cpl_vector * xcorrs;
00235 cpl_polynomial * poly
00236 = irplib_wlxcorr_best_poly(spectrum, catalog, degree,
00237 guess_poly, wl_err, nsamples,
00238 slitw, fwhm, &xc, &wl_res, &xcorrs);
00239 cpl_test_nonnull(poly);
00240 cpl_test_error(CPL_ERROR_NONE);
00241
00242 if (i == 0 && poly != NULL) {
00243 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00244 const char * labels[] = {IRPLIB_WLXCORR_COL_WAVELENGTH,
00245 IRPLIB_WLXCORR_COL_CAT_INIT,
00246 IRPLIB_WLXCORR_COL_CAT_FINAL,
00247 IRPLIB_WLXCORR_COL_OBS};
00248
00249 cpl_plot_vector( "", "t 'X corr values' w lines", "", xcorrs);
00250
00251 cpl_test_zero(cpl_plot_columns("", "", "", wl_res, labels, 4));
00252 }
00253
00254 cpl_msg_info(cpl_func, "Corrected polynomial:");
00255 cpl_polynomial_dump(poly, stream);
00256
00257
00258
00259 cpl_test_zero(cpl_polynomial_derivative(poly, 0));
00260 cpl_test_leq(0.0, a_true * cpl_polynomial_eval_1d(poly, 1.0, NULL));
00261 cpl_test_leq(0.0, a_true
00262 * cpl_polynomial_eval_1d(poly, 0.5 * spec_size, NULL));
00263 cpl_test_leq(0.0, a_true
00264 * cpl_polynomial_eval_1d(poly, spec_size, NULL));
00265
00266 cpl_test_error(CPL_ERROR_NONE);
00267
00268 }
00269
00270 cpl_table_delete(wl_res);
00271 cpl_vector_delete(xcorrs);
00272 cpl_polynomial_delete(poly);
00273 }
00274
00275 cpl_vector_delete(wl_err);
00276 cpl_vector_delete(spectrum);
00277 cpl_bivector_delete(catalog);
00278 cpl_polynomial_delete(true_poly);
00279 cpl_polynomial_delete(guess_poly);
00280 cpl_test_error(CPL_ERROR_NONE);
00281
00282 if (stream != stdout) cpl_test_zero( fclose(stream) );
00283
00284 return;
00285 }
00286
00287
00288 static void irplib_wlxcorr_convolve_create_kernel_test_one(double slitw,
00289 double fwhm)
00290 {
00291
00292 cpl_vector * kernel;
00293 double sum = 0.0;
00294
00295 const double maxval = irplib_wlcalib_lss(0.0, slitw, fwhm);
00296 double prev = maxval;
00297 int n, i;
00298
00299 cpl_msg_info(cpl_func, "Slit-width=%g, FWHM=%g", slitw, fwhm);
00300
00301 kernel = irplib_wlxcorr_convolve_create_kernel(0.0, fwhm);
00302
00303 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
00304 cpl_test_null(kernel);
00305
00306 kernel = irplib_wlxcorr_convolve_create_kernel(slitw, 0.0);
00307
00308 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
00309 cpl_test_null(kernel);
00310
00311 kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00312
00313 cpl_test_nonnull(kernel);
00314
00315 n = cpl_vector_get_size(kernel);
00316
00317 for (i = 0; i < n; i++) {
00318 const double val = cpl_vector_get(kernel, i);
00319 sum += i ? 2.0*val : val;
00320
00321
00322 cpl_test_leq(0.0, val);
00323
00324
00325 cpl_test_leq(val, prev);
00326
00327 if (i > 0) {
00328
00329
00330 cpl_test_leq(val, irplib_wlcalib_lss(i - 0.5, slitw, fwhm));
00331 cpl_test_leq(irplib_wlcalib_lss(i + 0.5, slitw, fwhm), val);
00332 }
00333
00334
00335 if ((double)i < 0.5 * slitw) {
00336
00337
00338 cpl_test_leq(0.5 * maxval, val);
00339 } else if (val < 0.5 * maxval) {
00340
00341
00342 cpl_test_leq(0.5*slitw, (double)i);
00343 }
00344
00345 prev = val;
00346 }
00347
00348
00349 cpl_test_abs(sum, 1.0, 1e-5);
00350
00351 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00352 char * title = cpl_sprintf("t 'LSS profile, slitw=%g, fwhm=%g' "
00353 "w linespoints", slitw, fwhm);
00354 cpl_plot_vector("set grid;", title, "", kernel);
00355 cpl_free(title);
00356 }
00357
00358 cpl_vector_delete(kernel);
00359 }
00360
00361 static void irplib_wlxcorr_convolve_create_kernel_test(void)
00362 {
00363
00364 irplib_wlxcorr_convolve_create_kernel_test_one(0.86, 2.0);
00365 irplib_wlxcorr_convolve_create_kernel_test_one(1.72, 3.0);
00366 irplib_wlxcorr_convolve_create_kernel_test_one(40.0, 2.0);
00367 irplib_wlxcorr_convolve_create_kernel_test_one(3.0, 40.0);
00368
00369 }
00370
00371
00372
00382
00383 static double irplib_wlcalib_lss(double x, double slitw, double fwhm)
00384 {
00385 const double sigmasqrt2 = fwhm * CPL_MATH_SIG_FWHM * CPL_MATH_SQRT2;
00386 const double result = 0.5 / slitw *
00387 (erf((x+0.5*slitw)/sigmasqrt2) - erf((x-0.5*slitw)/sigmasqrt2));
00388
00389 cpl_test_lt(0.0, slitw);
00390 cpl_test_lt(0.0, sigmasqrt2);
00391
00392
00393 return result < 0.0 ? 0.0 : result;
00394
00395 }
00396
00397
00398
00407
00408 static void irplib_wavecal_profile_compare(int spec_size, double slitw,
00409 double fwhm)
00410 {
00411
00412 cpl_vector * spectrum1 = cpl_vector_new(spec_size);
00413 cpl_vector * spectrum2 = cpl_vector_new(spec_size);
00414 cpl_bivector * catalog = cpl_bivector_new(2);
00415 cpl_polynomial * dispersion = cpl_polynomial_new(1);
00416 const double a = 1.0;
00417 const double b = 100.0;
00418 const double xtrunc = 0.5 * slitw + 2.0 * fwhm * CPL_MATH_SIG_FWHM;
00419 double mean;
00420 cpl_error_code error;
00421 cpl_size pow_ind;
00422
00423
00424 pow_ind = 1;
00425 cpl_polynomial_set_coeff(dispersion, &pow_ind, a);
00426 pow_ind = 0;
00427 cpl_polynomial_set_coeff(dispersion, &pow_ind, b);
00428
00429 cpl_vector_set(cpl_bivector_get_x(catalog), 0, b + spec_size / 3.0);
00430 cpl_vector_set(cpl_bivector_get_y(catalog), 0, 100);
00431
00432 cpl_vector_set(cpl_bivector_get_x(catalog), 1, b + spec_size / 1.5);
00433 cpl_vector_set(cpl_bivector_get_y(catalog), 1, 100);
00434
00435 cpl_test_error(CPL_ERROR_NONE);
00436
00437 error = irplib_vector_fill_line_spectrum_model(spectrum1, NULL, NULL,
00438 dispersion, catalog, slitw,
00439 fwhm, xtrunc, 0, CPL_FALSE,
00440 CPL_FALSE, NULL);
00441 cpl_test_error(CPL_ERROR_NONE);
00442 cpl_test_eq(error, CPL_ERROR_NONE);
00443
00444
00445 error = irplib_vector_fill_line_spectrum_model(spectrum2, NULL, NULL,
00446 dispersion, catalog, slitw,
00447 fwhm, xtrunc, 0, CPL_TRUE,
00448 CPL_FALSE, NULL);
00449
00450 cpl_test_error(CPL_ERROR_NONE);
00451 cpl_test_eq(error, CPL_ERROR_NONE);
00452
00453 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00454 error = cpl_plot_vector("set grid;", "t 'Spectrum' w lines", "",
00455 spectrum1);
00456 cpl_test_error(CPL_ERROR_NONE);
00457 cpl_test_eq(error, CPL_ERROR_NONE);
00458 error = cpl_plot_vector("set grid;", "t 'Spectrum' w lines", "",
00459 spectrum2);
00460 cpl_test_error(CPL_ERROR_NONE);
00461 cpl_test_eq(error, CPL_ERROR_NONE);
00462 }
00463
00464 cpl_vector_subtract(spectrum1, spectrum2);
00465 mean = cpl_vector_get_mean(spectrum1);
00466 if (mean != 0.0) {
00467 cpl_msg_info(cpl_func, "Error: %g", mean);
00468 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00469 error = cpl_plot_vector("set grid;", "t 'Spectrum error' w lines",
00470 "", spectrum1);
00471 cpl_test_error(CPL_ERROR_NONE);
00472 cpl_test_eq(error, CPL_ERROR_NONE);
00473 }
00474 }
00475
00476 cpl_polynomial_delete(dispersion);
00477 cpl_vector_delete(spectrum1);
00478 cpl_vector_delete(spectrum2);
00479 cpl_bivector_delete(catalog);
00480
00481 cpl_test_error(CPL_ERROR_NONE);
00482
00483 }