00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023
00024
00025
00026
00027
00028 #include <xsh_fit.h>
00029 #include <tests.h>
00030 #include <cpl_test.h>
00031 #include <math.h>
00032 #include <float.h>
00033
00034
00035
00036
00037
00038 #define MODULE_ID "XSH_FIT"
00039
00040
00041 #define XSH_TEST_MARGIN 2.0
00042
00043 #define xsh_test(expr) \
00044 do { \
00045 if (!(expr)) assure(0, CPL_ERROR_ILLEGAL_OUTPUT, "Test failed"); \
00046 } while(0) \
00047
00048 #define xsh_test_tol(first, second, tolerance) \
00049 do { \
00050 const double xsh_test_first = (double)(first); \
00051 const double xsh_test_second = (double)(second); \
00052 const double xsh_test_tolerance = (double)(tolerance); \
00053 \
00054 const double xsh_test_margin = (double)(XSH_TEST_MARGIN); \
00055 \
00056 if (!(fabs(xsh_test_first - xsh_test_second) <= \
00057 xsh_test_tolerance * xsh_test_margin)) \
00058 { \
00059 xsh_test(0); \
00060 } \
00061 } while (0)
00062
00063 #define IMAGESZ 10
00064 #define NFRAMES 10
00065 #define IMAGESZFIT 256
00066
00067 #define xsh_fit_imagelist_is_zero(A, B) \
00068 xsh_fit_imagelist_is_zero_macro(A, B)
00069 #define xsh_fit_image_is_zero(A, B) \
00070 xsh_fit_image_is_zero_macro(A, B)
00071
00072
00073
00078
00079
00080
00081
00082
00083
00084 static void xsh_fit_imagelist_polynomial_tests(void);
00085 static void xsh_fit_imagelist_is_zero_macro(const cpl_imagelist *, double);
00086 static void xsh_fit_image_is_zero_macro(const cpl_image *, double);
00087
00088 static cpl_error_code xsh_image_fill_noise_uniform(cpl_image *, double,
00089 double);
00090
00091
00092
00096
00097
00098
00099 int main(void)
00100 {
00101 int ret=0;
00102
00103 TESTS_INIT(MODULE_ID);
00104
00105 check( xsh_fit_imagelist_polynomial_tests() );
00106
00107 cleanup:
00108 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00109 xsh_error_dump(CPL_MSG_ERROR);
00110 ret= 1;
00111 }
00112 TEST_END();
00113 return ret;
00114 }
00115
00116
00117 static void xsh_fit_imagelist_polynomial_tests(void)
00118 {
00119
00120 const double ditval[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
00121 cpl_imagelist * fit;
00122 cpl_imagelist * input;
00123 cpl_image * dfiterror
00124 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_DOUBLE);
00125 cpl_image * ffiterror
00126 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_FLOAT);
00127 cpl_image * ifiterror
00128 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_INT);
00129 const int ndits = (int)(sizeof(ditval)/sizeof(double));
00130 cpl_vector * vdit = cpl_vector_wrap(ndits, (double*)ditval);
00131 const double sqsum = 204.0;
00132 const double mytol = 2.76 * FLT_EPSILON;
00133 int i;
00134 const cpl_type pixel_type[] = {CPL_TYPE_DOUBLE, CPL_TYPE_FLOAT, CPL_TYPE_INT};
00135 int ntest;
00136
00137
00138 cpl_msg_info(cpl_func, "Testing with %d %d X %d images",
00139 ndits, IMAGESZFIT, IMAGESZFIT);
00140
00141 fit = xsh_fit_imagelist_polynomial(NULL, NULL, 0, 0, CPL_FALSE, NULL);
00142 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
00143 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00144 cpl_error_reset();
00145 xsh_test( fit == NULL );
00146 cpl_imagelist_delete(fit);
00147
00148 input = cpl_imagelist_new();
00149 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 0, CPL_FALSE, NULL);
00150 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
00151 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00152 cpl_error_reset();
00153 xsh_test( fit == NULL );
00154 cpl_imagelist_delete(fit);
00155
00156 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, 1, CPL_FALSE, NULL);
00157 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
00158 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00159 cpl_error_reset();
00160 xsh_test( fit == NULL );
00161 cpl_imagelist_delete(fit);
00162
00163
00164 for (ntest = 0; ntest < 3; ntest++) {
00165
00166 const cpl_type test_type = pixel_type[ntest];
00167
00168 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZ, test_type);
00169
00170
00171 cpl_msg_info(cpl_func, "Fitting with pixel type %u",
00172 (unsigned)test_type);
00173
00174 xsh_test(!cpl_imagelist_set(input, image, 0));
00175
00176 image = cpl_image_duplicate(image);
00177
00178 xsh_test(!xsh_image_fill_noise_uniform(image, 1.0, 20.0));
00179
00180 xsh_test(!cpl_image_multiply_scalar(image, ditval[1]));
00181
00182 xsh_test(!cpl_imagelist_set(input, image, 1));
00183
00184
00185 for (i=2; i < ndits; i++) {
00186
00187 image
00188 = cpl_image_multiply_scalar_create(cpl_imagelist_get(input, 1),
00189 ditval[i]);
00190
00191 xsh_test(!cpl_imagelist_set(input, image, i));
00192
00193 }
00194
00195 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits-1, CPL_FALSE, NULL);
00196
00197 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00198 xsh_test( cpl_imagelist_get_size(fit) == ndits - 1 );
00199
00200
00201
00202 xsh_test(!cpl_image_divide(cpl_imagelist_get(fit, 0),
00203 cpl_imagelist_get(input, 1)));
00204
00205
00206 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0), 1.0));
00207
00208 xsh_fit_imagelist_is_zero(fit, IMAGESZFIT * mytol);
00209
00210 cpl_imagelist_delete(fit);
00211 cpl_imagelist_delete(input);
00212 input = cpl_imagelist_new();
00213 }
00214
00215
00216 for (i=0; i < ndits; i++) {
00217 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZFIT,
00218 CPL_TYPE_DOUBLE);
00219
00220 xsh_test(!cpl_image_add_scalar(image, ditval[i]*ditval[i]));
00221
00222 xsh_test(!cpl_imagelist_set(input, image, i));
00223
00224 cpl_msg_debug(cpl_func, "Dit and mean of input image no. %d: %g %g",
00225 i, ditval[i], cpl_image_get_mean(image));
00226 }
00227
00228 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits, CPL_FALSE,
00229 NULL);
00230 if (cpl_error_get_code() != CPL_ERROR_NONE ) {
00231
00232 xsh_test( cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX );
00233 cpl_error_reset();
00234 xsh_test( fit == NULL );
00235 }
00236 cpl_imagelist_delete(fit);
00237
00238
00239 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, 0, CPL_FALSE, NULL);
00240 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
00241 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00242 cpl_error_reset();
00243 xsh_test( fit == NULL );
00244 cpl_imagelist_delete(fit);
00245
00246
00247 fit = xsh_fit_imagelist_polynomial(vdit, input, -1, 0, CPL_FALSE, NULL);
00248 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
00249 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00250 cpl_error_reset();
00251 xsh_test( fit == NULL );
00252 cpl_imagelist_delete(fit);
00253
00254
00255
00256
00257 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 2, CPL_TRUE,
00258 ifiterror);
00259
00260 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00261 xsh_test( cpl_imagelist_get_size(fit) == 3 );
00262 xsh_fit_image_is_zero(ifiterror, mytol);
00263
00264 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2), 1.0));
00265
00266 xsh_fit_imagelist_is_zero(fit, mytol);
00267
00268 cpl_imagelist_delete(fit);
00269
00270
00271
00272
00273
00274 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, ndits-1, CPL_TRUE,
00275 ifiterror);
00276
00277 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00278 xsh_test( cpl_imagelist_get_size(fit) == ndits );
00279 xsh_fit_image_is_zero(ifiterror, mytol);
00280
00281 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2), 1.0));
00282
00283 xsh_fit_imagelist_is_zero(fit, mytol);
00284
00285 cpl_imagelist_delete(fit);
00286
00287
00288 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits-1, CPL_FALSE,
00289 dfiterror);
00290
00291 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00292 xsh_test( cpl_imagelist_get_size(fit) == ndits-1 );
00293
00294 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 1), 1.0));
00295
00296 xsh_fit_imagelist_is_zero(fit, mytol);
00297 xsh_fit_image_is_zero(dfiterror, mytol);
00298
00299 cpl_imagelist_delete(fit);
00300
00301
00302 fit = xsh_fit_imagelist_polynomial(vdit, input, 2, ndits, CPL_TRUE,
00303 ffiterror);
00304
00305 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00306 xsh_test( cpl_imagelist_get_size(fit) == ndits-1 );
00307
00308 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0), 1.0));
00309
00310 xsh_fit_imagelist_is_zero(fit, mytol);
00311 xsh_fit_image_is_zero(ffiterror, mytol);
00312
00313 cpl_imagelist_delete(fit);
00314
00315
00316 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 0, CPL_TRUE,
00317 dfiterror);
00318
00319 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
00320 xsh_test( cpl_imagelist_get_size(fit) == 1 );
00321
00322 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0),
00323 sqsum/(double)ndits));
00324
00325 xsh_fit_imagelist_is_zero(fit, mytol);
00326
00327 cpl_imagelist_delete(fit);
00328
00329 cpl_imagelist_delete(input);
00330
00331 (void)cpl_vector_unwrap(vdit);
00332
00333
00334
00335
00336 input = cpl_imagelist_new();
00337
00338 for (ntest = 1; ntest <= ndits; ntest++) {
00339 const double gain = 4.0;
00340
00341 cpl_msg_info(cpl_func, "Fitting %d coefficients to as many points",
00342 ntest);
00343
00344 vdit = cpl_vector_wrap(ntest, (double*)ditval);
00345
00346
00347 for (i = ntest - 1; i < ntest; i++) {
00348 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZFIT,
00349 CPL_TYPE_FLOAT);
00350
00351 xsh_test(!cpl_image_add_scalar(image, gain * ditval[i]*ditval[i]));
00352
00353 xsh_test(!cpl_imagelist_set(input, image, i));
00354
00355 cpl_msg_debug(cpl_func, "Dit and mean of input image no. %d: %g %g",
00356 i, ditval[i], cpl_image_get_mean(image));
00357 }
00358
00359
00360
00361
00362 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, ntest-1, CPL_TRUE,
00363 ffiterror);
00364
00365 (void)cpl_vector_unwrap(vdit);
00366
00367 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00368 xsh_test( fit == NULL );
00369
00370 cpl_msg_info(cpl_func, "Could not fit %d coefficients to as many "
00371 "points", ntest);
00372
00373 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
00374 cpl_error_reset();
00375
00376 break;
00377 }
00378
00379 xsh_test( cpl_imagelist_get_size(fit) == ntest );
00380
00381 if (ntest == 2) {
00382 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 1),
00383 gain));
00384 } else if (ntest > 2) {
00385 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2),
00386 gain));
00387 }
00388
00389 xsh_fit_imagelist_is_zero(fit, mytol);
00390
00391 xsh_fit_image_is_zero(ffiterror, mytol);
00392
00393 cpl_imagelist_delete(fit);
00394 }
00395
00396 cpl_imagelist_delete(input);
00397
00398
00399 cpl_image_delete(dfiterror);
00400 cpl_image_delete(ffiterror);
00401 cpl_image_delete(ifiterror);
00402
00403 cleanup:
00404 return;
00405 }
00406
00407
00408
00409
00417
00418 static void xsh_fit_imagelist_is_zero_macro(const cpl_imagelist * self,
00419 double tol)
00420 {
00421
00422 const int n = cpl_imagelist_get_size(self);
00423 int i;
00424
00425 for (i = 0; i < n; i++) {
00426
00427 check(
00428 xsh_fit_image_is_zero_macro(cpl_imagelist_get_const( self, i),
00429 tol));
00430
00431 }
00432 cleanup:
00433 return;
00434 }
00435
00436
00437
00446
00447 static void xsh_fit_image_is_zero_macro(const cpl_image * self, double tol)
00448 {
00449
00450 cpl_stats * stats = cpl_stats_new_from_image(self,
00451 CPL_STATS_MIN | CPL_STATS_MAX
00452 | CPL_STATS_MEAN);
00453
00454 const double mymin = cpl_stats_get_min(stats);
00455 const double mymax = cpl_stats_get_max(stats);
00456
00457 xsh_test_tol( mymin, 0.0, tol );
00458 xsh_test_tol( mymax, 0.0, tol );
00459
00460 cleanup:
00461 cpl_stats_delete(stats);
00462 return;
00463
00464 }
00465
00466
00467
00480
00481 static cpl_error_code xsh_image_fill_noise_uniform(cpl_image * self,
00482 double min_pix,
00483 double max_pix)
00484 {
00485
00486 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00487
00488 if (cpl_image_get_type(self) == CPL_TYPE_INT) {
00489
00490 int * pi = cpl_image_get_data_int(self);
00491 const int nx = cpl_image_get_size_x(self);
00492 const int ny = cpl_image_get_size_y(self);
00493 int i, j;
00494
00495
00496 for (j=0 ; j < ny ; j++) {
00497 for (i=0 ; i < nx ; i++) {
00498 const double value
00499 = min_pix + (max_pix * (double)rand())/(double)RAND_MAX;
00500
00501 pi[i + j * nx] = (int) value;
00502 }
00503 }
00504 } else {
00505
00506 const cpl_error_code error
00507 = cpl_image_fill_noise_uniform(self, min_pix, max_pix);
00508 cpl_ensure_code(!error, error);
00509 }
00510
00511 return CPL_ERROR_NONE;
00512 }