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