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