Skip to content

Commit f20cecf

Browse files
authored
Merge pull request #507 from LSSTDESC/u/welucas2/correct-diffraction-normalisation
Correct normalization in photon diffraction by circles
2 parents ee263ec + c013cdd commit f20cecf

2 files changed

Lines changed: 31 additions & 7 deletions

File tree

imsim/diffraction.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ def directed_dist(
219219
n[line_mask] = geometry.thick_lines[min_line_idx[line_mask]][..., :2]
220220
dist[~line_mask] = min_dist_circles[~line_mask]
221221
d = geometry.circles[min_circle_idx[~line_mask]][..., :2] - points[~line_mask]
222-
n[~line_mask] = d / np.linalg.norm(d)
222+
norm = np.linalg.norm(d, axis=1)
223+
n[~line_mask] = d / np.column_stack((norm, norm))
223224
return dist, n
224225

225226

tests/test_photon_ops.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ def test_rubin_diffraction_produces_spikes() -> None:
226226

227227
# Define a tolerance for the spike width in rad:
228228
spike_angle_tolerance = np.pi / 6.0
229+
# Determine the total fraction of a circle taken up by all regions of this
230+
# size, and regions outside of the spikes:
231+
spike_fraction = 2. * spike_angle_tolerance / np.pi
232+
non_spike_fraction = 1. - spike_fraction
233+
weight = spike_fraction / non_spike_fraction
229234

230235
delta_angles = spike_angles - cross_rot_angle
231236
delta_angles[delta_angles < 0.0] += 2.0 * np.pi
@@ -248,11 +253,29 @@ def test_rubin_diffraction_produces_spikes() -> None:
248253
# Merge last and first bin:
249254
h[0] += h[-1]
250255
h = h[:-1]
256+
# Weight the non-spike counts in h to account for the different bin sizes.
257+
h[1::2] = h[1::2] * weight
251258

252-
# Check that there less than 0.5% of the spike photons outside of the spike regions:
253-
np.testing.assert_array_less(h[1::2], spike_angles.size // 200)
254-
# Check that there are photons in all spike regions:
255-
np.testing.assert_array_less(0, h[0::2])
259+
# The min and max counts we might expect in a bin of size
260+
# spike_angle_tolerance if there were only non-spike photons, with some
261+
# amount of Poisson noise.
262+
bg_level_min = np.mean(h[1::2]) - 2. * np.sqrt(np.mean(h[1::2]))
263+
bg_level_max = np.mean(h[1::2]) + 2. * np.sqrt(np.mean(h[1::2]))
264+
265+
# Assert all out-of-spike regions are within that range.
266+
np.testing.assert_array_less(bg_level_min, h[1::2])
267+
np.testing.assert_array_less(h[1::2], bg_level_max)
268+
269+
# Perform the same checks on spike regions.
270+
spike_level_min = np.mean(h[0::2]) - 2. * np.sqrt(np.mean(h[0::2]))
271+
spike_level_max = np.mean(h[0::2]) + 2. * np.sqrt(np.mean(h[0::2]))
272+
np.testing.assert_array_less(spike_level_min, h[0::2])
273+
np.testing.assert_array_less(h[0::2], spike_level_max)
274+
275+
# Check that each of the spike bins are measured above the non-spike
276+
# level + an appreciable noise level.
277+
high_bg = np.mean(h[1::2]) + 10. * np.sqrt(np.mean(h[1::2]))
278+
np.testing.assert_array_less(high_bg, h[0::2])
256279

257280

258281
def test_rubin_diffraction_optics_is_same_as_diffraction_and_optics() -> None:
@@ -357,8 +380,8 @@ def test_rubin_diffraction_shows_field_rotation() -> None:
357380
)
358381

359382
# Find the angle, the cross is rotated relative to the axis cross:
360-
cross_rot_angle_0 = np.mean(spike_angles_0 % (np.pi / 2.0))
361-
cross_rot_angle_1 = np.mean(spike_angles_1 % (np.pi / 2.0))
383+
cross_rot_angle_0 = np.median(spike_angles_0 % (np.pi / 2.0))
384+
cross_rot_angle_1 = np.median(spike_angles_1 % (np.pi / 2.0))
362385

363386
# Check that the angle of the crosses are rotated relative to each other:
364387
expected_angle_difference = field_rotation_angle(latitude, altitude, azimuth, dt)

0 commit comments

Comments
 (0)