httomolibgpu 5.5.1__tar.gz → 5.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {httomolibgpu-5.5.1/httomolibgpu.egg-info → httomolibgpu-5.7}/PKG-INFO +1 -1
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/denoise.py +3 -1
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/morph.py +52 -21
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/rescale.py +0 -1
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/prep/normalize.py +71 -11
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/recon/algorithm.py +135 -4
- {httomolibgpu-5.5.1 → httomolibgpu-5.7/httomolibgpu.egg-info}/PKG-INFO +1 -1
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/LICENSE +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/MANIFEST.in +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/README.rst +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/__init__.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/__init__.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/calc_metrics.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/center_360_shifts.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/generate_mask.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/median_kernel.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/raven_filter.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/remove_nan_inf.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cuda_kernels/remove_stripe_fw.cu +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/cupywrapper.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/__init__.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/corr.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/misc/utils.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/prep/__init__.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/prep/alignment.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/prep/phase.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/prep/stripe.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/recon/__init__.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/recon/_phase_cross_correlation.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu/recon/rotation.py +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu.egg-info/SOURCES.txt +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu.egg-info/dependency_links.txt +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu.egg-info/requires.txt +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/httomolibgpu.egg-info/top_level.txt +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/pyproject.toml +0 -0
- {httomolibgpu-5.5.1 → httomolibgpu-5.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: httomolibgpu
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.7
|
|
4
4
|
Summary: Commonly used tomography data processing methods at DLS.
|
|
5
5
|
Author-email: Daniil Kazantsev <daniil.kazantsev@diamond.ac.uk>, Yousef Moazzam <yousef.moazzam@diamond.ac.uk>, Naman Gera <naman.gera@diamond.ac.uk>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -175,7 +175,9 @@ def total_variation_PD(
|
|
|
175
175
|
__check_variable_type(iterations, [int], "iterations", [], methods_name)
|
|
176
176
|
__check_variable_type(isotropic, [bool], "isotropic", [], methods_name)
|
|
177
177
|
__check_variable_type(nonnegativity, [bool], "nonnegativity", [], methods_name)
|
|
178
|
-
__check_variable_type(
|
|
178
|
+
__check_variable_type(
|
|
179
|
+
lipschitz_const, [float, int], "lipschitz_const", [], methods_name
|
|
180
|
+
)
|
|
179
181
|
__check_variable_type(gpu_id, [int], "gpu_id", [], methods_name)
|
|
180
182
|
__check_variable_type(half_precision, [bool], "half_precision", [], methods_name)
|
|
181
183
|
###################################
|
|
@@ -80,45 +80,76 @@ def sino_360_to_180(
|
|
|
80
80
|
)
|
|
81
81
|
__check_variable_type(overlap, [int, float], "overlap", [], methods_name)
|
|
82
82
|
__check_variable_type(side, [str], "side", ["left", "right"], methods_name)
|
|
83
|
-
__check_if_positive_nonzero(
|
|
84
|
-
overlap, "overlap", positive=True, nonzero=True, methods_name=methods_name
|
|
85
|
-
)
|
|
86
83
|
###################################
|
|
87
84
|
#
|
|
88
85
|
dx, dy, dz = data.shape
|
|
89
86
|
|
|
90
87
|
overlap = int(np.round(overlap))
|
|
91
|
-
if overlap >= dz - 1:
|
|
92
|
-
raise ValueError("Overlap must be less than size of the horizontal detector")
|
|
93
88
|
if overlap % 2 != 0:
|
|
94
89
|
overlap += 1
|
|
95
|
-
|
|
90
|
+
overlap_pos = abs(overlap)
|
|
91
|
+
if overlap_pos >= dz - 1:
|
|
92
|
+
raise ValueError("Overlap must be less than size of the horizontal detector")
|
|
96
93
|
n = dx // 2
|
|
97
94
|
out = cp.empty((n, dy, 2 * dz - overlap), dtype=data.dtype)
|
|
98
95
|
|
|
99
96
|
if side == "left":
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
97
|
+
if overlap == 0:
|
|
98
|
+
out[:, :, -dz:] = data[:n, :, :]
|
|
99
|
+
out[:, :, :dz] = data[n : 2 * n, :, :][:, :, ::-1]
|
|
100
|
+
return out
|
|
101
|
+
elif overlap < 0:
|
|
102
|
+
out[:, :, -dz:] = data[:n, :, :]
|
|
103
|
+
out[:, :, : (dz + overlap_pos)] = cp.pad(
|
|
104
|
+
data[n : 2 * n, :, :][:, :, ::-1],
|
|
105
|
+
pad_width=(
|
|
106
|
+
(0, 0),
|
|
107
|
+
(0, 0),
|
|
108
|
+
(0, overlap_pos),
|
|
109
|
+
),
|
|
110
|
+
mode="edge",
|
|
111
|
+
)
|
|
112
|
+
return out
|
|
113
|
+
else:
|
|
114
|
+
weights = cp.linspace(0, 1.0, overlap, dtype=cp.float32)
|
|
115
|
+
out[:, :, -dz + overlap :] = data[:n, :, overlap:]
|
|
116
|
+
out[:, :, : dz - overlap] = data[n : 2 * n, :, overlap:][:, :, ::-1]
|
|
117
|
+
out[:, :, dz - overlap : dz] = (
|
|
118
|
+
weights * data[:n, :, :overlap]
|
|
119
|
+
+ (weights * data[n : 2 * n, :, :overlap])[:, :, ::-1]
|
|
120
|
+
)
|
|
107
121
|
if side == "right":
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
if overlap == 0:
|
|
123
|
+
out[:, :, :dz] = data[:n, :, :]
|
|
124
|
+
out[:, :, dz::] = data[n : 2 * n, :, :][:, :, ::-1]
|
|
125
|
+
return out
|
|
126
|
+
elif overlap < 0:
|
|
127
|
+
out[:, :, : (dz + overlap_pos)] = cp.pad(
|
|
128
|
+
data[:n, :, :],
|
|
129
|
+
pad_width=(
|
|
130
|
+
(0, 0),
|
|
131
|
+
(0, 0),
|
|
132
|
+
(0, overlap_pos),
|
|
133
|
+
),
|
|
134
|
+
mode="edge",
|
|
135
|
+
)
|
|
136
|
+
out[:, :, (dz + overlap_pos) : :] = data[n : 2 * n, :, :][:, :, ::-1]
|
|
137
|
+
return out
|
|
138
|
+
else:
|
|
139
|
+
weights = cp.linspace(1.0, 0, overlap, dtype=cp.float32)
|
|
140
|
+
out[:, :, : dz - overlap] = data[:n, :, :-overlap]
|
|
141
|
+
out[:, :, -dz + overlap :] = data[n : 2 * n, :, :-overlap][:, :, ::-1]
|
|
142
|
+
out[:, :, dz - overlap : dz] = (
|
|
143
|
+
weights * data[:n, :, -overlap:]
|
|
144
|
+
+ (weights * data[n : 2 * n, :, -overlap:])[:, :, ::-1]
|
|
145
|
+
)
|
|
115
146
|
|
|
116
147
|
return cp.pad(
|
|
117
148
|
out,
|
|
118
149
|
pad_width=(
|
|
119
150
|
(0, 0),
|
|
120
151
|
(0, 0),
|
|
121
|
-
(
|
|
152
|
+
(overlap_pos // 2, overlap_pos // 2),
|
|
122
153
|
),
|
|
123
154
|
mode="edge",
|
|
124
155
|
)
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"""Modules for raw projection data normalization"""
|
|
22
22
|
|
|
23
23
|
from httomolibgpu import cupywrapper
|
|
24
|
+
import numpy as np
|
|
24
25
|
|
|
25
26
|
cp = cupywrapper.cp
|
|
26
27
|
cupy_run = cupywrapper.cupy_run
|
|
@@ -32,8 +33,8 @@ if cupy_run:
|
|
|
32
33
|
else:
|
|
33
34
|
mean = Mock()
|
|
34
35
|
|
|
35
|
-
from typing import Union
|
|
36
|
-
from numpy import float32
|
|
36
|
+
from typing import Union, Optional
|
|
37
|
+
from numpy import float32, int64
|
|
37
38
|
from httomolibgpu.misc.utils import (
|
|
38
39
|
__check_variable_type,
|
|
39
40
|
__check_if_data_3D_array,
|
|
@@ -49,7 +50,8 @@ def dark_flat_field_correction(
|
|
|
49
50
|
darks: cp.ndarray,
|
|
50
51
|
flats_multiplier: Union[float, int] = 1.0,
|
|
51
52
|
darks_multiplier: Union[float, int] = 1.0,
|
|
52
|
-
|
|
53
|
+
upper_bound: Optional[Union[float, int]] = None,
|
|
54
|
+
lower_bound: Optional[Union[float, int]] = None,
|
|
53
55
|
) -> cp.ndarray:
|
|
54
56
|
"""
|
|
55
57
|
Perform dark/flat field correction of raw projection data.
|
|
@@ -66,8 +68,10 @@ def dark_flat_field_correction(
|
|
|
66
68
|
A multiplier to apply to flats, can work as an intensity compensation constant.
|
|
67
69
|
darks_multiplier: float,int
|
|
68
70
|
A multiplier to apply to darks, can work as an intensity compensation constant.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
upper_bound : Optional[float, int]
|
|
72
|
+
All values above the upper bound are set to the provided value. Default None.
|
|
73
|
+
lower_bound : Optional[float, int]
|
|
74
|
+
All values bellow the lower bound are set to the provided value. Default None.
|
|
71
75
|
|
|
72
76
|
Returns
|
|
73
77
|
-------
|
|
@@ -92,10 +96,21 @@ def dark_flat_field_correction(
|
|
|
92
96
|
__check_variable_type(
|
|
93
97
|
darks_multiplier, [int, float], "darks_multiplier", [], methods_name
|
|
94
98
|
)
|
|
95
|
-
__check_variable_type(
|
|
96
|
-
|
|
99
|
+
__check_variable_type(
|
|
100
|
+
upper_bound, [int, float, type(None)], "upper_bound", [], methods_name
|
|
101
|
+
)
|
|
102
|
+
__check_variable_type(
|
|
103
|
+
lower_bound, [int, float, type(None)], "lower_bound", [], methods_name
|
|
104
|
+
)
|
|
97
105
|
|
|
98
106
|
_check_valid_input_flats_darks(flats, darks)
|
|
107
|
+
###################################
|
|
108
|
+
|
|
109
|
+
data_elements_num = int(np.prod(data.shape))
|
|
110
|
+
if upper_bound is None:
|
|
111
|
+
upper_bound = 1e12
|
|
112
|
+
if lower_bound is None:
|
|
113
|
+
lower_bound = -1e12
|
|
99
114
|
|
|
100
115
|
dark0 = cp.empty(darks.shape[1:], dtype=float32)
|
|
101
116
|
flat0 = cp.empty(flats.shape[1:], dtype=float32)
|
|
@@ -114,12 +129,12 @@ def dark_flat_field_correction(
|
|
|
114
129
|
}
|
|
115
130
|
float v = (float(data) - float(darks))/denom;
|
|
116
131
|
"""
|
|
117
|
-
kernel += "if (v >
|
|
118
|
-
kernel += "if (v
|
|
132
|
+
kernel += "if (v > upper_bound) v = upper_bound;\n"
|
|
133
|
+
kernel += "if (v <= lower_bound) v = lower_bound;\n"
|
|
119
134
|
kernel += "out = v;\n"
|
|
120
135
|
|
|
121
136
|
normalisation_kernel = cp.ElementwiseKernel(
|
|
122
|
-
"T data, U flats, U darks, raw float32
|
|
137
|
+
"T data, U flats, U darks, raw float32 upper_bound, raw float32 lower_bound",
|
|
123
138
|
"float32 out",
|
|
124
139
|
kernel,
|
|
125
140
|
kernel_name,
|
|
@@ -128,7 +143,52 @@ def dark_flat_field_correction(
|
|
|
128
143
|
no_return=True,
|
|
129
144
|
)
|
|
130
145
|
|
|
131
|
-
|
|
146
|
+
count_greater_kernel = cp.ReductionKernel(
|
|
147
|
+
in_params="T data, raw float32 upper_bound",
|
|
148
|
+
out_params="int32 out",
|
|
149
|
+
map_expr="data >= upper_bound ? 1 : 0", # map each element → 1 or 0
|
|
150
|
+
reduce_expr="a + b", # sum them
|
|
151
|
+
post_map_expr="out = a", # final result
|
|
152
|
+
identity="0",
|
|
153
|
+
name="count_greater",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
count_smaller_kernel = cp.ReductionKernel(
|
|
157
|
+
in_params="T data, raw float32 lower_bound",
|
|
158
|
+
out_params="int32 out",
|
|
159
|
+
map_expr="data <= lower_bound ? 1 : 0", # map each element → 1 or 0
|
|
160
|
+
reduce_expr="a + b", # sum them
|
|
161
|
+
post_map_expr="out = a", # final result
|
|
162
|
+
identity="0",
|
|
163
|
+
name="count_smaller",
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
normalisation_kernel(data, flat0, dark0, upper_bound, lower_bound, out)
|
|
167
|
+
|
|
168
|
+
# Count the amount of clipping and raise warnings if required
|
|
169
|
+
clipped_percentage_warning = (
|
|
170
|
+
50.0 # warning if more clipped values than given percentage
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
clipped_total_up = int(count_greater_kernel(out, float32(upper_bound)))
|
|
174
|
+
clipped_up_percent = clipped_total_up / data_elements_num * 100
|
|
175
|
+
|
|
176
|
+
if clipped_up_percent >= clipped_percentage_warning:
|
|
177
|
+
print(
|
|
178
|
+
"Warning! The output data of 'dark_flat_field_correction' method contains \033[31m{}\033[0m percent of 'upper_bound' clipped data.".format(
|
|
179
|
+
int(clipped_up_percent)
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
clipped_total_lower = int(count_smaller_kernel(out, float32(lower_bound)))
|
|
184
|
+
clipped_down_percent = clipped_total_lower / data_elements_num * 100
|
|
185
|
+
|
|
186
|
+
if clipped_down_percent >= clipped_percentage_warning:
|
|
187
|
+
print(
|
|
188
|
+
"Warning! The output data of 'dark_flat_field_correction' method contains \033[31m{}\033[0m percent of 'lower_bound' clipped data.".format(
|
|
189
|
+
int(clipped_down_percent)
|
|
190
|
+
)
|
|
191
|
+
)
|
|
132
192
|
|
|
133
193
|
return out
|
|
134
194
|
|
|
@@ -56,6 +56,7 @@ __all__ = [
|
|
|
56
56
|
"CGLS3d_tomobar",
|
|
57
57
|
"FISTA3d_tomobar",
|
|
58
58
|
"ADMM3d_tomobar",
|
|
59
|
+
"OSEM3d_tomobar",
|
|
59
60
|
]
|
|
60
61
|
|
|
61
62
|
input_data_axis_labels = ["angles", "detY", "detX"] # set the labels of the input data
|
|
@@ -126,7 +127,18 @@ def FBP2d_astra(
|
|
|
126
127
|
filter_type,
|
|
127
128
|
[str],
|
|
128
129
|
"filter_type",
|
|
129
|
-
[
|
|
130
|
+
[
|
|
131
|
+
"none",
|
|
132
|
+
"ram-lak",
|
|
133
|
+
"cosine",
|
|
134
|
+
"shepp-logan",
|
|
135
|
+
"tukey",
|
|
136
|
+
"gaussian",
|
|
137
|
+
"blackman",
|
|
138
|
+
"kaiser",
|
|
139
|
+
"lanczos",
|
|
140
|
+
"hann",
|
|
141
|
+
],
|
|
130
142
|
methods_name,
|
|
131
143
|
)
|
|
132
144
|
__check_variable_type(
|
|
@@ -552,7 +564,7 @@ def FISTA3d_tomobar(
|
|
|
552
564
|
subsets_number: int
|
|
553
565
|
The number of the ordered subsets to accelerate convergence. Keep the value bellow 10 to avoid divergence.
|
|
554
566
|
data_fidelity: str
|
|
555
|
-
Data fidelity given as 'LS' (Least Squares)
|
|
567
|
+
Data fidelity given as 'LS' (Least Squares)
|
|
556
568
|
regularisation_type: str
|
|
557
569
|
A method to use for regularisation. Currently PD_TV and ROF_TV are available.
|
|
558
570
|
regularisation_parameter: float
|
|
@@ -644,7 +656,7 @@ def ADMM3d_tomobar(
|
|
|
644
656
|
initialisation: Literal["FBP", "CGLS", "SIRT", None] = "FBP",
|
|
645
657
|
ADMM_rho_const: float = 1.0,
|
|
646
658
|
ADMM_relax_par: float = 1.7,
|
|
647
|
-
regularisation_type:
|
|
659
|
+
regularisation_type: Literal["ROF_TV", "PD_TV"] = "PD_TV",
|
|
648
660
|
regularisation_parameter: float = 0.0025,
|
|
649
661
|
regularisation_iterations: int = 40,
|
|
650
662
|
regularisation_half_precision: bool = True,
|
|
@@ -679,7 +691,7 @@ def ADMM3d_tomobar(
|
|
|
679
691
|
subsets_number: int
|
|
680
692
|
The number of the ordered subsets to accelerate convergence. The recommended range is between 12 to 24.
|
|
681
693
|
data_fidelity: str
|
|
682
|
-
Data fidelity given as 'LS' (Least Squares)
|
|
694
|
+
Data fidelity given as 'LS' (Least Squares)
|
|
683
695
|
initialisation: str, optional
|
|
684
696
|
Initialise ADMM with the reconstructed image to reduce the number of iterations and accelerate. Choose between 'CGLS' or 'SIRT' when data
|
|
685
697
|
is noisy and/or undersampled. Choose 'FBP' when the data is of better quality (default) or None.
|
|
@@ -835,6 +847,125 @@ def ADMM3d_tomobar(
|
|
|
835
847
|
return cp.require(cp.swapaxes(reconstruction, 0, 1), requirements="C")
|
|
836
848
|
|
|
837
849
|
|
|
850
|
+
## %%%%%%%%%%%%%%%%%%%%%%% OSEM reconstruction %%%%%%%%%%%%%%%%%%%%%%%%%%%% ##
|
|
851
|
+
def OSEM3d_tomobar(
|
|
852
|
+
data: cp.ndarray,
|
|
853
|
+
angles: np.ndarray,
|
|
854
|
+
center: Optional[float] = None,
|
|
855
|
+
detector_pad: Union[bool, int] = False,
|
|
856
|
+
recon_size: Optional[int] = None,
|
|
857
|
+
recon_mask_radius: Optional[float] = 0.95,
|
|
858
|
+
iterations: int = 20,
|
|
859
|
+
subsets_number: int = 12,
|
|
860
|
+
regularisation_type: Literal["ROF_TV", "PD_TV"] = "PD_TV",
|
|
861
|
+
regularisation_parameter: float = 1.0,
|
|
862
|
+
regularisation_iterations: int = 30,
|
|
863
|
+
regularisation_half_precision: bool = True,
|
|
864
|
+
nonnegativity: bool = True,
|
|
865
|
+
gpu_id: int = 0,
|
|
866
|
+
) -> cp.ndarray:
|
|
867
|
+
"""
|
|
868
|
+
Ordered-Subsets Expectation-Maximisation method is the accelerated Maximum Likelihood Expectation-Maximisation (MLEM) algorithm.
|
|
869
|
+
Can be coupled with various types of regularisation or denoising operations :cite:`kazantsev2019ccpi` (currently accepts ROF_TV and PD_TV regularisations only).
|
|
870
|
+
Should be applied to reconstruct emission-type measurements, e.g., XRF tomography measurements.
|
|
871
|
+
|
|
872
|
+
Parameters
|
|
873
|
+
----------
|
|
874
|
+
data : cp.ndarray
|
|
875
|
+
Projection data as a CuPy array.
|
|
876
|
+
angles : np.ndarray
|
|
877
|
+
An array of angles given in radians.
|
|
878
|
+
center : float, optional
|
|
879
|
+
The center of rotation (CoR).
|
|
880
|
+
detector_pad : bool, int
|
|
881
|
+
Detector width padding with edge values to remove circle/arc type artifacts in the reconstruction. Set to True to perform
|
|
882
|
+
an automated padding or specify a certain value as an integer.
|
|
883
|
+
recon_size : int, optional
|
|
884
|
+
The squared size of the reconstructed slice. By default (None), the reconstructed size will be the dimension of the horizontal detector.
|
|
885
|
+
recon_mask_radius: float, optional
|
|
886
|
+
The radius of the circular mask that applies to the reconstructed slice in order to crop
|
|
887
|
+
out some undesirable artifacts. The values outside the given diameter will be set to zero.
|
|
888
|
+
To implement the cropping one can use the range [0.7-1.0] or set to None (2.0) when no cropping is needed.
|
|
889
|
+
iterations : int
|
|
890
|
+
The number of OSEM algorithm iterations. For OS method 20 interations is normally sufficient, while for MLEM one should run 300-500 iterations.
|
|
891
|
+
subsets_number: int
|
|
892
|
+
The number of the ordered subsets to accelerate convergence. One can set 'subsets_number' to 1 to achieve MLEM, but the number of 'iterations' should be also increased.
|
|
893
|
+
data_fidelity: str
|
|
894
|
+
Data fidelity given as 'LS' (Least Squares)
|
|
895
|
+
regularisation_type: str
|
|
896
|
+
A method to use for regularisation. Currently PD_TV and ROF_TV are available.
|
|
897
|
+
regularisation_parameter: float
|
|
898
|
+
The main regularisation parameter to control the amount of smoothing/noise removal. Larger values lead to stronger smoothing.
|
|
899
|
+
regularisation_iterations: int
|
|
900
|
+
The number of iterations for regularisers (aka INNER iterations).
|
|
901
|
+
regularisation_half_precision: bool
|
|
902
|
+
Perform faster regularisation computation in half-precision with a very minimal sacrifice in quality.
|
|
903
|
+
nonnegativity : bool
|
|
904
|
+
Impose nonnegativity constraint on the reconstructed image.
|
|
905
|
+
gpu_id : int
|
|
906
|
+
A GPU device index to perform operation on.
|
|
907
|
+
|
|
908
|
+
Returns
|
|
909
|
+
-------
|
|
910
|
+
cp.ndarray
|
|
911
|
+
The OSEM reconstructed volume as a CuPy array.
|
|
912
|
+
"""
|
|
913
|
+
### Data and parameters checks ###
|
|
914
|
+
methods_name = "OSEM3d_tomobar"
|
|
915
|
+
__common_data_parameters_check(
|
|
916
|
+
data,
|
|
917
|
+
angles,
|
|
918
|
+
methods_name,
|
|
919
|
+
center,
|
|
920
|
+
detector_pad,
|
|
921
|
+
recon_size,
|
|
922
|
+
recon_mask_radius,
|
|
923
|
+
gpu_id,
|
|
924
|
+
)
|
|
925
|
+
__common_iterative_basic_parameters_check(methods_name, iterations, nonnegativity)
|
|
926
|
+
__common_iterative_parameters_check(
|
|
927
|
+
methods_name,
|
|
928
|
+
subsets_number,
|
|
929
|
+
regularisation_type,
|
|
930
|
+
regularisation_parameter,
|
|
931
|
+
regularisation_iterations,
|
|
932
|
+
regularisation_half_precision,
|
|
933
|
+
)
|
|
934
|
+
###################################
|
|
935
|
+
|
|
936
|
+
RecToolsCP = _instantiate_iterative_recon_class(
|
|
937
|
+
data,
|
|
938
|
+
angles,
|
|
939
|
+
center,
|
|
940
|
+
detector_pad,
|
|
941
|
+
recon_size,
|
|
942
|
+
subsets_number,
|
|
943
|
+
gpu_id,
|
|
944
|
+
)
|
|
945
|
+
|
|
946
|
+
_data_ = {
|
|
947
|
+
"projection_data": data,
|
|
948
|
+
"data_axes_labels_order": input_data_axis_labels,
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
_algorithm_ = {
|
|
952
|
+
"iterations": iterations,
|
|
953
|
+
"nonnegativity": nonnegativity,
|
|
954
|
+
"recon_mask_radius": recon_mask_radius,
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
_regularisation_ = {
|
|
958
|
+
"method": regularisation_type, # Selected regularisation method
|
|
959
|
+
"regul_param": regularisation_parameter, # Regularisation parameter
|
|
960
|
+
"iterations": regularisation_iterations, # The number of regularisation iterations
|
|
961
|
+
"half_precision": regularisation_half_precision, # enabling half-precision calculation
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
reconstruction = RecToolsCP.OSEM(_data_, _algorithm_, _regularisation_)
|
|
965
|
+
cp._default_memory_pool.free_all_blocks()
|
|
966
|
+
return cp.require(cp.swapaxes(reconstruction, 0, 1), requirements="C")
|
|
967
|
+
|
|
968
|
+
|
|
838
969
|
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ##
|
|
839
970
|
def _instantiate_direct_recon_class(
|
|
840
971
|
data: cp.ndarray | Tuple[int, int, int],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: httomolibgpu
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.7
|
|
4
4
|
Summary: Commonly used tomography data processing methods at DLS.
|
|
5
5
|
Author-email: Daniil Kazantsev <daniil.kazantsev@diamond.ac.uk>, Yousef Moazzam <yousef.moazzam@diamond.ac.uk>, Naman Gera <naman.gera@diamond.ac.uk>
|
|
6
6
|
License: BSD-3-Clause
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|