CR2RE Pipeline Reference Manual 1.6.7
hdrl_der_snr-test.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2017 European Southern Observatory
4 *
5 * This program 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include "hdrl_DER_SNR.h"
29#include "hdrl_spectrum.h"
30#include "hdrl_random.h"
31
32#include <cpl.h>
33#include <math.h>
34#include <time.h>
35#include <stdlib.h>
36
37
38
39/*----------------------------------------------------------------------------*/
43/*----------------------------------------------------------------------------*/
44
45static inline cpl_image * get_noisy_flux(const cpl_image * img);
46
47#define ARR_SIZE(a) ((cpl_size)((sizeof((a)) / sizeof((a[0])))))
48
49static inline
50cpl_image * get_error(const int* data, const int* map, cpl_size length){
51 /* map[j] is the position in unsorted where the j-th element is going to
52 * be inserted*/
53 cpl_array * wav = cpl_array_new(length, HDRL_TYPE_DATA);
54 cpl_image * flux = cpl_image_new(length, 1, HDRL_TYPE_DATA);
55
56 for(cpl_size j = 0; j < length; ++j){
57 cpl_image_set(flux, map[j] + 1, 1, data[j]);
58 cpl_array_set(wav, map[j], j + 1);
59 }
60
61 const hdrl_data_t *flux_p =
62 (const hdrl_data_t *)cpl_image_get_data_const(flux);
63
64 const cpl_binary *msk = NULL;
65 cpl_image *flux_e = estimate_noise_DER_SNR(flux_p, msk, wav, length, 5);
66
67 cpl_image_delete(flux);
68 cpl_array_delete(wav);
69
70 return flux_e;
71}
72
73void test_DER_SNR_sort(void){
74
75 int data[] = {
76 1, 5, 10, 5, 23, 1, 8, 17, 21, 7, 11, 13, 5, 99, 12, 4,
77 1, 5, 10, 5, 23, 1, 8, 17, 21, 7, 11, 13, 5, 99, 12, 4
78 };
79
80 int map1[ARR_SIZE(data)] = {0};
81 int map2[ARR_SIZE(data)] = {0};
82
83 const cpl_size length = ARR_SIZE(data);
84
85 for(cpl_size i = 0; i < length; ++i){
86 map1[i] = i;
87 map2[i] = i;
88 }
89
90 for(cpl_size i = 0; i < length; ++i){
91
92 const cpl_size source = i;
93 const cpl_size dest = ((double)rand() / (double)RAND_MAX) * (length - 1);
94
95 cpl_test(dest >= 0 && dest < length);
96
97 const int data_s = map1[source];
98 const int data_d = map1[dest];
99
100 map1[source] = data_d;
101 map1[dest] = data_s;
102 }
103
104 cpl_image * flux_e_unsorted = get_error(data, map1, length);
105 cpl_image * flux_e_sorted = get_error(data, map2, length);
106
107 /* map1[i] is the position in unsorted where the i-th element of sorted
108 * is inserted.*/
109 for(cpl_size i = 0; i < length; ++i){
110 int rej1;
111 const double data1 = cpl_image_get(flux_e_sorted, i + 1, 1, &rej1);
112
113 int rej2;
114 const double data2 = cpl_image_get(flux_e_unsorted, map1[i] + 1, 1, &rej2);
115
116 cpl_test_eq(rej1, rej2);
117 cpl_test_abs(data1, data2, 1e-3);
118 }
119
120 cpl_image_delete(flux_e_sorted);
121 cpl_image_delete(flux_e_unsorted);
122}
123
124void test_DER_SNR(void){
125
126 int data[] = {
127 1, 5, 10, 5, 23, 1, 8, 17, 21, 7, 11, 13, 5, 99, 12, 4,
128 1, 5, 10, 5, 23, 1, 8, 17, 21, 7, 11, 13, 5, 99, 12, 4
129 };
130
131 cpl_array * wav = cpl_array_new(ARR_SIZE(data), HDRL_TYPE_DATA);
132 cpl_image * flux = cpl_image_new(ARR_SIZE(data), 1, HDRL_TYPE_DATA);
133
134 for(cpl_size i = 0; i < ARR_SIZE(data); ++i){
135 cpl_image_set(flux, i +1, 1, data[i]);
136 cpl_array_set(wav, i, i + 1);
137 }
138
139 const hdrl_data_t * flux_p =
140 (const hdrl_data_t *)cpl_image_get_data_const(flux);
141
142 const cpl_binary *msk = NULL;
143 hdrl_data_t err =
144 estimate_noise_window(flux_p, msk, 0,
145 ARR_SIZE(data) - 1, ARR_SIZE(data));
146 cpl_test_abs(err, 12.105, 1e-3);
147
148 cpl_image * flux_e = estimate_noise_DER_SNR(flux_p, msk, wav,
149 ARR_SIZE(data), 5);
150
151 cpl_test_eq(cpl_image_get_size_x(flux), cpl_image_get_size_x(flux_e));
152 cpl_test_eq(cpl_image_get_size_y(flux), cpl_image_get_size_y(flux_e));
153
154 int rej = 0;
155 err = cpl_image_get(flux_e, 7, 1, &rej);
156 cpl_test_abs(err, 13.921, 1e-3);
157
158 err = cpl_image_get(flux_e, 6, 1, &rej);
159 cpl_test_abs(err, 13.921, 1e-3);
160
161 err = cpl_image_get(flux_e, 1, 1, &rej);
162 cpl_test_abs(err, 2.421, 1e-3);
163
164 cpl_image_delete(flux_e);
165
166
167 /*bad pixel is bad also in error*/
168 cpl_image_reject(flux, 2, 1);
169
170 flux_p = (const hdrl_data_t *)cpl_image_get_data_const(flux);
171 const cpl_mask *mask = cpl_image_get_bpm_const(flux);
172 msk = cpl_mask_get_data_const(mask);
173
174 flux_e = estimate_noise_DER_SNR(flux_p, msk, wav, ARR_SIZE(data), 5);
175
176 cpl_test(cpl_image_is_rejected(flux_e, 2, 1));
177
178 /*bad pixels in window are skipped*/
179 err = cpl_image_get(flux_e, 6, 1, &rej);
180 cpl_test_abs(err, 14.829, 1e-3);
181 cpl_test_eq(rej, 0);
182
183 /*good pixel surrounded by bad pixels so that there is no pixel to calculate
184 * error, becomes bad*/
185 cpl_image_delete(flux_e);
186
187 for(cpl_size i = 1; i <= 11; i++)
188 {
189 if(i == 6) continue;
190 cpl_image_reject(flux, i, 1);
191 }
192
193 flux_p = (const hdrl_data_t *)cpl_image_get_data_const(flux);
194 mask = cpl_image_get_bpm_const(flux);
195 msk = cpl_mask_get_data_const(mask);
196
197 flux_e = estimate_noise_DER_SNR(flux_p, msk, wav, ARR_SIZE(data), 5);
198 cpl_test(cpl_image_is_rejected(flux_e, 6, 1));
199 cpl_test(!cpl_image_is_rejected(flux, 6, 1));
200
201 cpl_image_delete(flux_e);
202 cpl_image_delete(flux);
203 cpl_array_delete(wav);
204}
205
206void test_DER_SNR_performance(void){
207
208 static const int sz = 2000;
209 static const double delta = 3.14 / 2000.0;
210 static const double peak = 1e3;
211 static const int n_iter = 100;
212
213 cpl_image * flux = cpl_image_new(sz, 1, HDRL_TYPE_DATA);
214 cpl_array * lambdas = cpl_array_new(sz, HDRL_TYPE_DATA);
215
216 for(cpl_size i = 0; i < sz; i++){
217 double x = delta * (i+1);
218 cpl_array_set(lambdas, i, x);
219 cpl_image_set(flux, i + 1, 1, peak * sin(x));
220 }
221
222 cpl_image * std_dev_theo = cpl_image_power_create(flux, 1./2.);
223 cpl_image * DER_SNR_avg = cpl_image_new(sz, 1,HDRL_TYPE_DATA);
224
225 for(cpl_size i = 0; i < n_iter; ++i){
226 cpl_image * noisy_flux_i = get_noisy_flux(flux);
227
228 const hdrl_data_t * noisy_flux =
229 (const hdrl_data_t *)cpl_image_get_data_const(noisy_flux_i);
230
231 const cpl_binary *msk = NULL;
232 cpl_image * e = estimate_noise_DER_SNR(noisy_flux, msk, lambdas, sz, 5);
233
234 cpl_image_divide_scalar(e, n_iter);
235 cpl_image_add(DER_SNR_avg, e);
236 cpl_image_delete(e);
237
238 cpl_image_delete(noisy_flux_i);
239 }
240
241 cpl_image * ratio = cpl_image_divide_create(std_dev_theo, DER_SNR_avg);
242 double avg_ratio = cpl_image_get_absflux(ratio) / sz;
243
244 cpl_test_leq(avg_ratio, 1.1);
245 cpl_test_leq(.9, avg_ratio);
246
247 cpl_image_delete(flux);
248 cpl_image_delete(DER_SNR_avg);
249 cpl_array_delete(lambdas);
250 cpl_image_delete(ratio);
251 cpl_image_delete(std_dev_theo);
252}
253
254/*----------------------------------------------------------------------------*/
258/*----------------------------------------------------------------------------*/
259int main(void)
260{
261 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
262
263 srand (time(NULL));
264
265 test_DER_SNR();
266 test_DER_SNR_sort();
267 test_DER_SNR_performance();
268
269 return cpl_test_end(0);
270}
271
272/*----------------------------------------------------------------------------*/
276/*----------------------------------------------------------------------------*/
277static inline
278cpl_image * get_noisy_flux(const cpl_image * img){
279
280 cpl_size sx = cpl_image_get_size_x(img);
281 cpl_size sy = cpl_image_get_size_y(img);
282
283 cpl_image * to_ret = cpl_image_new(sx, sy, HDRL_TYPE_DATA);
284
285 hdrl_random_state * rng = hdrl_random_state_new(1, NULL);
286
287 for(cpl_size x = 1; x <= sx; x++){
288 for(cpl_size y = 1; y <= sy; y++){
289 int rej = 0;
290 double clean_value = cpl_image_get(img, x, y, &rej);
291 double noisy_value = hdrl_random_poisson(rng, clean_value);
292 cpl_image_set(to_ret, x, y, noisy_value);
293 }
294 }
295
296 hdrl_random_state_delete(rng);
297 return to_ret;
298}
299
300
hdrl_error_t estimate_noise_window(const hdrl_data_t *flux, const cpl_binary *msk, cpl_size start, cpl_size stop, const cpl_size sz)
Estimate the noise in the pixels between [start, stop]. The noise calculation is done using the formu...
Definition: hdrl_DER_SNR.c:89
cpl_image * estimate_noise_DER_SNR(const hdrl_data_t *flux_in, const cpl_binary *msk_in, const cpl_array *wavelengths, const cpl_size length, const cpl_size half_window)
For every pixel in position i in img_arg, the function estimates the noise using the pixels in the wi...
Definition: hdrl_DER_SNR.c:160