CR2RE Pipeline Reference Manual 1.6.2
hdrl_combine-test.c
1/* $Id: hdrl_combine-test.c,v 1.7 2013-09-24 14:58:54 jtaylor Exp $
2 *
3 * This file is part of the HDRL
4 * Copyright (C) 2013 European Southern Observatory
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * $Author: jtaylor $
23 * $Date: 2013-09-24 14:58:54 $
24 * $Revision: 1.7 $
25 * $Name: not supported by cvs2svn $
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31
32/*-----------------------------------------------------------------------------
33 Includes
34 -----------------------------------------------------------------------------*/
35
36#include "hdrl_combine.h"
37#include <cpl.h>
38
39#include <math.h>
40#include <stdlib.h>
41
42#ifndef ARRAY_LEN
43#define ARRAY_LEN(a) sizeof((a))/sizeof((a)[0])
44#endif
45
46
47/*----------------------------------------------------------------------------*/
51/*----------------------------------------------------------------------------*/
52
53
54/*----------------------------------------------------------------------------*/
58/*----------------------------------------------------------------------------*/
59int main(void)
60{
61 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
62
63#define TST_FREE \
64 cpl_image_delete(outimg); \
65 cpl_image_delete(outerr); \
66 cpl_image_delete(contrib); \
67 hdrl_collapse_imagelist_to_image_delete(method);
68
69 /* create data, value 5., error +-1 */
70 cpl_imagelist * data = cpl_imagelist_new();
71 cpl_imagelist * errs = cpl_imagelist_new();
72 cpl_image * img = cpl_image_new(40, 40, CPL_TYPE_DOUBLE);
73 cpl_image * err = cpl_image_new(40, 40, CPL_TYPE_DOUBLE);
74 cpl_image_add_scalar(img, 5.);
75 cpl_image_add_scalar(err, 2.);
76 size_t nz = 5;
77
78 /* create expected results (err / sqrt(nz) for mean) */
79 cpl_image * expect_err = cpl_image_duplicate(err);
80 cpl_image_divide_scalar(expect_err, sqrt(nz));
81 cpl_image * expect_contrib = cpl_image_new(40, 40, CPL_TYPE_INT);
82 cpl_image_add_scalar(expect_contrib, 5);
83 for (size_t i = 0; i < nz; i++) {
84 cpl_imagelist_set(data, cpl_image_duplicate(img), cpl_imagelist_get_size(data));
85 cpl_imagelist_set(errs, cpl_image_duplicate(err), cpl_imagelist_get_size(errs));
86 }
87 cpl_image * outimg, * outerr, * contrib;
88
89 /* test inputs */
90 {
91 hdrl_collapse_imagelist_to_image_t * method =
92 hdrl_collapse_imagelist_to_image_mean();
93 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, NULL);
94 cpl_test_error(CPL_ERROR_NULL_INPUT);
95 hdrl_imagelist_combine(data, errs, method, &outimg, NULL, &contrib);
96 cpl_test_error(CPL_ERROR_NULL_INPUT);
97 hdrl_imagelist_combine(data, errs, method, NULL, &outerr, &contrib);
98 cpl_test_error(CPL_ERROR_NULL_INPUT);
99 hdrl_imagelist_combine(data, errs, NULL, &outimg, &outerr, &contrib);
100 cpl_test_error(CPL_ERROR_NULL_INPUT);
101 hdrl_imagelist_combine(data, NULL, method, &outimg, &outerr, &contrib);
102 cpl_test_error(CPL_ERROR_NULL_INPUT);
103 hdrl_imagelist_combine(NULL, errs, method, &outimg, &outerr, &contrib);
104 cpl_test_error(CPL_ERROR_NULL_INPUT);
105 hdrl_collapse_imagelist_to_image_delete(method);
106 }
107 /* wrong imagelist sizes */
108 {
109 hdrl_collapse_imagelist_to_image_t * method =
110 hdrl_collapse_imagelist_to_image_mean();
111 cpl_imagelist * data2 = cpl_imagelist_duplicate(data);
112 cpl_imagelist * errs2;
113 cpl_image_delete(cpl_imagelist_unset(data2, 0));
114 hdrl_imagelist_combine(data2, errs, method, &outimg, &outerr, &contrib);
115 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
116 cpl_imagelist_delete(data2);
117
118 data2 = cpl_imagelist_new();
119 errs2 = cpl_imagelist_new();
120 hdrl_imagelist_combine(data2, errs2, method, &outimg, &outerr, &contrib);
121 cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
122 cpl_imagelist_delete(data2);
123 cpl_imagelist_delete(errs2);
124 hdrl_collapse_imagelist_to_image_delete(method);
125 }
126 /* test reductions on uniform error cases */
127 {
128 /* mean */
129 hdrl_collapse_imagelist_to_image_t * method =
130 hdrl_collapse_imagelist_to_image_mean();
131 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
132
133 cpl_test_image_abs(outimg, img, HDRL_EPS_DATA);
134 cpl_test_image_abs(outerr, expect_err, HDRL_EPS_ERROR);
135 cpl_test_image_abs(contrib, expect_contrib, 0);
136 TST_FREE;
137
138 /* sigclip */
139 method = hdrl_collapse_imagelist_to_image_sigclip(3., 3., 3);
140 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
141
142 cpl_test_image_abs(outimg, img, HDRL_EPS_DATA);
143 cpl_test_image_abs(outerr, expect_err, HDRL_EPS_ERROR);
144 cpl_test_image_abs(contrib, expect_contrib, 0);
145 TST_FREE;
146
147 /* minmax */
148 method = hdrl_collapse_imagelist_to_image_minmax(0, 0);
149 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
150
151 cpl_test_image_abs(outimg, img, HDRL_EPS_DATA);
152 cpl_test_image_abs(outerr, expect_err, HDRL_EPS_ERROR);
153 cpl_test_image_abs(contrib, expect_contrib, 0);
154 TST_FREE;
155
156 /* weighted mean */
157 method = hdrl_collapse_imagelist_to_image_weighted_mean();
158 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
159
160 cpl_test_image_abs(outimg, img, HDRL_EPS_DATA);
161 cpl_test_image_abs(outerr, expect_err, HDRL_EPS_ERROR);
162 cpl_test_image_abs(contrib, expect_contrib, 0);
163 TST_FREE;
164
165 /* median */
166 cpl_image_multiply_scalar(expect_err, sqrt(CPL_MATH_PI_2));
167 method = hdrl_collapse_imagelist_to_image_median();
168 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
169
170 cpl_test_image_abs(outimg, img, HDRL_EPS_DATA);
171 cpl_test_image_abs(outerr, expect_err, HDRL_EPS_ERROR);
172 cpl_test_image_abs(contrib, expect_contrib, 0);
173 TST_FREE;
174 }
175 /* test non uniform error cases */
176 {
177 double v[] = {1, 2, 1, 3, 2};
178 double e[] = {0.5, 0.7, 0.1, 1.0, 0.01};
179 int d;
180 for (size_t i = 0; i < nz; i++) {
181 cpl_image * tmp = cpl_imagelist_get(data, i);
182 cpl_image_set(tmp, 1, 1, v[i]);
183 tmp = cpl_imagelist_get(errs, i);
184 cpl_image_set(tmp, 1, 1, e[i]);
185 }
186 hdrl_collapse_imagelist_to_image_t * method =
187 hdrl_collapse_imagelist_to_image_mean();
188 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
189 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.8, HDRL_EPS_DATA);
190 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.26458269028793246, HDRL_EPS_ERROR);
191 cpl_test_image_abs(contrib, expect_contrib, 0);
192 TST_FREE;
193
194 method = hdrl_collapse_imagelist_to_image_sigclip(3., 3., 3);
195 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
196
197 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.8, HDRL_EPS_DATA);
198 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.26458269028793246, HDRL_EPS_ERROR);
199 cpl_test_image_abs(contrib, expect_contrib, 0);
200 TST_FREE;
201
202 method = hdrl_collapse_imagelist_to_image_minmax(1, 1);
203 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
204
205 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 5./3., HDRL_EPS_DATA);
206
207 /* The minmax rejection algorithm has a
208 * intrinsic problem with same values but different errors. If for
209 * example the two lowest values are 1+-0.5 and 1+-500 what "1" should
210 * be kept? It doesn't matter for the mean, but for the propagated
211 * error - the implemented algorithm propagates the smaller error */
212
213 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d),
214 sqrt(0.1 * 0.1 + 0.7 * 0.7 + 0.01 * 0.01) / 3.,
215 HDRL_EPS_ERROR);
216 cpl_image * expect_contrib_minmax =
217 cpl_image_subtract_scalar_create(expect_contrib, 2);
218 cpl_test_image_abs(contrib, expect_contrib_minmax, 0);
219 cpl_image_delete(expect_contrib_minmax);
220 TST_FREE;
221
222 method = hdrl_collapse_imagelist_to_image_weighted_mean();
223 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
224 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.9898090843925733, HDRL_EPS_DATA);
225 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.0099469054598625289, HDRL_EPS_ERROR);
226 cpl_test_image_abs(contrib, expect_contrib, 0);
227 TST_FREE;
228 }
229 /* test non uniform error cases with rejected values */
230 {
231 double v[] = {1, 2, 1, 3, 2};
232 double e[] = {0.5, 0.7, 0.1, 1.0, 0.01};
233 int d;
234 for (size_t i = 0; i < nz; i++) {
235 cpl_image * tmp = cpl_imagelist_get(data, i);
236 cpl_image_set(tmp, 1, 1, v[i]);
237 if (i == 3) {
238 cpl_image_reject(tmp, 1, 1);
239 }
240 tmp = cpl_imagelist_get(errs, i);
241 cpl_image_set(tmp, 1, 1, e[i]);
242 if (i == 3) {
243 cpl_image_reject(tmp, 1, 1);
244 }
245 }
246 cpl_image_delete(expect_contrib);
247 expect_contrib = cpl_image_new_from_accepted(data);
248
249 hdrl_collapse_imagelist_to_image_t * method =
250 hdrl_collapse_imagelist_to_image_mean();
251 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
252
253 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.5, HDRL_EPS_DATA);
254 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.21652078422174625, HDRL_EPS_ERROR);
255 cpl_test_image_abs(contrib, expect_contrib, 0);
256 TST_FREE;
257
258 method = hdrl_collapse_imagelist_to_image_sigclip(3., 3., 3);
259 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
260
261 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.5, HDRL_EPS_DATA);
262 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.21652078422174625, HDRL_EPS_ERROR);
263 cpl_test_image_abs(contrib, expect_contrib, 0);
264 TST_FREE;
265
266 method = hdrl_collapse_imagelist_to_image_minmax(1, 1);
267 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
268
269 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 3./2., HDRL_EPS_DATA);
270 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d),
271 sqrt(0.01 * 0.01 + 0.1 * 0.1) / 2., HDRL_EPS_ERROR);
272 cpl_image * expect_contrib_minmax =
273 cpl_image_subtract_scalar_create(expect_contrib, 2);
274 cpl_test_image_abs(contrib, expect_contrib_minmax, 0);
275 cpl_image_delete(expect_contrib_minmax);
276 TST_FREE;
277
278 method = hdrl_collapse_imagelist_to_image_weighted_mean();
279 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
280
281 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.9897091252756485, HDRL_EPS_DATA);
282 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 0.0099473975744101273, HDRL_EPS_ERROR);
283 cpl_test_image_abs(contrib, expect_contrib, 0);
284 TST_FREE;
285 }
286 /* test median error propagation with rejects, only makes sense on uniform
287 * errors as the scaling relies on gaussian errors */
288 {
289 double v[] = {1, 2, 1, 3, 2};
290 double e[] = {1., 1., 1., 1., 1.};
291 int d;
292 for (size_t i = 0; i < nz; i++) {
293 cpl_image * tmp = cpl_imagelist_get(data, i);
294 cpl_image_set(tmp, 1, 1, v[i]);
295 cpl_image_set(tmp, 2, 2, v[i]);
296 if (i > 1) {
297 cpl_image_reject(tmp, 1, 1);
298 }
299 tmp = cpl_imagelist_get(errs, i);
300 cpl_image_set(tmp, 1, 1, e[i]);
301 cpl_image_set(tmp, 2, 2, e[i]);
302 if (i > 1) {
303 cpl_image_reject(tmp, 1, 1);
304 }
305 }
306 cpl_image_delete(expect_contrib);
307 expect_contrib = cpl_image_new_from_accepted(data);
308
309 hdrl_collapse_imagelist_to_image_t * method =
310 hdrl_collapse_imagelist_to_image_median();
311 hdrl_imagelist_combine(data, errs, method, &outimg, &outerr, &contrib);
312
313 /* contrib > 2 -> sqrt(nz * pi / 2) error scaling */
314 cpl_test_abs(cpl_image_get(outimg, 2, 2, &d), 2., HDRL_EPS_DATA);
315 cpl_test_abs(cpl_image_get(outerr, 2, 2, &d),
316 1. / sqrt(nz) * sqrt(CPL_MATH_PI_2), HDRL_EPS_ERROR);
317 /* contrib <= 2 -> median is a mean, no scaling */
318 cpl_test_abs(cpl_image_get(outimg, 1, 1, &d), 1.5, HDRL_EPS_DATA);
319 cpl_test_abs(cpl_image_get(outerr, 1, 1, &d), 1. / sqrt(2.), HDRL_EPS_ERROR);
320 cpl_test_image_abs(contrib, expect_contrib, 0);
321 TST_FREE;
322 }
323
324 cpl_imagelist_delete(data);
325 cpl_imagelist_delete(errs);
326 cpl_image_delete(expect_err);
327 cpl_image_delete(expect_contrib);
328 cpl_image_delete(img);
329 cpl_image_delete(err);
330
331 return cpl_test_end(0);
332#undef TST_FREE
333}