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
00062
00063
00067
00068
00069
00070
00071
00072 int main(void)
00073 {
00074
00075 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
00076
00077 irplib_wlxcorr_convolve_create_kernel_test();
00078 irplib_wlxcorr_best_poly_test();
00079
00080 return cpl_test_end(0);
00081 }
00082
00083
00084 static void irplib_wlxcorr_best_poly_test(void)
00085 {
00086 cpl_polynomial * poly;
00087 const cpl_boolean do_bench = cpl_msg_get_level() <= CPL_MSG_INFO
00088 ? CPL_TRUE : CPL_FALSE;
00089 const int spec_size = do_bench ? 1024 : 256;
00090 const int nreps = do_bench ? 3 : 1;
00091 const int nsamples = do_bench ? 30 : 10;
00092
00093
00094
00095 poly = irplib_wlxcorr_best_poly(NULL, NULL, 1, NULL, NULL, 1, 1.0, 1.0,
00096 NULL, NULL, NULL);
00097 cpl_test_error(CPL_ERROR_NULL_INPUT);
00098 cpl_test_null( poly );
00099
00100 #if 1
00101
00102 irplib_wlxcorr_best_poly_test_one(spec_size, spec_size*10, CPL_TRUE,
00103 nsamples, nreps);
00104 #endif
00105
00106
00107 irplib_wlxcorr_best_poly_test_one(spec_size, spec_size/50, CPL_FALSE,
00108 nsamples, nreps);
00109 }
00110
00111 static void irplib_wlxcorr_best_poly_test_one(int spec_size, int cat_size,
00112 cpl_boolean do_resample,
00113 int nsamples, int nreps)
00114 {
00115 const int degree = 2;
00116 cpl_vector * spectrum = cpl_vector_new(spec_size);
00117 cpl_bivector * catalog = cpl_bivector_new(cat_size);
00118 cpl_polynomial * true_poly = cpl_polynomial_new(1);
00119 cpl_polynomial * guess_poly = cpl_polynomial_new(1);
00120 cpl_vector * wl_err = cpl_vector_new(degree+1);
00121 double xc;
00122 const double slitw = 2.0;
00123 const double fwhm = 2.0;
00124 const double xtrunc = 0.5 * slitw + 5.0 * fwhm * CPL_MATH_SIG_FWHM;
00125 const double rel_error = 0.05;
00126
00127
00128 const double temp_bb = 253.0;
00129
00130 const double b_true = 2e-6;
00131 const double a_true = 48e-6 / spec_size;
00132
00133 const double a_error = a_true * rel_error;
00134 const double b_error = b_true * rel_error;
00135 const double a = a_true + a_error;
00136 const double b = b_true + b_error;
00137 double wl_errmax;
00138 int pow_ind;
00139 int i;
00140 FILE * stream = cpl_msg_get_level() > CPL_MSG_INFO
00141 ? fopen("/dev/null", "a") : stdout;
00142
00143
00144 cpl_test_nonnull( stream );
00145
00146
00147
00148 pow_ind = 1;
00149 cpl_polynomial_set_coeff(true_poly, &pow_ind, a_true);
00150 cpl_polynomial_set_coeff(guess_poly, &pow_ind, a);
00151 pow_ind = 0;
00152 cpl_polynomial_set_coeff(true_poly, &pow_ind, b_true);
00153 cpl_polynomial_set_coeff(guess_poly, &pow_ind, b);
00154
00155 cpl_msg_info(cpl_func, "First guess polynomial:");
00156 cpl_polynomial_dump(guess_poly, stream);
00157
00158
00159 #if defined CPL_VERSION_CODE && CPL_VERSION_CODE > CPL_VERSION(4, 5, 0)
00160 cpl_test_zero(cpl_polynomial_shift_1d(guess_poly, 0, 25.0));
00161 #else
00162 cpl_test_zero(cpl_polynomial_shift_1d(guess_poly, 25.0));
00163 #endif
00164
00165 cpl_msg_info(cpl_func, "True polynomial:");
00166 cpl_polynomial_dump(true_poly, stream);
00167
00168
00169 if (do_resample) {
00170 cpl_vector * evalpoints = cpl_vector_new(spec_size);
00171
00172
00173 cpl_vector_fill_polynomial(evalpoints, true_poly, 1.0, 1.0);
00174
00175
00176
00177 cpl_vector_fill_polynomial(cpl_bivector_get_x(catalog), true_poly,
00178 -1.0, 1.5 * spec_size / cat_size);
00179
00180 cpl_photom_fill_blackbody(cpl_bivector_get_y(catalog), CPL_UNIT_LESS,
00181 cpl_bivector_get_x_const(catalog),
00182 CPL_UNIT_LENGTH, temp_bb);
00183
00184 cpl_photom_fill_blackbody(spectrum, CPL_UNIT_LESS,
00185 evalpoints, CPL_UNIT_LENGTH, temp_bb);
00186
00187 cpl_vector_delete(evalpoints);
00188
00189 } else {
00190
00191 double * dx = cpl_bivector_get_x_data(catalog);
00192 double * dy = cpl_bivector_get_y_data(catalog);
00193
00194 for (i = 0; i < cat_size; i++) {
00195 const double wli = cpl_polynomial_eval_1d(true_poly, 3.0 * i * i
00196 -10.0, NULL);
00197
00198 dx[i] = wli;
00199 dy[i] = sin(i * CPL_MATH_PI / cat_size);
00200
00201 }
00202
00203 irplib_vector_fill_line_spectrum_model(spectrum, NULL, true_poly,
00204 catalog, slitw, fwhm, xtrunc, 0);
00205 }
00206
00207
00208
00209 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00210 cpl_plot_bivector( "", "t 'Catalog' w lines", "", catalog);
00211 cpl_plot_vector( "", "t 'Spectrum' w lines", "", spectrum);
00212 }
00213
00214
00215
00216
00217 wl_errmax = cpl_polynomial_eval_1d(guess_poly, spec_size, NULL)
00218 - cpl_polynomial_eval_1d(true_poly, spec_size, NULL);
00219 cpl_vector_fill(wl_err, 2.0 * wl_errmax);
00220
00221
00222
00223 for (i=0; i < nreps; i++) {
00224 cpl_table * wl_res;
00225 cpl_vector * xcorrs;
00226 cpl_polynomial * poly
00227 = irplib_wlxcorr_best_poly(spectrum, catalog, degree,
00228 guess_poly, wl_err, nsamples,
00229 slitw, fwhm, &xc, &wl_res, &xcorrs);
00230 cpl_test_nonnull(poly);
00231 cpl_test_error(CPL_ERROR_NONE);
00232
00233 if (i == 0 && poly != NULL) {
00234 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00235 const char * labels[] = {IRPLIB_WLXCORR_COL_WAVELENGTH,
00236 IRPLIB_WLXCORR_COL_CAT_INIT,
00237 IRPLIB_WLXCORR_COL_CAT_FINAL,
00238 IRPLIB_WLXCORR_COL_OBS};
00239
00240 cpl_plot_vector( "", "t 'X corr values' w lines", "", xcorrs);
00241
00242 cpl_test_zero(cpl_plot_columns("", "", "", wl_res, labels, 4));
00243 }
00244
00245 cpl_msg_info(cpl_func, "Corrected polynomial:");
00246 cpl_polynomial_dump(poly, stream);
00247
00248
00249
00250 cpl_test_zero(cpl_polynomial_derivative(poly, 0));
00251 cpl_test_leq(0.0, a_true * cpl_polynomial_eval_1d(poly, 1.0, NULL));
00252 cpl_test_leq(0.0, a_true
00253 * cpl_polynomial_eval_1d(poly, 0.5 * spec_size, NULL));
00254 cpl_test_leq(0.0, a_true
00255 * cpl_polynomial_eval_1d(poly, spec_size, NULL));
00256
00257 cpl_test_error(CPL_ERROR_NONE);
00258
00259 }
00260
00261 cpl_table_delete(wl_res);
00262 cpl_vector_delete(xcorrs);
00263 cpl_polynomial_delete(poly);
00264 }
00265
00266 cpl_vector_delete(wl_err);
00267 cpl_vector_delete(spectrum);
00268 cpl_bivector_delete(catalog);
00269 cpl_polynomial_delete(true_poly);
00270 cpl_polynomial_delete(guess_poly);
00271 cpl_test_error(CPL_ERROR_NONE);
00272
00273 if (stream != stdout) cpl_test_zero( fclose(stream) );
00274
00275 return;
00276 }
00277
00278
00279 static void irplib_wlxcorr_convolve_create_kernel_test_one(double slitw,
00280 double fwhm)
00281 {
00282
00283 cpl_vector * kernel;
00284 double sum = 0.0;
00285
00286 const double maxval = irplib_wlcalib_lss(0.0, slitw, fwhm);
00287 double prev = maxval;
00288 int n, i;
00289
00290 cpl_msg_info(cpl_func, "Slit-width=%g, FWHM=%g", slitw, fwhm);
00291
00292 kernel = irplib_wlxcorr_convolve_create_kernel(0.0, fwhm);
00293
00294 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
00295 cpl_test_null(kernel);
00296
00297 kernel = irplib_wlxcorr_convolve_create_kernel(slitw, 0.0);
00298
00299 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
00300 cpl_test_null(kernel);
00301
00302 kernel = irplib_wlxcorr_convolve_create_kernel(slitw, fwhm);
00303
00304 cpl_test_nonnull(kernel);
00305
00306 n = cpl_vector_get_size(kernel);
00307
00308 for (i = 0; i < n; i++) {
00309 const double val = cpl_vector_get(kernel, i);
00310 sum += i ? 2.0*val : val;
00311
00312
00313 cpl_test_leq(0.0, val);
00314
00315
00316 cpl_test_leq(val, prev);
00317
00318 if (i > 0) {
00319
00320
00321 cpl_test_leq(val, irplib_wlcalib_lss(i - 0.5, slitw, fwhm));
00322 cpl_test_leq(irplib_wlcalib_lss(i + 0.5, slitw, fwhm), val);
00323 }
00324
00325
00326 if ((double)i < 0.5 * slitw) {
00327
00328
00329 cpl_test_leq(0.5 * maxval, val);
00330 } else if (val < 0.5 * maxval) {
00331
00332
00333 cpl_test_leq(0.5*slitw, (double)i);
00334 }
00335
00336 prev = val;
00337 }
00338
00339
00340 cpl_test_abs(sum, 1.0, 1e-5);
00341
00342 if (cpl_msg_get_level() <= CPL_MSG_DEBUG) {
00343 char * title = cpl_sprintf("t 'LSS profile, slitw=%g, fwhm=%g' "
00344 "w linespoints", slitw, fwhm);
00345 cpl_plot_vector("set grid;", title, "", kernel);
00346 cpl_free(title);
00347 }
00348
00349 cpl_vector_delete(kernel);
00350 }
00351
00352 static void irplib_wlxcorr_convolve_create_kernel_test(void)
00353 {
00354
00355 irplib_wlxcorr_convolve_create_kernel_test_one(0.86, 2.0);
00356 irplib_wlxcorr_convolve_create_kernel_test_one(1.72, 3.0);
00357 irplib_wlxcorr_convolve_create_kernel_test_one(40.0, 2.0);
00358 irplib_wlxcorr_convolve_create_kernel_test_one(3.0, 40.0);
00359
00360 }
00361
00362
00363
00373
00374 static double irplib_wlcalib_lss(double x, double slitw, double fwhm)
00375 {
00376 const double sigmasqrt2 = fwhm * CPL_MATH_SIG_FWHM * CPL_MATH_SQRT2;
00377 const double result = 0.5 / slitw *
00378 (erf((x+0.5*slitw)/sigmasqrt2) - erf((x-0.5*slitw)/sigmasqrt2));
00379
00380 cpl_test_lt(0.0, slitw);
00381 cpl_test_lt(0.0, sigmasqrt2);
00382
00383
00384 return result < 0.0 ? 0.0 : result;
00385
00386 }