X-shooter Pipeline Reference Manual 3.8.15
test-xsh_fit.c
Go to the documentation of this file.
1/* *
2 * This file is part of the ESO X-Shooter package *
3 * Copyright (C) 2004,2005 European Southern Observatory *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18 * */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24
25/*-----------------------------------------------------------------------------
26 Includes
27 -----------------------------------------------------------------------------*/
28#include <xsh_fit.h>
29#include <tests.h>
30#include <cpl_test.h>
31#include <math.h>
32#include <float.h>
33
34/*-----------------------------------------------------------------------------
35 Defines
36 -----------------------------------------------------------------------------*/
37
38#define MODULE_ID "XSH_FIT"
39
40/* Acceptable numerical error margin */
41#define XSH_TEST_MARGIN 2.0
42
43#define xsh_test(expr) \
44 do { \
45 if (!(expr)) assure(0, CPL_ERROR_ILLEGAL_OUTPUT, "Test failed"); \
46 } while(0) \
47
48#define xsh_test_tol(first, second, tolerance) \
49 do { \
50 const double xsh_test_first = (double)(first); \
51 const double xsh_test_second = (double)(second); \
52 const double xsh_test_tolerance = (double)(tolerance); \
53 /* The error margin on the tolerance */ \
54 const double xsh_test_margin = (double)(XSH_TEST_MARGIN); \
55 \
56 if (!(fabs(xsh_test_first - xsh_test_second) <= \
57 xsh_test_tolerance * xsh_test_margin)) \
58 { \
59 xsh_test(0); \
60 } \
61 } while (0)
62
63#define IMAGESZ 10
64#define NFRAMES 10
65#define IMAGESZFIT 256
66
67#define xsh_fit_imagelist_is_zero(A, B) \
68 xsh_fit_imagelist_is_zero_macro(A, B)
69#define xsh_fit_image_is_zero(A, B) \
70 xsh_fit_image_is_zero_macro(A, B)
71
72
73/*----------------------------------------------------------------------------*/
78/*----------------------------------------------------------------------------*/
79
80/*-----------------------------------------------------------------------------
81 Private Function prototypes
82 -----------------------------------------------------------------------------*/
83
85static void xsh_fit_imagelist_is_zero_macro(const cpl_imagelist *, double);
86static void xsh_fit_image_is_zero_macro(const cpl_image *, double);
87
88static cpl_error_code xsh_image_fill_noise_uniform(cpl_image *, double,
89 double);
90
91
92/*----------------------------------------------------------------------------*/
96/*----------------------------------------------------------------------------*/
97
98
99int main(void)
100{
101 int ret=0;
102
104
106
107 cleanup:
108 if (cpl_error_get_code() != CPL_ERROR_NONE) {
109 xsh_error_dump(CPL_MSG_ERROR);
110 ret= 1;
111 }
112 TEST_END();
113 return ret;
114}
115
116
118{
119
120 const double ditval[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
121 cpl_imagelist * fit;
122 cpl_imagelist * input;
123 cpl_image * dfiterror
124 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_DOUBLE);
125 cpl_image * ffiterror
126 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_FLOAT);
127 cpl_image * ifiterror
128 = cpl_image_new(IMAGESZFIT, IMAGESZFIT, CPL_TYPE_INT);
129 const int ndits = (int)(sizeof(ditval)/sizeof(double));
130 cpl_vector * vdit = cpl_vector_wrap(ndits, (double*)ditval);
131 const double sqsum = 204.0; /* Sum of squares of ditvals */
132 const double mytol = 2.76 * FLT_EPSILON;
133 int i;
134 const cpl_type pixel_type[] = {CPL_TYPE_DOUBLE, CPL_TYPE_FLOAT, CPL_TYPE_INT};
135 int ntest;
136
137
138 cpl_msg_info(cpl_func, "Testing with %d %d X %d images",
139 ndits, IMAGESZFIT, IMAGESZFIT);
140
141 fit = xsh_fit_imagelist_polynomial(NULL, NULL, 0, 0, CPL_FALSE, NULL);
142 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
143 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
144 cpl_error_reset();
145 xsh_test( fit == NULL );
146 cpl_imagelist_delete(fit);
147
148 input = cpl_imagelist_new();
149 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 0, CPL_FALSE, NULL);
150 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
151 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
152 cpl_error_reset();
153 xsh_test( fit == NULL );
154 cpl_imagelist_delete(fit);
155
156 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, 1, CPL_FALSE, NULL);
157 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
158 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
159 cpl_error_reset();
160 xsh_test( fit == NULL );
161 cpl_imagelist_delete(fit);
162
163 /* Test with all types of pixels */
164 for (ntest = 0; ntest < 3; ntest++) {
165
166 const cpl_type test_type = pixel_type[ntest];
167
168 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZ, test_type);
169
170
171 cpl_msg_info(cpl_func, "Fitting with pixel type %u",
172 (unsigned)test_type);
173
174 xsh_test(!cpl_imagelist_set(input, image, 0));
175
176 image = cpl_image_duplicate(image);
177
178 xsh_test(!xsh_image_fill_noise_uniform(image, 1.0, 20.0));
179
180 xsh_test(!cpl_image_multiply_scalar(image, ditval[1]));
181
182 xsh_test(!cpl_imagelist_set(input, image, 1));
183
184 /* A perfectly linear set */
185 for (i=2; i < ndits; i++) {
186
187 image
188 = cpl_image_multiply_scalar_create(cpl_imagelist_get(input, 1),
189 ditval[i]);
190
191 xsh_test(!cpl_imagelist_set(input, image, i));
192
193 }
194
195 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits-1, CPL_FALSE, NULL);
196
197 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
198 xsh_test( cpl_imagelist_get_size(fit) == ndits - 1 );
199
200 /* The linarity must be equal to the values in image 1
201 - normalize */
202 xsh_test(!cpl_image_divide(cpl_imagelist_get(fit, 0),
203 cpl_imagelist_get(input, 1)));
204
205 /* Subtract the expected value in the 1st image */
206 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0), 1.0));
207
209
210 cpl_imagelist_delete(fit);
211 cpl_imagelist_delete(input);
212 input = cpl_imagelist_new();
213 }
214
215 /* Create a list of images with a 2nd order function */
216 for (i=0; i < ndits; i++) {
217 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZFIT,
218 CPL_TYPE_DOUBLE);
219
220 xsh_test(!cpl_image_add_scalar(image, ditval[i]*ditval[i]));
221
222 xsh_test(!cpl_imagelist_set(input, image, i));
223
224 cpl_msg_debug(cpl_func, "Dit and mean of input image no. %d: %g %g",
225 i, ditval[i], cpl_image_get_mean(image));
226 }
227
228 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits, CPL_FALSE,
229 NULL);
230 if (cpl_error_get_code() != CPL_ERROR_NONE ) {
231 /* Fails on 32-bit intel, but not on others */
232 xsh_test( cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX );
233 cpl_error_reset();
234 xsh_test( fit == NULL );
235 }
236 cpl_imagelist_delete(fit);
237
238 /* Illegal max-degree */
239 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, 0, CPL_FALSE, NULL);
240 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
241 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
242 cpl_error_reset();
243 xsh_test( fit == NULL );
244 cpl_imagelist_delete(fit);
245
246 /* Illegal min-degree */
247 fit = xsh_fit_imagelist_polynomial(vdit, input, -1, 0, CPL_FALSE, NULL);
248 xsh_test( cpl_error_get_code() != CPL_ERROR_NONE );
249 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
250 cpl_error_reset();
251 xsh_test( fit == NULL );
252 cpl_imagelist_delete(fit);
253
254
255 /* Fit with zero-order term */
256 /* Also, try to use an integer-type image for fitting error */
257 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 2, CPL_TRUE,
258 ifiterror);
259
260 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
261 xsh_test( cpl_imagelist_get_size(fit) == 3 );
262 xsh_fit_image_is_zero(ifiterror, mytol);
263
264 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2), 1.0));
265
266 xsh_fit_imagelist_is_zero(fit, mytol);
267
268 cpl_imagelist_delete(fit);
269
270
271
272 /* Fit with zero-order term */
273 /* Also, try to use an integer-type image for fitting error */
274 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, ndits-1, CPL_TRUE,
275 ifiterror);
276
277 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
278 xsh_test( cpl_imagelist_get_size(fit) == ndits );
279 xsh_fit_image_is_zero(ifiterror, mytol);
280
281 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2), 1.0));
282
283 xsh_fit_imagelist_is_zero(fit, mytol);
284
285 cpl_imagelist_delete(fit);
286
287 /* Fit without zero-order term */
288 fit = xsh_fit_imagelist_polynomial(vdit, input, 1, ndits-1, CPL_FALSE,
289 dfiterror);
290
291 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
292 xsh_test( cpl_imagelist_get_size(fit) == ndits-1 );
293
294 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 1), 1.0));
295
296 xsh_fit_imagelist_is_zero(fit, mytol);
297 xsh_fit_image_is_zero(dfiterror, mytol);
298
299 cpl_imagelist_delete(fit);
300
301 /* Fit with no zero- and 1st-order terms */
302 fit = xsh_fit_imagelist_polynomial(vdit, input, 2, ndits, CPL_TRUE,
303 ffiterror);
304
305 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
306 xsh_test( cpl_imagelist_get_size(fit) == ndits-1 );
307
308 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0), 1.0));
309
310 xsh_fit_imagelist_is_zero(fit, mytol);
311 xsh_fit_image_is_zero(ffiterror, mytol);
312
313 cpl_imagelist_delete(fit);
314
315 /* Fit with one zero-term */
316 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, 0, CPL_TRUE,
317 dfiterror);
318
319 xsh_test( cpl_error_get_code() == CPL_ERROR_NONE );
320 xsh_test( cpl_imagelist_get_size(fit) == 1 );
321
322 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 0),
323 sqsum/(double)ndits));
324
325 xsh_fit_imagelist_is_zero(fit, mytol);
326
327 cpl_imagelist_delete(fit);
328
329 cpl_imagelist_delete(input);
330
331 (void)cpl_vector_unwrap(vdit);
332
333 /* Try to fit as many coefficients are there are data points */
334 /* Also, use floats this time */
335
336 input = cpl_imagelist_new();
337
338 for (ntest = 1; ntest <= ndits; ntest++) {
339 const double gain = 4.0; /* Some random number */
340
341 cpl_msg_info(cpl_func, "Fitting %d coefficients to as many points",
342 ntest);
343
344 vdit = cpl_vector_wrap(ntest, (double*)ditval);
345
346 /* Create a list of images with a 2nd order function */
347 for (i = ntest - 1; i < ntest; i++) {
348 cpl_image * image = cpl_image_new(IMAGESZFIT, IMAGESZFIT,
349 CPL_TYPE_FLOAT);
350
351 xsh_test(!cpl_image_add_scalar(image, gain * ditval[i]*ditval[i]));
352
353 xsh_test(!cpl_imagelist_set(input, image, i));
354
355 cpl_msg_debug(cpl_func, "Dit and mean of input image no. %d: %g %g",
356 i, ditval[i], cpl_image_get_mean(image));
357 }
358
359 /* Ready for fitting */
360
361 /* Fit with zero-order term */
362 fit = xsh_fit_imagelist_polynomial(vdit, input, 0, ntest-1, CPL_TRUE,
363 ffiterror);
364
365 (void)cpl_vector_unwrap(vdit);
366
367 if (cpl_error_get_code() != CPL_ERROR_NONE) {
368 xsh_test( fit == NULL );
369
370 cpl_msg_info(cpl_func, "Could not fit %d coefficients to as many "
371 "points", ntest);
372
373 xsh_test( cpl_error_get_code() != CPL_ERROR_UNSPECIFIED );
374 cpl_error_reset();
375
376 break;
377 }
378
379 xsh_test( cpl_imagelist_get_size(fit) == ntest );
380
381 if (ntest == 2) {
382 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 1),
383 gain));
384 } else if (ntest > 2) {
385 xsh_test(!cpl_image_subtract_scalar(cpl_imagelist_get(fit, 2),
386 gain));
387 }
388
389 xsh_fit_imagelist_is_zero(fit, mytol);
390
391 xsh_fit_image_is_zero(ffiterror, mytol);
392
393 cpl_imagelist_delete(fit);
394 }
395
396 cpl_imagelist_delete(input);
397
398 /* Done testing */
399 cpl_image_delete(dfiterror);
400 cpl_image_delete(ffiterror);
401 cpl_image_delete(ifiterror);
402
403 cleanup:
404 return;
405}
406
407
408
409/*----------------------------------------------------------------------------*/
417/*----------------------------------------------------------------------------*/
418static void xsh_fit_imagelist_is_zero_macro(const cpl_imagelist * self,
419 double tol)
420{
421
422 const int n = cpl_imagelist_get_size(self);
423 int i;
424
425 for (i = 0; i < n; i++) {
426
427 check(
428 xsh_fit_image_is_zero_macro(cpl_imagelist_get_const( self, i),
429 tol));
430
431 }
432 cleanup:
433 return;
434}
435
436
437/*----------------------------------------------------------------------------*/
446/*----------------------------------------------------------------------------*/
447static void xsh_fit_image_is_zero_macro(const cpl_image * self, double tol)
448{
449
450 cpl_stats * stats = cpl_stats_new_from_image(self,
451 CPL_STATS_MIN | CPL_STATS_MAX
452 | CPL_STATS_MEAN);
453
454 const double mymin = cpl_stats_get_min(stats);
455 const double mymax = cpl_stats_get_max(stats);
456
457 xsh_test_tol( mymin, 0.0, tol );
458 xsh_test_tol( mymax, 0.0, tol );
459
460 cleanup:
461 cpl_stats_delete(stats);
462 return;
463
464}
465
466
467/*----------------------------------------------------------------------------*/
480/*----------------------------------------------------------------------------*/
481static cpl_error_code xsh_image_fill_noise_uniform(cpl_image * self,
482 double min_pix,
483 double max_pix)
484{
485
486 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
487
488 if (cpl_image_get_type(self) == CPL_TYPE_INT) {
489
490 int * pi = cpl_image_get_data_int(self);
491 const int nx = cpl_image_get_size_x(self);
492 const int ny = cpl_image_get_size_y(self);
493 int i, j;
494
495
496 for (j=0 ; j < ny ; j++) {
497 for (i=0 ; i < nx ; i++) {
498 const double value
499 = min_pix + (max_pix * (double)rand())/(double)RAND_MAX;
500
501 pi[i + j * nx] = (int) value;
502 }
503 }
504 } else {
505
506 const cpl_error_code error
507 = cpl_image_fill_noise_uniform(self, min_pix, max_pix);
508 cpl_ensure_code(!error, error);
509 }
510
511 return CPL_ERROR_NONE;
512}
#define check(COMMAND)
Definition: xsh_error.h:71
#define xsh_error_dump(level)
Definition: xsh_error.h:92
cpl_imagelist * xsh_fit_imagelist_polynomial(const cpl_vector *x_pos, const cpl_imagelist *values, int mindeg, int maxdeg, cpl_boolean is_eqdist, cpl_image *fiterror)
Fit a polynomial to each pixel in a list of images.
Definition: xsh_fit.c:171
static void xsh_fit_imagelist_is_zero_macro(const cpl_imagelist *, double)
Verify that all elements in an imagelist are zero (within a tolerance)
Definition: test-xsh_fit.c:418
#define xsh_test(expr)
Definition: test-xsh_fit.c:43
#define IMAGESZ
Definition: test-xsh_fit.c:63
static void xsh_fit_image_is_zero_macro(const cpl_image *, double)
Verify that all elements in an image are zero (within a tolerance)
Definition: test-xsh_fit.c:447
#define IMAGESZFIT
Definition: test-xsh_fit.c:65
static void xsh_fit_imagelist_polynomial_tests(void)
Definition: test-xsh_fit.c:117
int main(void)
Unit tests of fit module.
Definition: test-xsh_fit.c:99
static cpl_error_code xsh_image_fill_noise_uniform(cpl_image *, double, double)
Fill an image with uniform random noise distribution.
Definition: test-xsh_fit.c:481
#define MODULE_ID
Definition: test-xsh_fit.c:38
#define xsh_fit_imagelist_is_zero(A, B)
Definition: test-xsh_fit.c:67
#define xsh_fit_image_is_zero(A, B)
Definition: test-xsh_fit.c:69
#define xsh_test_tol(first, second, tolerance)
Definition: test-xsh_fit.c:48
#define TEST_END()
Definition: tests.h:111
#define TESTS_INIT(DRL_ID)
Definition: tests.h:105
int nx
int n
Definition: xsh_detmon_lg.c:92
int ny