Skip to content

Commit ef679e9

Browse files
authored
Merge pull request #81 from DiamondLightSource/paganin_changes
Paganin filter related changes
2 parents fb4c193 + 14dabaa commit ef679e9

File tree

7 files changed

+113
-59
lines changed

7 files changed

+113
-59
lines changed

httomo_backends/methods_database/packages/backends/httomolibgpu/httomolibgpu.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ prep:
7878
multiplier: None
7979
method: module
8080
phase:
81-
paganin_filter_tomopy:
81+
paganin_filter:
8282
pattern: projection
8383
output_dims_change: False
8484
implementation: gpu_cupy

httomo_backends/methods_database/packages/backends/httomolibgpu/supporting_funcs/prep/phase.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@
2020
# ---------------------------------------------------------------------------
2121
"""Modules for memory estimation for phase retrieval and phase-contrast enhancement"""
2222

23-
import math
2423
from typing import Tuple
2524
import numpy as np
2625

2726
from httomo_backends.cufft import CufftType, cufft_estimate_2d
2827

2928
__all__ = [
30-
"_calc_memory_bytes_paganin_filter_tomopy",
29+
"_calc_memory_bytes_paganin_filter",
3130
]
3231

3332

34-
def _calc_memory_bytes_paganin_filter_tomopy(
33+
def _calc_memory_bytes_paganin_filter(
3534
non_slice_dims_shape: Tuple[int, int],
3635
dtype: np.dtype,
3736
**kwargs,

httomo_backends/methods_database/packages/backends/httomolibgpu/supporting_funcs/recon/algorithm.py

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def _calc_memory_bytes_LPRec3d_tomobar(
189189
if detector_pad is True:
190190
detector_pad = __estimate_detectorHoriz_padding(non_slice_dims_shape[1])
191191
elif detector_pad is False:
192-
detector_pad = 0
192+
detector_pad = 0
193193

194194
min_mem_usage_filter = False
195195
if "min_mem_usage_filter" in kwargs:
@@ -208,9 +208,9 @@ def _calc_memory_bytes_LPRec3d_tomobar(
208208
_CENTER_SIZE_MIN = 192 # must be divisible by 8
209209

210210
n = DetectorsLengthH
211-
if(power_of_2_cropping):
211+
if power_of_2_cropping:
212212
n_pow2 = 2 ** math.ceil(math.log2(n))
213-
if( 0.9 < n / n_pow2 ):
213+
if 0.9 < n / n_pow2:
214214
n = n_pow2
215215

216216
odd_horiz = False
@@ -309,10 +309,7 @@ def _calc_memory_bytes_LPRec3d_tomobar(
309309
DetectorsLengthH_prepad * DetectorsLengthH_prepad * np.float32().itemsize
310310
)
311311
ifft2_plan_slice_size = (
312-
cufft_estimate_2d(
313-
nx=2 * n, ny=2 * n, fft_type=CufftType.CUFFT_C2C
314-
)
315-
/ 2
312+
cufft_estimate_2d(nx=2 * n, ny=2 * n, fft_type=CufftType.CUFFT_C2C) / 2
316313
)
317314
circular_mask_size = np.prod(output_dims) / 2 * np.int64().itemsize * 4
318315
after_recon_swapaxis_slice = recon_output_size
@@ -351,38 +348,74 @@ def add_to_memory_counters(amount, per_slice: bool):
351348
add_to_memory_counters(tmp_p_input_slice, True)
352349
if min_mem_usage_filter:
353350
add_to_memory_counters(rfft_plan_slice_size / 4 / projection_chunk_count, False)
354-
add_to_memory_counters(irfft_plan_slice_size / 4 / projection_chunk_count, False)
351+
add_to_memory_counters(
352+
irfft_plan_slice_size / 4 / projection_chunk_count, False
353+
)
355354
add_to_memory_counters(padded_tmp_p_input_slice / projection_chunk_count, False)
356355

357356
add_to_memory_counters(rfft_result_size / projection_chunk_count, False)
358-
add_to_memory_counters(filtered_rfft_result_size / projection_chunk_count, False)
357+
add_to_memory_counters(
358+
filtered_rfft_result_size / projection_chunk_count, False
359+
)
359360
add_to_memory_counters(-rfft_result_size / projection_chunk_count, False)
360-
add_to_memory_counters(-padded_tmp_p_input_slice / projection_chunk_count, False)
361+
add_to_memory_counters(
362+
-padded_tmp_p_input_slice / projection_chunk_count, False
363+
)
361364

362-
add_to_memory_counters(irfft_scratch_memory_size / projection_chunk_count, False)
363-
add_to_memory_counters(-irfft_scratch_memory_size / projection_chunk_count, False)
365+
add_to_memory_counters(
366+
irfft_scratch_memory_size / projection_chunk_count, False
367+
)
368+
add_to_memory_counters(
369+
-irfft_scratch_memory_size / projection_chunk_count, False
370+
)
364371
add_to_memory_counters(irfft_result_size / projection_chunk_count, False)
365-
add_to_memory_counters(-filtered_rfft_result_size / projection_chunk_count, False)
372+
add_to_memory_counters(
373+
-filtered_rfft_result_size / projection_chunk_count, False
374+
)
366375

367376
add_to_memory_counters(-irfft_result_size / projection_chunk_count, False)
368377
else:
369-
add_to_memory_counters(rfft_plan_slice_size / chunk_count / projection_chunk_count * 2, True)
370-
add_to_memory_counters(irfft_plan_slice_size / chunk_count / projection_chunk_count * 2, True)
378+
add_to_memory_counters(
379+
rfft_plan_slice_size / chunk_count / projection_chunk_count * 2, True
380+
)
381+
add_to_memory_counters(
382+
irfft_plan_slice_size / chunk_count / projection_chunk_count * 2, True
383+
)
371384
# add_to_memory_counters(irfft_scratch_memory_size / chunk_count / projection_chunk_count, True)
372385
for _ in range(0, chunk_count):
373-
add_to_memory_counters(padded_tmp_p_input_slice / chunk_count / projection_chunk_count, True)
374-
375-
add_to_memory_counters(rfft_result_size / chunk_count / projection_chunk_count, True)
376-
add_to_memory_counters(filtered_rfft_result_size / chunk_count / projection_chunk_count, True)
377-
add_to_memory_counters(-rfft_result_size / chunk_count / projection_chunk_count, True)
378-
add_to_memory_counters(-padded_tmp_p_input_slice / chunk_count / projection_chunk_count, True)
379-
380-
add_to_memory_counters(irfft_scratch_memory_size / chunk_count / projection_chunk_count, True)
381-
add_to_memory_counters(-irfft_scratch_memory_size / chunk_count / projection_chunk_count, True)
382-
add_to_memory_counters(irfft_result_size / chunk_count / projection_chunk_count, True)
383-
add_to_memory_counters(-filtered_rfft_result_size / chunk_count / projection_chunk_count, True)
384-
385-
add_to_memory_counters(-irfft_result_size / chunk_count / projection_chunk_count, True)
386+
add_to_memory_counters(
387+
padded_tmp_p_input_slice / chunk_count / projection_chunk_count, True
388+
)
389+
390+
add_to_memory_counters(
391+
rfft_result_size / chunk_count / projection_chunk_count, True
392+
)
393+
add_to_memory_counters(
394+
filtered_rfft_result_size / chunk_count / projection_chunk_count, True
395+
)
396+
add_to_memory_counters(
397+
-rfft_result_size / chunk_count / projection_chunk_count, True
398+
)
399+
add_to_memory_counters(
400+
-padded_tmp_p_input_slice / chunk_count / projection_chunk_count, True
401+
)
402+
403+
add_to_memory_counters(
404+
irfft_scratch_memory_size / chunk_count / projection_chunk_count, True
405+
)
406+
add_to_memory_counters(
407+
-irfft_scratch_memory_size / chunk_count / projection_chunk_count, True
408+
)
409+
add_to_memory_counters(
410+
irfft_result_size / chunk_count / projection_chunk_count, True
411+
)
412+
add_to_memory_counters(
413+
-filtered_rfft_result_size / chunk_count / projection_chunk_count, True
414+
)
415+
416+
add_to_memory_counters(
417+
-irfft_result_size / chunk_count / projection_chunk_count, True
418+
)
386419

387420
add_to_memory_counters(-padded_in_slice_size, True)
388421
add_to_memory_counters(-filter_size, False)
@@ -433,7 +466,7 @@ def _calc_memory_bytes_SIRT3d_tomobar(
433466
if detector_pad is True:
434467
detector_pad = __estimate_detectorHoriz_padding(non_slice_dims_shape[1])
435468
elif detector_pad is False:
436-
detector_pad = 0
469+
detector_pad = 0
437470

438471
anglesnum = non_slice_dims_shape[0]
439472
DetectorsLengthH_padded = non_slice_dims_shape[1] + 2 * detector_pad
@@ -456,7 +489,7 @@ def _calc_memory_bytes_SIRT3d_tomobar(
456489
Res_times_R = Res
457490
C_times_res = out_data_size
458491

459-
astra_projection = (in_data_size + out_data_size)
492+
astra_projection = in_data_size + out_data_size
460493

461494
tot_memory_bytes = int(
462495
recon_data_size_original
@@ -483,7 +516,7 @@ def _calc_memory_bytes_CGLS3d_tomobar(
483516
if detector_pad is True:
484517
detector_pad = __estimate_detectorHoriz_padding(non_slice_dims_shape[1])
485518
elif detector_pad is False:
486-
detector_pad = 0
519+
detector_pad = 0
487520

488521
anglesnum = non_slice_dims_shape[0]
489522
DetectorsLengthH_padded = non_slice_dims_shape[1] + 2 * detector_pad
@@ -535,7 +568,7 @@ def _calc_memory_bytes_FISTA3d_tomobar(
535568
if detector_pad is True:
536569
detector_pad = __estimate_detectorHoriz_padding(non_slice_dims_shape[1])
537570
elif detector_pad is False:
538-
detector_pad = 0
571+
detector_pad = 0
539572

540573
anglesnum = non_slice_dims_shape[0]
541574
DetectorsLengthH_padded = non_slice_dims_shape[1] + 2 * detector_pad

httomo_backends/pipelines_full/deg360_paganin_FBP3d_tomobar_directive.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
module_path: httomolibgpu.misc.morph
99
- method: remove_stripe_based_sorting
1010
module_path: httomolibgpu.prep.stripe
11-
- method: paganin_filter_tomopy
11+
- method: paganin_filter
1212
module_path: httomolibgpu.prep.phase
1313
- method: FBP3d_tomobar
1414
module_path: httomolibgpu.recon.algorithm

httomo_backends/pipelines_full/sweep_paganin_FBP3d_tomobar_directive.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
module_path: httomolibgpu.recon.rotation
55
- method: normalize
66
module_path: httomolibgpu.prep.normalize
7-
- method: paganin_filter_tomopy
7+
- method: paganin_filter
88
module_path: httomolibgpu.prep.phase
9-
sweep_parameter: alpha
10-
sweep_values: [0.01, 0.001, 0.0001]
9+
sweep_parameter: ratio_delta_beta
10+
sweep_values: [10, 150, 350]
1111
- method: FBP3d_tomobar
12-
module_path: httomolibgpu.recon.algorithm
12+
module_path: httomolibgpu.recon.algorithm

httomo_backends/scripts/yaml_pipelines_generator.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def yaml_pipelines_generator(
138138

139139
pipeline_full.yaml_set_start_comment(
140140
"This pipeline should be supported by the latest developments of HTTomo. Use module load httomo/latest module at Diamond."
141-
)
141+
)
142142

143143
if "loaders" in module_name:
144144
# should be the first method in the list
@@ -246,8 +246,20 @@ def yaml_pipelines_generator(
246246
)
247247
pipeline_full += yaml_template_method
248248
pipeline_full[i]["parameters"].yaml_add_eol_comment(
249-
key="alpha",
250-
comment="Controls the balance between the strength of the filter and the amount of noise reduction. Smaller values lead to less noise and more blur.",
249+
key="ratio_delta_beta",
250+
comment="The ratio of delta/beta for filter strength control. Larger values lead to more smoothing.",
251+
)
252+
pipeline_full[i]["parameters"].yaml_add_eol_comment(
253+
key="pixel_size",
254+
comment="Detector pixel size (resolution) in MICRON units.",
255+
)
256+
pipeline_full[i]["parameters"].yaml_add_eol_comment(
257+
key="distance",
258+
comment="Propagation distance of the wavefront from sample to detector in METRE units.",
259+
)
260+
pipeline_full[i]["parameters"].yaml_add_eol_comment(
261+
key="energy",
262+
comment="Beam energy in keV.",
251263
)
252264
elif "stripe" in module_name:
253265
pipeline_full.yaml_set_comment_before_after_key(
@@ -273,7 +285,7 @@ def yaml_pipelines_generator(
273285
)
274286
pipeline_full[i]["parameters"].yaml_add_eol_comment(
275287
key="recon_mask_radius",
276-
comment="Zero pixels outside the mask-circle radius.",
288+
comment="Zero pixels outside the mask-circle radius. Make radius equal to 2.0 to remove the mask effect.",
277289
)
278290
pipeline_full[i]["parameters"].yaml_add_eol_comment(
279291
key="neglog",

tests/test_httomolibgpu.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from httomolibgpu.misc.morph import data_resampler, sino_360_to_180
1717
from httomolibgpu.prep.normalize import normalize
18-
from httomolibgpu.prep.phase import paganin_filter_tomopy
18+
from httomolibgpu.prep.phase import paganin_filter
1919
from httomolibgpu.prep.alignment import distortion_correction_proj_discorpy
2020
from httomolibgpu.prep.stripe import (
2121
remove_stripe_based_sorting,
@@ -228,19 +228,19 @@ def test_denoiser_PD_TV_memoryhook(ensure_clean_memory, slices):
228228
@pytest.mark.parametrize("slices", [64, 128])
229229
@pytest.mark.parametrize("dim_x", [81, 260, 320])
230230
@pytest.mark.parametrize("dim_y", [340, 135, 96])
231-
def test_paganin_filter_tomopy_memoryhook(slices, dim_x, dim_y, ensure_clean_memory):
231+
def test_paganin_filter_memoryhook(slices, dim_x, dim_y, ensure_clean_memory):
232232
data = cp.random.random_sample((slices, dim_x, dim_y), dtype=np.float32)
233233
hook = MaxMemoryHook()
234234
with hook:
235-
data_filtered = paganin_filter_tomopy(cp.copy(data)).get()
235+
data_filtered = paganin_filter(cp.copy(data)).get()
236236

237237
# make sure estimator function is within range (80% min, 100% max)
238238
max_mem = (
239239
hook.max_mem
240240
) # the amount of memory in bytes needed for the method according to memoryhook
241241

242242
# now we estimate how much of the total memory required for this data
243-
(estimated_memory_bytes, subtract_bytes) = _calc_memory_bytes_paganin_filter_tomopy(
243+
(estimated_memory_bytes, subtract_bytes) = _calc_memory_bytes_paganin_filter(
244244
(dim_x, dim_y), dtype=np.float32()
245245
)
246246
estimated_memory_mb = round(slices * estimated_memory_bytes / (1024**2), 2)
@@ -574,7 +574,9 @@ def test_recon_LPRec3d_tomobar_0_pi_memoryhook(
574574

575575
@pytest.mark.full
576576
@pytest.mark.cupy
577-
@pytest.mark.parametrize("min_mem_usage_filter_ifft2", [(False, False), (True, False), (True, True)])
577+
@pytest.mark.parametrize(
578+
"min_mem_usage_filter_ifft2", [(False, False), (True, False), (True, True)]
579+
)
578580
@pytest.mark.parametrize("power_of_2_cropping", [False, True])
579581
@pytest.mark.parametrize("padding_detx", [0, 10, 50, 100, 800])
580582
@pytest.mark.parametrize("projections", [1500, 1801, 2560, 3601])
@@ -605,7 +607,9 @@ def test_recon_LPRec3d_tomobar_0_pi_memoryhook_full(
605607

606608
@pytest.mark.full
607609
@pytest.mark.cupy
608-
@pytest.mark.parametrize("min_mem_usage_filter_ifft2", [(False, False), (True, False), (True, True)])
610+
@pytest.mark.parametrize(
611+
"min_mem_usage_filter_ifft2", [(False, False), (True, False), (True, True)]
612+
)
609613
@pytest.mark.parametrize("power_of_2_cropping", [False, True])
610614
@pytest.mark.parametrize("padding_detx", [0, 10, 50, 100, 800])
611615
@pytest.mark.parametrize("projections", [1500, 1801, 2560, 3601])
@@ -742,10 +746,13 @@ def test_recon_SIRT3d_tomobar_memoryhook(slices, recon_size_it, ensure_clean_mem
742746
assert estimated_memory_mb >= max_mem_mb
743747
assert percents_relative_maxmem <= 100
744748

749+
745750
@pytest.mark.cupy
746751
@pytest.mark.parametrize("slices", [3])
747752
@pytest.mark.parametrize("recon_size_it", [2560])
748-
def test_recon_SIRT3d_tomobar_autopad_memoryhook(slices, recon_size_it, ensure_clean_memory):
753+
def test_recon_SIRT3d_tomobar_autopad_memoryhook(
754+
slices, recon_size_it, ensure_clean_memory
755+
):
749756
angles_tot = 901
750757
det_size = 2560
751758
data = cp.random.random_sample((angles_tot, slices, det_size), dtype=np.float32)
@@ -758,8 +765,8 @@ def test_recon_SIRT3d_tomobar_autopad_memoryhook(slices, recon_size_it, ensure_c
758765
recon_data = SIRT3d_tomobar(
759766
cp.copy(data),
760767
np.linspace(0.0 * np.pi / 180.0, 180.0 * np.pi / 180.0, data.shape[0]),
761-
center = 1200,
762-
detector_pad = True,
768+
center=1200,
769+
detector_pad=True,
763770
recon_size=recon_size_it,
764771
iterations=2,
765772
nonnegativity=True,
@@ -803,8 +810,8 @@ def test_recon_CGLS3d_tomobar_memoryhook(slices, recon_size_it, ensure_clean_mem
803810
recon_data = CGLS3d_tomobar(
804811
cp.copy(data),
805812
np.linspace(0.0 * np.pi / 180.0, 180.0 * np.pi / 180.0, data.shape[0]),
806-
center = 1200,
807-
detector_pad = False,
813+
center=1200,
814+
detector_pad=False,
808815
recon_size=recon_size_it,
809816
iterations=2,
810817
nonnegativity=True,
@@ -835,7 +842,9 @@ def test_recon_CGLS3d_tomobar_memoryhook(slices, recon_size_it, ensure_clean_mem
835842
@pytest.mark.cupy
836843
@pytest.mark.parametrize("slices", [3])
837844
@pytest.mark.parametrize("recon_size_it", [2560])
838-
def test_recon_CGLS3d_tomobar_autopad_memoryhook(slices, recon_size_it, ensure_clean_memory):
845+
def test_recon_CGLS3d_tomobar_autopad_memoryhook(
846+
slices, recon_size_it, ensure_clean_memory
847+
):
839848
angles_tot = 901
840849
det_size = 2560
841850
data = cp.random.random_sample((angles_tot, slices, det_size), dtype=np.float32)
@@ -848,8 +857,8 @@ def test_recon_CGLS3d_tomobar_autopad_memoryhook(slices, recon_size_it, ensure_c
848857
recon_data = CGLS3d_tomobar(
849858
cp.copy(data),
850859
np.linspace(0.0 * np.pi / 180.0, 180.0 * np.pi / 180.0, data.shape[0]),
851-
center = 1200,
852-
detector_pad = True,
860+
center=1200,
861+
detector_pad=True,
853862
recon_size=recon_size_it,
854863
iterations=2,
855864
nonnegativity=True,
@@ -876,6 +885,7 @@ def test_recon_CGLS3d_tomobar_autopad_memoryhook(slices, recon_size_it, ensure_c
876885
assert estimated_memory_mb >= max_mem_mb
877886
assert percents_relative_maxmem <= 85
878887

888+
879889
@pytest.mark.cupy
880890
@pytest.mark.parametrize("slices", [3, 5])
881891
@pytest.mark.parametrize("recon_size_it", [2560])

0 commit comments

Comments
 (0)