Skip to content

Commit be3a3a2

Browse files
Jammy2211claude
authored andcommitted
Fix sign of poisson noise in preprocess.poisson_noise_via_data_eps_from
The function returned data_eps - noisy_eps, which made data_eps_with_poisson_noise_added produce 2*data - noisy_data (noise reflected around the mean — same magnitude, mirrored skew). Poisson is positively skewed; the buggy version had negative skew, biasing inference on simulated low-count imaging. Now returns noisy_eps - data_eps so that data + noise = noisy_data. Also wraps the result back into the input Array2D type via with_new_array(), preventing the numpy/Array2D dispatch from returning a raw ndarray. Test fixtures regenerated under the same seeds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4ea58e1 commit be3a3a2

3 files changed

Lines changed: 19 additions & 15 deletions

File tree

autoarray/dataset/preprocess.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,11 +472,13 @@ def poisson_noise_via_data_eps_from(data_eps, exposure_time_map, seed=-1):
472472
"""
473473
setup_random_seed(seed)
474474

475-
image_counts = np.multiply(data_eps.array, exposure_time_map.array)
476-
return data_eps - np.divide(
477-
np.random.poisson(image_counts, data_eps.shape), exposure_time_map.array
475+
image_counts = data_eps.array * exposure_time_map.array
476+
noisy_eps_array = (
477+
np.random.poisson(image_counts, data_eps.shape) / exposure_time_map.array
478478
)
479479

480+
return data_eps.with_new_array(noisy_eps_array) - data_eps
481+
480482

481483
def data_eps_with_poisson_noise_added(data_eps, exposure_time_map, seed=-1):
482484
"""

test_autoarray/dataset/imaging/test_simulator.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ def test__via_image_from__psf_off__include_poisson_noise_in_noise_map(
4343
dataset = simulator.via_image_from(image=image)
4444

4545
assert dataset.data.native == pytest.approx(
46-
np.array([[1.05, 1.3, 1.25], [1.05, 2.1, 1.2], [1.05, 1.3, 1.15]]), 1e-2
46+
np.array([[0.95, 0.7, 0.75], [0.95, 1.9, 0.8], [0.95, 0.7, 0.85]]), 1e-2
4747
)
4848

4949
assert dataset.noise_map.native == pytest.approx(
50-
np.array([[0.229, 0.255, 0.25], [0.229, 0.324, 0.245], [0.229, 0.255, 0.240]]),
50+
np.array(
51+
[[0.218, 0.187, 0.194], [0.218, 0.308, 0.2], [0.218, 0.187, 0.206]]
52+
),
5153
1e-2,
5254
)
5355

@@ -85,10 +87,10 @@ def test__via_image_from__psf_off__background_sky_on(image_central_delta_3x3):
8587

8688
assert (
8789
dataset.data.native
88-
== np.array([[1.0, 5.0, 4.0], [1.0, 2.0, 1.0], [5.0, 2.0, 7.0]])
90+
== np.array([[-1.0, -5.0, -4.0], [-1.0, 0.0, -1.0], [-5.0, -2.0, -7.0]])
8991
).all()
9092

91-
assert dataset.noise_map.native[0, 0] == pytest.approx(4.12310, 1.0e-4)
93+
assert dataset.noise_map.native[0, 0] == pytest.approx(3.87298, 1.0e-4)
9294

9395

9496
def test__via_image_from__psf_on__psf_blurs_image_with_edge_trimming(
@@ -143,7 +145,7 @@ def test__via_image_from__psf_on__disable_poisson_noise_in_data(
143145

144146
assert dataset.noise_map.native == pytest.approx(
145147
np.array(
146-
[[0.0, 0.22912, 0.0], [0.25495, 0.34278, 0.22912], [0.0, 0.229128, 0.0]]
148+
[[0.0, 0.21794, 0.0], [0.18708, 0.28723, 0.21794], [0.0, 0.21794, 0.0]]
147149
),
148150
1e-2,
149151
)
@@ -169,5 +171,5 @@ def test__via_image_from__psf_on__psf_and_noise_both_on(image_central_delta_3x3)
169171
dataset = simulator.via_image_from(image=image)
170172

171173
assert dataset.data.native == pytest.approx(
172-
np.array([[4.1, 6.65, 4.45], [6.15, 8.15, 6.5], [4.1, 6.7, 4.25]]), 1e-2
174+
np.array([[3.9, 5.35, 3.55], [5.85, 7.85, 5.5], [3.9, 5.3, 3.75]]), 1e-2
173175
)

test_autoarray/dataset/test_preprocess.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ def test__poisson_noise_from_data():
612612
)
613613

614614
assert (
615-
poisson_noise.native == np.array([[(10.0 - 9.0), 0], [0, (10.0 - 6.0)]])
615+
poisson_noise.native == np.array([[(9.0 - 10.0), 0], [0, (6.0 - 10.0)]])
616616
).all()
617617

618618
data = aa.Array2D.full(fill_value=10.0, shape_native=(2, 2), pixel_scales=1.0)
@@ -623,7 +623,7 @@ def test__poisson_noise_from_data():
623623
)
624624

625625
# Use known noise_map_1d map for given seed.
626-
assert (poisson_noise.native == np.array([[1, 4], [3, 1]])).all()
626+
assert (poisson_noise.native == np.array([[-1, -4], [-3, -1]])).all()
627627

628628
data = aa.Array2D.no_mask(
629629
values=[[10000000.0, 0.0], [0.0, 10000000.0]], pixel_scales=1.0
@@ -634,7 +634,7 @@ def test__poisson_noise_from_data():
634634
data_eps=data, exposure_time_map=exposure_time_map, seed=1
635635
)
636636

637-
assert (poisson_noise.native == np.array([[743, 0], [0, 3783]])).all()
637+
assert (poisson_noise.native == np.array([[-743, 0], [0, -3783]])).all()
638638

639639

640640
def test__data_with_poisson_noised_added():
@@ -654,7 +654,7 @@ def test__data_with_poisson_noised_added():
654654
data_eps=data, exposure_time_map=exposure_time_map, seed=1
655655
)
656656

657-
assert (data_with_poisson_noise.native == np.array([[11, 0], [0, 14]])).all()
657+
assert (data_with_poisson_noise.native == np.array([[9, 0], [0, 6]])).all()
658658

659659
data = aa.Array2D.full(fill_value=10.0, shape_native=(2, 2), pixel_scales=1.0)
660660

@@ -663,7 +663,7 @@ def test__data_with_poisson_noised_added():
663663
data_eps=data, exposure_time_map=exposure_time_map, seed=1
664664
)
665665

666-
assert (data_with_poisson_noise.native == np.array([[11, 14], [13, 11]])).all()
666+
assert (data_with_poisson_noise.native == np.array([[9, 6], [7, 9]])).all()
667667

668668
data = aa.Array2D.no_mask(
669669
values=[[10000000.0, 0.0], [0.0, 10000000.0]], pixel_scales=1.0
@@ -676,7 +676,7 @@ def test__data_with_poisson_noised_added():
676676
)
677677

678678
assert (
679-
data_with_poisson_noise.native == np.array([[10000743, 0.0], [0.0, 10003783.0]])
679+
data_with_poisson_noise.native == np.array([[9999257, 0.0], [0.0, 9996217.0]])
680680
).all()
681681

682682

0 commit comments

Comments
 (0)