Skip to content

Commit 9fac44e

Browse files
committed
Bugfix: Fix normalization factors for gridder / imager
Makes more sense to keep beam / image vis at same normalization. Then, post FFT we can correct for both sample-weightings and FFT-normalization in a single operation.
1 parent c4a9969 commit 9fac44e

File tree

5 files changed

+24
-17
lines changed

5 files changed

+24
-17
lines changed

src/fastimgproto/gridder/gridder.py

+4-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ def convolve_to_grid(kernel_func,
2323
raise_bounds=True,
2424
progress_bar=None):
2525
"""
26-
Grid visibilities, calculating the exact kernel distribution for each.
26+
Grid visibilities using convolutional gridding.
27+
28+
Returns the **un-normalized** weighted visibilities; the
29+
weights-renormalization factor can be calculated by summing the sample grid.
2730
2831
If ``exact == True`` then exact gridding is used, i.e. the kernel is
2932
recalculated for each visibility, with precise sub-pixel offset according to
@@ -135,13 +138,6 @@ def convolve_to_grid(kernel_func,
135138
if progress_bar is not None:
136139
progress_bar.update(1)
137140

138-
# Finally, renormalise the visibilities by the sampled weights total
139-
# NB, this is computationally expensive, and can be side-stepped
140-
# by simply tracking the sum of 'good_vis' weights, then normalizing
141-
# source-fluxes later on. But we do it here for completeness.
142-
sample_grid_total = sampling_grid.sum()
143-
if sample_grid_total != 0. :
144-
vis_grid /= sample_grid_total
145141
return vis_grid, sampling_grid
146142

147143

src/fastimgproto/imager.py

+10
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ def image_visibilities(vis,
8383
)
8484
image = fft_to_image_plane(vis_grid)
8585
beam = fft_to_image_plane(sample_grid)
86+
87+
total_sample_weight = sample_grid.sum()
88+
# To calculate the normalization factor:
89+
# We correct for the FFT scale factor of 1/image_size**2
90+
# (cf https://docs.scipy.org/doc/numpy/reference/routines.fft.html#implementation-details)
91+
# And then divide by the total sample weight to renormalize the visibilities.
92+
if total_sample_weight!=0:
93+
renormalization_factor = (image_size_int*image_size_int)/total_sample_weight
94+
beam *= renormalization_factor
95+
image *= renormalization_factor
8696
if normalize:
8797
beam_max = np.max(np.real(beam))
8898
beam /= beam_max

tests/test_gridder/test_exact_gridding.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ def test_single_pixel_overlap_pillbox():
3636
[0., 0., 0., 0., 0., 0., 0., 0., ],
3737
[0., 0., 0., 0., 0., 0., 0., 0., ]]
3838
)
39-
assert (expected_sample_grid * vis_amplitude == vis_grid).all()
39+
assert (expected_sample_grid * vis_amplitude * vis_weights.sum()
40+
== vis_grid).all()
4041
assert (expected_sample_grid * vis_weights.sum() == sampling_grid).all()
4142

4243

@@ -184,7 +185,7 @@ def test_multiple_complex_vis():
184185
vis_weights=vis_weights,
185186
)
186187
# simplification true since weights are all 1:
187-
assert vis_grid.sum() == vis.sum() / vis_weights.sum()
188+
assert vis_grid.sum() == vis.sum()
188189

189190
# Since uv is precisely on a sampling point, we'll get a
190191
# 3x3 pillbox
@@ -201,7 +202,7 @@ def test_multiple_complex_vis():
201202
[0., v, v, v, 0., 0., 0., 0.],
202203
[0., 0., 0., 0., 0., 0., 0., 0.]]
203204
)
204-
assert (expected_sample_grid / sampling_grid.sum() == vis_grid).all()
205+
assert (expected_sample_grid == vis_grid).all()
205206
assert (expected_sample_grid == sampling_grid).all()
206207

207208

@@ -227,7 +228,7 @@ def test_nearby_complex_vis():
227228
vis_weights=vis_weights,
228229
)
229230
# simplification true since weights are all 1:
230-
assert vis_grid.sum() == vis.sum() / vis_weights.sum()
231+
assert vis_grid.sum() == vis.sum()
231232

232233
# Since uv is precisely on a sampling point, we'll get a
233234
# 3x3 pillbox
@@ -244,8 +245,8 @@ def test_nearby_complex_vis():
244245
[0., v, v, v, 0., 0., 0., 0.],
245246
[0., 0., 0., 0., 0., 0., 0., 0.]]
246247
)
247-
248-
assert (expected_sample_grid / vis_weights.sum() == vis_grid).all()
248+
# simplification true since weights are all 1:
249+
assert (expected_sample_grid == vis_grid).all()
249250
assert (expected_sample_grid == sampling_grid).all()
250251

251252

tests/test_gridder/test_oversampled_gridding.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,4 @@ def test_oversampled_gridding():
186186
)
187187

188188
# simplification true since weights are all 1:
189-
assert vis_grid.sum() == vis.sum() / vis_weights.sum()
189+
assert vis_grid.sum() == vis.sum()

tests/test_gridder/test_sample_weighting.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,6 @@ def test_natural_weighting():
8585
[0., 0., 0., 0., 0., 0., 0., 0., ]]
8686
)
8787
assert (
88-
expected_sample_locations * vis_weights.sum() == sampling_grid).all()
88+
expected_sample_locations == sampling_grid/sampling_grid.sum()).all()
8989
assert ((expected_sample_locations * natural_weighted_sum) ==
90-
vis_grid).all()
90+
vis_grid / sampling_grid.sum()).all()

0 commit comments

Comments
 (0)