httomolibgpu 2.5.1__tar.gz → 2.6__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-2.5.1/httomolibgpu.egg-info → httomolibgpu-2.6}/PKG-INFO +1 -1
- httomolibgpu-2.6/httomolibgpu/cuda_kernels/remove_nan_inf.cu +19 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/misc/corr.py +6 -4
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/misc/denoise.py +7 -3
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/misc/morph.py +6 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/misc/rescale.py +5 -4
- httomolibgpu-2.6/httomolibgpu/misc/supp_func.py +191 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/prep/alignment.py +6 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/prep/normalize.py +8 -2
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/prep/phase.py +6 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/prep/stripe.py +16 -2
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/recon/algorithm.py +21 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/recon/rotation.py +27 -2
- {httomolibgpu-2.5.1 → httomolibgpu-2.6/httomolibgpu.egg-info}/PKG-INFO +1 -1
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu.egg-info/SOURCES.txt +2 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/LICENSE +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/MANIFEST.in +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/README.rst +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/__init__.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/__init__.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/calc_metrics.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/center_360_shifts.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/generate_mask.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/median_kernel.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/paganin_filter_gen.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cuda_kernels/raven_filter.cu +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/cupywrapper.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/misc/__init__.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/prep/__init__.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu/recon/__init__.py +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu.egg-info/dependency_links.txt +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu.egg-info/requires.txt +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/httomolibgpu.egg-info/top_level.txt +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/pyproject.toml +0 -0
- {httomolibgpu-2.5.1 → httomolibgpu-2.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: httomolibgpu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6
|
|
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
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
template <typename Type>
|
|
2
|
+
__global__ void remove_nan_inf(Type *data, int Z, int M, int N, int *result) {
|
|
3
|
+
const long i = blockDim.x * blockIdx.x + threadIdx.x;
|
|
4
|
+
const long j = blockDim.y * blockIdx.y + threadIdx.y;
|
|
5
|
+
const long k = blockDim.z * blockIdx.z + threadIdx.z;
|
|
6
|
+
|
|
7
|
+
if (i >= N || j >= M || k >= Z)
|
|
8
|
+
return;
|
|
9
|
+
|
|
10
|
+
long long index = static_cast<long long>(i) + N * static_cast<long long>(j) + N * M * static_cast<long long>(k);
|
|
11
|
+
|
|
12
|
+
float val = float(data[index]); /*needs a cast to float for isnan isinf functions to work*/
|
|
13
|
+
Type zero = 0;
|
|
14
|
+
if (isnan(val) || isinf(val)) {
|
|
15
|
+
result[0] = 1;
|
|
16
|
+
data[index] = zero;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
@@ -18,9 +18,7 @@
|
|
|
18
18
|
# Created By : Tomography Team at DLS <scientificsoftware@diamond.ac.uk>
|
|
19
19
|
# Created Date: 21/October/2022
|
|
20
20
|
# ---------------------------------------------------------------------------
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
"""
|
|
21
|
+
"""Module for data correction. For more detailed information see :ref:`data_correction_module`."""
|
|
24
22
|
|
|
25
23
|
import numpy as np
|
|
26
24
|
from typing import Union
|
|
@@ -38,6 +36,7 @@ if cupy_run:
|
|
|
38
36
|
else:
|
|
39
37
|
load_cuda_module = Mock()
|
|
40
38
|
|
|
39
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
41
40
|
|
|
42
41
|
__all__ = [
|
|
43
42
|
"median_filter",
|
|
@@ -74,7 +73,6 @@ def median_filter(
|
|
|
74
73
|
If the input array is not three dimensional.
|
|
75
74
|
"""
|
|
76
75
|
input_type = data.dtype
|
|
77
|
-
|
|
78
76
|
if input_type not in ["float32", "uint16"]:
|
|
79
77
|
raise ValueError("The input data should be either float32 or uint16 data type")
|
|
80
78
|
|
|
@@ -84,6 +82,10 @@ def median_filter(
|
|
|
84
82
|
else:
|
|
85
83
|
raise ValueError("The input array must be a 3D array")
|
|
86
84
|
|
|
85
|
+
data = data_checker(
|
|
86
|
+
data, verbosity=True, method_name="median_filter_or_remove_outlier"
|
|
87
|
+
)
|
|
88
|
+
|
|
87
89
|
if kernel_size not in [3, 5, 7, 9, 11, 13]:
|
|
88
90
|
raise ValueError("Please select a correct kernel size: 3, 5, 7, 9, 11, 13")
|
|
89
91
|
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
# Created By : Tomography Team at DLS <scientificsoftware@diamond.ac.uk>
|
|
19
19
|
# Created Date: 18/December/2024
|
|
20
20
|
# ---------------------------------------------------------------------------
|
|
21
|
-
"""
|
|
22
|
-
"""
|
|
21
|
+
"""Module for data denoising. For more detailed information see :ref:`data_denoising_module`."""
|
|
23
22
|
|
|
24
23
|
import numpy as np
|
|
25
24
|
from typing import Union, Optional
|
|
@@ -29,9 +28,10 @@ from httomolibgpu import cupywrapper
|
|
|
29
28
|
cp = cupywrapper.cp
|
|
30
29
|
cupy_run = cupywrapper.cupy_run
|
|
31
30
|
|
|
32
|
-
from numpy import float32
|
|
33
31
|
from unittest.mock import Mock
|
|
34
32
|
|
|
33
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
34
|
+
|
|
35
35
|
if cupy_run:
|
|
36
36
|
from ccpi.filters.regularisersCuPy import ROF_TV, PD_TV
|
|
37
37
|
else:
|
|
@@ -82,6 +82,8 @@ def total_variation_ROF(
|
|
|
82
82
|
If the input array is not float32 data type.
|
|
83
83
|
"""
|
|
84
84
|
|
|
85
|
+
data = data_checker(data, verbosity=True, method_name="total_variation_ROF")
|
|
86
|
+
|
|
85
87
|
return ROF_TV(
|
|
86
88
|
data, regularisation_parameter, iterations, time_marching_parameter, gpu_id
|
|
87
89
|
)
|
|
@@ -127,6 +129,8 @@ def total_variation_PD(
|
|
|
127
129
|
If the input array is not float32 data type.
|
|
128
130
|
"""
|
|
129
131
|
|
|
132
|
+
data_checker(data, verbosity=True, method_name="total_variation_PD")
|
|
133
|
+
|
|
130
134
|
methodTV = 0
|
|
131
135
|
if not isotropic:
|
|
132
136
|
methodTV = 1
|
|
@@ -35,6 +35,8 @@ else:
|
|
|
35
35
|
|
|
36
36
|
from typing import Literal
|
|
37
37
|
|
|
38
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
39
|
+
|
|
38
40
|
__all__ = [
|
|
39
41
|
"sino_360_to_180",
|
|
40
42
|
"data_resampler",
|
|
@@ -66,6 +68,8 @@ def sino_360_to_180(
|
|
|
66
68
|
if data.ndim != 3:
|
|
67
69
|
raise ValueError("only 3D data is supported")
|
|
68
70
|
|
|
71
|
+
data = data_checker(data, verbosity=True, method_name="sino_360_to_180")
|
|
72
|
+
|
|
69
73
|
dx, dy, dz = data.shape
|
|
70
74
|
|
|
71
75
|
overlap = int(np.round(overlap))
|
|
@@ -136,6 +140,8 @@ def data_resampler(
|
|
|
136
140
|
data = cp.expand_dims(data, 1)
|
|
137
141
|
axis = 1
|
|
138
142
|
|
|
143
|
+
data = data_checker(data, verbosity=True, method_name="data_resampler")
|
|
144
|
+
|
|
139
145
|
N, M, Z = cp.shape(data)
|
|
140
146
|
|
|
141
147
|
if axis == 0:
|
|
@@ -18,9 +18,7 @@
|
|
|
18
18
|
# Created By : Tomography Team at DLS <scientificsoftware@diamond.ac.uk>
|
|
19
19
|
# Created Date: 1 March 2024
|
|
20
20
|
# ---------------------------------------------------------------------------
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
"""
|
|
21
|
+
"""Module for data rescaling. For more detailed information see :ref:`data_rescale_module`."""
|
|
24
22
|
|
|
25
23
|
import numpy as np
|
|
26
24
|
from httomolibgpu import cupywrapper
|
|
@@ -30,6 +28,8 @@ cupy_run = cupywrapper.cupy_run
|
|
|
30
28
|
|
|
31
29
|
from typing import Literal, Optional, Tuple, Union
|
|
32
30
|
|
|
31
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
32
|
+
|
|
33
33
|
__all__ = [
|
|
34
34
|
"rescale_to_int",
|
|
35
35
|
]
|
|
@@ -80,6 +80,8 @@ def rescale_to_int(
|
|
|
80
80
|
else:
|
|
81
81
|
output_dtype = np.uint32
|
|
82
82
|
|
|
83
|
+
data = data_checker(data, verbosity=True, method_name="rescale_to_int")
|
|
84
|
+
|
|
83
85
|
if cupy_run:
|
|
84
86
|
xp = cp.get_array_module(data)
|
|
85
87
|
else:
|
|
@@ -109,7 +111,6 @@ def rescale_to_int(
|
|
|
109
111
|
if xp.__name__ == "numpy":
|
|
110
112
|
if input_max == pow(2, 32):
|
|
111
113
|
input_max -= 1
|
|
112
|
-
data[np.logical_not(np.isfinite(data))] = 0
|
|
113
114
|
res = np.copy(data.astype(float))
|
|
114
115
|
res[data.astype(float) < input_min] = int(input_min)
|
|
115
116
|
res[data.astype(float) > input_max] = int(input_max)
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ---------------------------------------------------------------------------
|
|
4
|
+
# Copyright 2022 Diamond Light Source Ltd.
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Created By : Tomography Team at DLS <scientificsoftware@diamond.ac.uk>
|
|
19
|
+
# Created Date: 02/June/2025
|
|
20
|
+
# ---------------------------------------------------------------------------
|
|
21
|
+
"""This is a collection of supplementary functions (utils) to perform various data checks"""
|
|
22
|
+
|
|
23
|
+
from httomolibgpu import cupywrapper
|
|
24
|
+
from typing import Optional
|
|
25
|
+
|
|
26
|
+
cp = cupywrapper.cp
|
|
27
|
+
cupy_run = cupywrapper.cupy_run
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
|
|
31
|
+
from unittest.mock import Mock
|
|
32
|
+
|
|
33
|
+
if cupy_run:
|
|
34
|
+
from httomolibgpu.cuda_kernels import load_cuda_module
|
|
35
|
+
else:
|
|
36
|
+
load_cuda_module = Mock()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _naninfs_check(
|
|
40
|
+
data: cp.ndarray,
|
|
41
|
+
verbosity: bool = True,
|
|
42
|
+
method_name: Optional[str] = None,
|
|
43
|
+
) -> cp.ndarray:
|
|
44
|
+
"""
|
|
45
|
+
This function finds NaN's, +-Inf's in the input data and then prints the warnings and correct the data if correction is enabled.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
data : cp.ndarray
|
|
50
|
+
Input CuPy or Numpy array either float32 or uint16 data type.
|
|
51
|
+
verbosity : bool
|
|
52
|
+
If enabled, then the printing of the warning happens when data contains infs or nans
|
|
53
|
+
method_name : str, optional.
|
|
54
|
+
Method's name for which input data is tested.
|
|
55
|
+
|
|
56
|
+
Returns
|
|
57
|
+
-------
|
|
58
|
+
ndarray
|
|
59
|
+
Uncorrected or corrected (nans and infs converted to zeros) input array.
|
|
60
|
+
"""
|
|
61
|
+
present_nans_infs_b = False
|
|
62
|
+
|
|
63
|
+
if cupy_run:
|
|
64
|
+
xp = cp.get_array_module(data)
|
|
65
|
+
else:
|
|
66
|
+
import numpy as xp
|
|
67
|
+
|
|
68
|
+
if xp.__name__ == "cupy":
|
|
69
|
+
input_type = data.dtype
|
|
70
|
+
if len(data.shape) == 2:
|
|
71
|
+
dy, dx = data.shape
|
|
72
|
+
dz = 1
|
|
73
|
+
else:
|
|
74
|
+
dz, dy, dx = data.shape
|
|
75
|
+
|
|
76
|
+
present_nans_infs = cp.zeros(shape=(1)).astype(cp.uint8)
|
|
77
|
+
|
|
78
|
+
block_x = 128
|
|
79
|
+
# setting grid/block parameters
|
|
80
|
+
block_dims = (block_x, 1, 1)
|
|
81
|
+
grid_x = (dx + block_x - 1) // block_x
|
|
82
|
+
grid_y = dy
|
|
83
|
+
grid_z = dz
|
|
84
|
+
grid_dims = (grid_x, grid_y, grid_z)
|
|
85
|
+
params = (data, dz, dy, dx, present_nans_infs)
|
|
86
|
+
|
|
87
|
+
kernel_args = "remove_nan_inf<{0}>".format(
|
|
88
|
+
"float" if input_type == "float32" else "unsigned short"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
module = load_cuda_module("remove_nan_inf", name_expressions=[kernel_args])
|
|
92
|
+
remove_nan_inf_kernel = module.get_function(kernel_args)
|
|
93
|
+
remove_nan_inf_kernel(grid_dims, block_dims, params)
|
|
94
|
+
|
|
95
|
+
if present_nans_infs[0].get() == 1:
|
|
96
|
+
present_nans_infs_b = True
|
|
97
|
+
else:
|
|
98
|
+
if not np.all(np.isfinite(data)):
|
|
99
|
+
present_nans_infs_b = True
|
|
100
|
+
np.nan_to_num(data, copy=False, nan=0.0, posinf=0.0, neginf=0.0)
|
|
101
|
+
|
|
102
|
+
if present_nans_infs_b:
|
|
103
|
+
if verbosity:
|
|
104
|
+
print(
|
|
105
|
+
f"Warning!!! Input data to method: {method_name} contains Inf's or/and NaN's. This will be corrected but it is recommended to check the validity of input to the method."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
return data
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _zeros_check(
|
|
112
|
+
data: cp.ndarray,
|
|
113
|
+
verbosity: bool = True,
|
|
114
|
+
percentage_threshold: float = 50,
|
|
115
|
+
method_name: Optional[str] = None,
|
|
116
|
+
) -> bool:
|
|
117
|
+
"""
|
|
118
|
+
This function finds all zeros present in the data. If the amount of zeros is larger than percentage_threshold it prints the warning.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
data : cp.ndarray
|
|
123
|
+
Input CuPy or Numpy array.
|
|
124
|
+
verbosity : bool
|
|
125
|
+
If enabled, then the printing of the warning happens when data contains infs or nans.
|
|
126
|
+
percentage_threshold: float:
|
|
127
|
+
If the number of zeros in input data is more than the percentage of all data points, then print the data warning
|
|
128
|
+
method_name : str, optional.
|
|
129
|
+
Method's name for which input data is tested.
|
|
130
|
+
|
|
131
|
+
Returns
|
|
132
|
+
-------
|
|
133
|
+
bool
|
|
134
|
+
True if the data contains too many zeros
|
|
135
|
+
"""
|
|
136
|
+
if cupy_run:
|
|
137
|
+
xp = cp.get_array_module(data)
|
|
138
|
+
else:
|
|
139
|
+
import numpy as xp
|
|
140
|
+
|
|
141
|
+
nonzero_elements_total = 1
|
|
142
|
+
for tot_elements_mult in data.shape:
|
|
143
|
+
nonzero_elements_total *= tot_elements_mult
|
|
144
|
+
|
|
145
|
+
warning_zeros = False
|
|
146
|
+
zero_elements_total = nonzero_elements_total - int(xp.count_nonzero(data))
|
|
147
|
+
|
|
148
|
+
if (zero_elements_total / nonzero_elements_total) * 100 >= percentage_threshold:
|
|
149
|
+
warning_zeros = True
|
|
150
|
+
if verbosity:
|
|
151
|
+
print(
|
|
152
|
+
f"Warning!!! Input data to method: {method_name} contains more than {percentage_threshold} percent of zeros."
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
return warning_zeros
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def data_checker(
|
|
159
|
+
data: cp.ndarray,
|
|
160
|
+
verbosity: bool = True,
|
|
161
|
+
method_name: Optional[str] = None,
|
|
162
|
+
) -> bool:
|
|
163
|
+
"""
|
|
164
|
+
Function that performs the variety of checks on input data, in some cases also correct the data and prints warnings.
|
|
165
|
+
Currently it checks for: the presence of infs and nans in data; the number of zero elements.
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
data : xp.ndarray
|
|
170
|
+
Input CuPy or Numpy array either float32 or uint16 data type.
|
|
171
|
+
verbosity : bool
|
|
172
|
+
If enabled, then the printing of the warning happens when data contains infs or nans.
|
|
173
|
+
method_name : str, optional.
|
|
174
|
+
Method's name for which input data is tested.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
cp.ndarray
|
|
179
|
+
Returns corrected or not data array.
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
data = _naninfs_check(data, verbosity=verbosity, method_name=method_name)
|
|
183
|
+
|
|
184
|
+
_zeros_check(
|
|
185
|
+
data,
|
|
186
|
+
verbosity=verbosity,
|
|
187
|
+
percentage_threshold=50,
|
|
188
|
+
method_name=method_name,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
return data
|
|
@@ -35,6 +35,8 @@ else:
|
|
|
35
35
|
|
|
36
36
|
from typing import Dict, List, Tuple
|
|
37
37
|
|
|
38
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
39
|
+
|
|
38
40
|
__all__ = [
|
|
39
41
|
"distortion_correction_proj_discorpy",
|
|
40
42
|
]
|
|
@@ -86,6 +88,10 @@ def distortion_correction_proj_discorpy(
|
|
|
86
88
|
if len(data.shape) == 2:
|
|
87
89
|
data = cp.expand_dims(data, axis=0)
|
|
88
90
|
|
|
91
|
+
data = data_checker(
|
|
92
|
+
data, verbosity=True, method_name="distortion_correction_proj_discorpy"
|
|
93
|
+
)
|
|
94
|
+
|
|
89
95
|
# Get info from metadata txt file
|
|
90
96
|
xcenter, ycenter, list_fact = _load_metadata_txt(metadata_path)
|
|
91
97
|
|
|
@@ -36,6 +36,8 @@ else:
|
|
|
36
36
|
from numpy import float32
|
|
37
37
|
from typing import Tuple
|
|
38
38
|
|
|
39
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
40
|
+
|
|
39
41
|
__all__ = ["normalize"]
|
|
40
42
|
|
|
41
43
|
|
|
@@ -80,7 +82,7 @@ def normalize(
|
|
|
80
82
|
cp.ndarray
|
|
81
83
|
Normalised 3D tomographic data as a CuPy array.
|
|
82
84
|
"""
|
|
83
|
-
|
|
85
|
+
_check_valid_input_normalise(data, flats, darks)
|
|
84
86
|
|
|
85
87
|
dark0 = cp.empty(darks.shape[1:], dtype=float32)
|
|
86
88
|
flat0 = cp.empty(flats.shape[1:], dtype=float32)
|
|
@@ -128,7 +130,7 @@ def normalize(
|
|
|
128
130
|
return out
|
|
129
131
|
|
|
130
132
|
|
|
131
|
-
def
|
|
133
|
+
def _check_valid_input_normalise(data, flats, darks) -> None:
|
|
132
134
|
"""Helper function to check the validity of inputs to normalisation functions"""
|
|
133
135
|
if data.ndim != 3:
|
|
134
136
|
raise ValueError("Input data must be a 3D stack of projections")
|
|
@@ -143,3 +145,7 @@ def _check_valid_input(data, flats, darks) -> None:
|
|
|
143
145
|
flats = flats[cp.newaxis, :, :]
|
|
144
146
|
if darks.ndim == 2:
|
|
145
147
|
darks = darks[cp.newaxis, :, :]
|
|
148
|
+
|
|
149
|
+
data_checker(data, verbosity=True, method_name="normalize_data")
|
|
150
|
+
data_checker(flats, verbosity=True, method_name="normalize_flats")
|
|
151
|
+
data_checker(darks, verbosity=True, method_name="normalize_darks")
|
|
@@ -41,6 +41,8 @@ from numpy import float32
|
|
|
41
41
|
from typing import Tuple
|
|
42
42
|
import math
|
|
43
43
|
|
|
44
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
45
|
+
|
|
44
46
|
__all__ = [
|
|
45
47
|
"paganin_filter_savu",
|
|
46
48
|
"paganin_filter_tomopy",
|
|
@@ -105,6 +107,8 @@ def paganin_filter_savu(
|
|
|
105
107
|
" please provide a stack of 2D projections."
|
|
106
108
|
)
|
|
107
109
|
|
|
110
|
+
data = data_checker(data, verbosity=True, method_name="paganin_filter_savu")
|
|
111
|
+
|
|
108
112
|
# Setup various values for the filter
|
|
109
113
|
_, height, width = data.shape
|
|
110
114
|
micron = 1e-6
|
|
@@ -297,6 +301,8 @@ def paganin_filter_tomopy(
|
|
|
297
301
|
" please provide a stack of 2D projections."
|
|
298
302
|
)
|
|
299
303
|
|
|
304
|
+
tomo = data_checker(tomo, verbosity=True, method_name="paganin_filter_tomopy")
|
|
305
|
+
|
|
300
306
|
dz_orig, dy_orig, dx_orig = tomo.shape
|
|
301
307
|
|
|
302
308
|
# Perform padding to the power of 2 as FFT is O(n*log(n)) complexity
|
|
@@ -43,6 +43,8 @@ else:
|
|
|
43
43
|
|
|
44
44
|
from typing import Union
|
|
45
45
|
|
|
46
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
47
|
+
|
|
46
48
|
__all__ = [
|
|
47
49
|
"remove_stripe_based_sorting",
|
|
48
50
|
"remove_stripe_ti",
|
|
@@ -80,6 +82,9 @@ def remove_stripe_based_sorting(
|
|
|
80
82
|
Corrected 3D tomographic data as a CuPy or NumPy array.
|
|
81
83
|
|
|
82
84
|
"""
|
|
85
|
+
|
|
86
|
+
data = data_checker(data, verbosity=True, method_name="remove_stripe_based_sorting")
|
|
87
|
+
|
|
83
88
|
if size is None:
|
|
84
89
|
if data.shape[2] > 2000:
|
|
85
90
|
size = 21
|
|
@@ -134,7 +139,13 @@ def remove_stripe_ti(
|
|
|
134
139
|
ndarray
|
|
135
140
|
3D array of de-striped projections.
|
|
136
141
|
"""
|
|
137
|
-
|
|
142
|
+
data = data_checker(data, verbosity=True, method_name="remove_stripe_ti")
|
|
143
|
+
|
|
144
|
+
_, _, dx_orig = data.shape
|
|
145
|
+
if (dx_orig % 2) != 0:
|
|
146
|
+
# the horizontal detector size is odd, data needs to be padded/cropped, for now raising the error
|
|
147
|
+
raise ValueError("The horizontal detector size must be even")
|
|
148
|
+
|
|
138
149
|
gamma = beta * ((1 - beta) / (1 + beta)) ** cp.abs(
|
|
139
150
|
cp.fft.fftfreq(data.shape[-1]) * data.shape[-1]
|
|
140
151
|
)
|
|
@@ -201,6 +212,8 @@ def remove_all_stripe(
|
|
|
201
212
|
Corrected 3D tomographic data as a CuPy or NumPy array.
|
|
202
213
|
|
|
203
214
|
"""
|
|
215
|
+
data = data_checker(data, verbosity=True, method_name="remove_all_stripe")
|
|
216
|
+
|
|
204
217
|
matindex = _create_matindex(data.shape[2], data.shape[0])
|
|
205
218
|
for m in range(data.shape[1]):
|
|
206
219
|
sino = data[:, m, :]
|
|
@@ -372,10 +385,11 @@ def raven_filter(
|
|
|
372
385
|
ValueError
|
|
373
386
|
If the input array is not three dimensional.
|
|
374
387
|
"""
|
|
375
|
-
|
|
376
388
|
if data.dtype != cp.float32:
|
|
377
389
|
raise ValueError("The input data should be float32 data type")
|
|
378
390
|
|
|
391
|
+
data = data_checker(data, verbosity=True, method_name="raven_filter")
|
|
392
|
+
|
|
379
393
|
# Padding of the sinogram
|
|
380
394
|
data = cp.pad(data, ((pad_y, pad_y), (0, 0), (pad_x, pad_x)), mode=pad_method)
|
|
381
395
|
|
|
@@ -40,6 +40,8 @@ else:
|
|
|
40
40
|
from numpy import float32, complex64
|
|
41
41
|
from typing import Optional, Type
|
|
42
42
|
|
|
43
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
44
|
+
|
|
43
45
|
|
|
44
46
|
__all__ = [
|
|
45
47
|
"FBP2d_astra",
|
|
@@ -103,6 +105,8 @@ def FBP2d_astra(
|
|
|
103
105
|
np.ndarray
|
|
104
106
|
The FBP reconstructed volume as a numpy array.
|
|
105
107
|
"""
|
|
108
|
+
data = data_checker(data, verbosity=True, method_name="FBP2d_astra")
|
|
109
|
+
|
|
106
110
|
data_shape = np.shape(data)
|
|
107
111
|
if recon_size is None:
|
|
108
112
|
recon_size = data_shape[2]
|
|
@@ -175,6 +179,8 @@ def FBP3d_tomobar(
|
|
|
175
179
|
cp.ndarray
|
|
176
180
|
FBP reconstructed volume as a CuPy array.
|
|
177
181
|
"""
|
|
182
|
+
data = data_checker(data, verbosity=True, method_name="FBP3d_tomobar")
|
|
183
|
+
|
|
178
184
|
RecToolsCP = _instantiate_direct_recon_class(
|
|
179
185
|
data, angles, center, recon_size, gpu_id
|
|
180
186
|
)
|
|
@@ -194,6 +200,8 @@ def LPRec3d_tomobar(
|
|
|
194
200
|
data: cp.ndarray,
|
|
195
201
|
angles: np.ndarray,
|
|
196
202
|
center: Optional[float] = None,
|
|
203
|
+
filter_type: str = "shepp",
|
|
204
|
+
filter_freq_cutoff: float = 1.0,
|
|
197
205
|
recon_size: Optional[int] = None,
|
|
198
206
|
recon_mask_radius: Optional[float] = 0.95,
|
|
199
207
|
neglog: bool = False,
|
|
@@ -211,6 +219,10 @@ def LPRec3d_tomobar(
|
|
|
211
219
|
An array of angles given in radians.
|
|
212
220
|
center : float, optional
|
|
213
221
|
The center of rotation (CoR).
|
|
222
|
+
filter_type : str
|
|
223
|
+
Filter type, the accepted strings are: none, ramp, shepp, cosine, cosine2, hamming, hann, parzen.
|
|
224
|
+
filter_freq_cutoff : float
|
|
225
|
+
Cutoff frequency parameter for a filter. The higher values increase the resolution but also amplify the noise.
|
|
214
226
|
recon_size : int, optional
|
|
215
227
|
The [recon_size, recon_size] shape of the reconstructed slice in pixels.
|
|
216
228
|
By default (None), the reconstructed size will be the dimension of the horizontal detector.
|
|
@@ -227,12 +239,17 @@ def LPRec3d_tomobar(
|
|
|
227
239
|
cp.ndarray
|
|
228
240
|
The Log-polar Fourier reconstructed volume as a CuPy array.
|
|
229
241
|
"""
|
|
242
|
+
|
|
243
|
+
data = data_checker(data, verbosity=True, method_name="LPRec3d_tomobar")
|
|
244
|
+
|
|
230
245
|
RecToolsCP = _instantiate_direct_recon_class(data, angles, center, recon_size, 0)
|
|
231
246
|
|
|
232
247
|
reconstruction = RecToolsCP.FOURIER_INV(
|
|
233
248
|
_take_neg_log(data) if neglog else data,
|
|
234
249
|
recon_mask_radius=recon_mask_radius,
|
|
235
250
|
data_axes_labels_order=input_data_axis_labels,
|
|
251
|
+
filter_type=filter_type,
|
|
252
|
+
cutoff_freq=filter_freq_cutoff,
|
|
236
253
|
)
|
|
237
254
|
cp._default_memory_pool.free_all_blocks()
|
|
238
255
|
return cp.require(cp.swapaxes(reconstruction, 0, 1), requirements="C")
|
|
@@ -281,6 +298,8 @@ def SIRT3d_tomobar(
|
|
|
281
298
|
cp.ndarray
|
|
282
299
|
The SIRT reconstructed volume as a CuPy array.
|
|
283
300
|
"""
|
|
301
|
+
data = data_checker(data, verbosity=True, method_name="SIRT3d_tomobar")
|
|
302
|
+
|
|
284
303
|
RecToolsCP = _instantiate_iterative_recon_class(
|
|
285
304
|
data,
|
|
286
305
|
angles,
|
|
@@ -346,6 +365,8 @@ def CGLS3d_tomobar(
|
|
|
346
365
|
cp.ndarray
|
|
347
366
|
The CGLS reconstructed volume as a CuPy array.
|
|
348
367
|
"""
|
|
368
|
+
data = data_checker(data, verbosity=True, method_name="CGLS3d_tomobar")
|
|
369
|
+
|
|
349
370
|
RecToolsCP = _instantiate_iterative_recon_class(
|
|
350
371
|
data, angles, center, recon_size, gpu_id, datafidelity="LS"
|
|
351
372
|
)
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"""Modules for finding the axis of rotation for 180 and 360 degrees scans"""
|
|
22
22
|
|
|
23
23
|
import numpy as np
|
|
24
|
+
from numpy.polynomial import Polynomial
|
|
24
25
|
from httomolibgpu import cupywrapper
|
|
25
26
|
|
|
26
27
|
cp = cupywrapper.cp
|
|
@@ -48,6 +49,8 @@ else:
|
|
|
48
49
|
import math
|
|
49
50
|
from typing import List, Literal, Optional, Tuple, Union
|
|
50
51
|
|
|
52
|
+
from httomolibgpu.misc.supp_func import data_checker
|
|
53
|
+
|
|
51
54
|
__all__ = [
|
|
52
55
|
"find_center_vo",
|
|
53
56
|
"find_center_360",
|
|
@@ -107,6 +110,8 @@ def find_center_vo(
|
|
|
107
110
|
data = cp.expand_dims(data, 1)
|
|
108
111
|
ind = 0
|
|
109
112
|
|
|
113
|
+
data = data_checker(data, verbosity=True, method_name="find_center_vo")
|
|
114
|
+
|
|
110
115
|
angles_tot, detY_size, detX_size = data.shape
|
|
111
116
|
|
|
112
117
|
if ind is None:
|
|
@@ -455,6 +460,8 @@ def find_center_360(
|
|
|
455
460
|
if data.ndim != 3:
|
|
456
461
|
raise ValueError("A 3D array must be provided")
|
|
457
462
|
|
|
463
|
+
data = data_checker(data, verbosity=True, method_name="find_center_360")
|
|
464
|
+
|
|
458
465
|
# this method works with a 360-degree sinogram.
|
|
459
466
|
if ind is None:
|
|
460
467
|
_sino = data[:, 0, :]
|
|
@@ -712,9 +719,23 @@ def _calculate_curvature(list_metric):
|
|
|
712
719
|
|
|
713
720
|
# work mostly on CPU here - we have very small arrays here
|
|
714
721
|
list1 = cp.asnumpy(list_metric[min_pos - radi : min_pos + radi + 1])
|
|
715
|
-
|
|
722
|
+
if not all(map(np.isfinite, list1)):
|
|
723
|
+
raise ValueError(
|
|
724
|
+
"The list of metrics (list1) contains nan's or infs. Check your input data"
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
series1 = Polynomial.fit(np.arange(0, 2 * radi + 1), list1, deg=2)
|
|
728
|
+
afact1 = series1.convert().coef[-1]
|
|
729
|
+
|
|
716
730
|
list2 = cp.asnumpy(list_metric[min_pos - 1 : min_pos + 2])
|
|
717
|
-
|
|
731
|
+
if not all(map(np.isfinite, list2)):
|
|
732
|
+
raise ValueError(
|
|
733
|
+
"The list of metrics (list2) contains nan's or infs. Check your input data"
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
series2 = Polynomial.fit(np.arange(min_pos - 1, min_pos + 2), list2, deg=2)
|
|
737
|
+
afact2 = series2.convert().coef[-1]
|
|
738
|
+
bfact2 = series2.convert().coef[-1 - 1]
|
|
718
739
|
|
|
719
740
|
curvature = np.abs(afact1)
|
|
720
741
|
if afact2 != 0.0:
|
|
@@ -759,6 +780,10 @@ def find_center_pc(
|
|
|
759
780
|
np.float32
|
|
760
781
|
Rotation axis location.
|
|
761
782
|
"""
|
|
783
|
+
|
|
784
|
+
proj1 = data_checker(proj1, verbosity=True, method_name="find_center_pc")
|
|
785
|
+
proj2 = data_checker(proj2, verbosity=True, method_name="find_center_pc")
|
|
786
|
+
|
|
762
787
|
imgshift = 0.0 if rotc_guess is None else rotc_guess - (proj1.shape[1] - 1.0) / 2.0
|
|
763
788
|
|
|
764
789
|
proj1 = shift(proj1, [0, -imgshift], mode="constant", cval=0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: httomolibgpu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6
|
|
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
|
|
@@ -16,11 +16,13 @@ httomolibgpu/cuda_kernels/generate_mask.cu
|
|
|
16
16
|
httomolibgpu/cuda_kernels/median_kernel.cu
|
|
17
17
|
httomolibgpu/cuda_kernels/paganin_filter_gen.cu
|
|
18
18
|
httomolibgpu/cuda_kernels/raven_filter.cu
|
|
19
|
+
httomolibgpu/cuda_kernels/remove_nan_inf.cu
|
|
19
20
|
httomolibgpu/misc/__init__.py
|
|
20
21
|
httomolibgpu/misc/corr.py
|
|
21
22
|
httomolibgpu/misc/denoise.py
|
|
22
23
|
httomolibgpu/misc/morph.py
|
|
23
24
|
httomolibgpu/misc/rescale.py
|
|
25
|
+
httomolibgpu/misc/supp_func.py
|
|
24
26
|
httomolibgpu/prep/__init__.py
|
|
25
27
|
httomolibgpu/prep/alignment.py
|
|
26
28
|
httomolibgpu/prep/normalize.py
|
|
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
|