httomolibgpu 5.1__tar.gz → 5.3__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.
Files changed (38) hide show
  1. {httomolibgpu-5.1/httomolibgpu.egg-info → httomolibgpu-5.3}/PKG-INFO +2 -1
  2. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/__init__.py +1 -0
  3. httomolibgpu-5.3/httomolibgpu/cuda_kernels/remove_stripe_fw.cu +155 -0
  4. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cupywrapper.py +2 -0
  5. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/prep/phase.py +70 -11
  6. httomolibgpu-5.3/httomolibgpu/prep/stripe.py +1038 -0
  7. {httomolibgpu-5.1 → httomolibgpu-5.3/httomolibgpu.egg-info}/PKG-INFO +2 -1
  8. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu.egg-info/SOURCES.txt +1 -0
  9. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu.egg-info/requires.txt +1 -0
  10. {httomolibgpu-5.1 → httomolibgpu-5.3}/pyproject.toml +1 -0
  11. httomolibgpu-5.1/httomolibgpu/prep/stripe.py +0 -437
  12. {httomolibgpu-5.1 → httomolibgpu-5.3}/LICENSE +0 -0
  13. {httomolibgpu-5.1 → httomolibgpu-5.3}/MANIFEST.in +0 -0
  14. {httomolibgpu-5.1 → httomolibgpu-5.3}/README.rst +0 -0
  15. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/__init__.py +0 -0
  16. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/calc_metrics.cu +0 -0
  17. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/center_360_shifts.cu +0 -0
  18. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/generate_mask.cu +0 -0
  19. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/median_kernel.cu +0 -0
  20. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/raven_filter.cu +0 -0
  21. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/cuda_kernels/remove_nan_inf.cu +0 -0
  22. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/memory_estimator_helpers.py +0 -0
  23. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/__init__.py +0 -0
  24. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/corr.py +0 -0
  25. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/denoise.py +0 -0
  26. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/morph.py +0 -0
  27. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/rescale.py +0 -0
  28. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/misc/utils.py +0 -0
  29. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/prep/__init__.py +0 -0
  30. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/prep/alignment.py +0 -0
  31. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/prep/normalize.py +0 -0
  32. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/recon/__init__.py +0 -0
  33. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/recon/_phase_cross_correlation.py +0 -0
  34. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/recon/algorithm.py +0 -0
  35. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu/recon/rotation.py +0 -0
  36. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu.egg-info/dependency_links.txt +0 -0
  37. {httomolibgpu-5.1 → httomolibgpu-5.3}/httomolibgpu.egg-info/top_level.txt +0 -0
  38. {httomolibgpu-5.1 → httomolibgpu-5.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: httomolibgpu
3
- Version: 5.1
3
+ Version: 5.3
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
@@ -19,6 +19,7 @@ Requires-Dist: scipy
19
19
  Requires-Dist: pillow
20
20
  Requires-Dist: scikit-image
21
21
  Requires-Dist: tomobar
22
+ Requires-Dist: PyWavelets
22
23
  Provides-Extra: dev
23
24
  Requires-Dist: pytest; extra == "dev"
24
25
  Requires-Dist: pytest-cov; extra == "dev"
@@ -9,6 +9,7 @@ from httomolibgpu.prep.normalize import dark_flat_field_correction, minus_log
9
9
  from httomolibgpu.prep.phase import paganin_filter, paganin_filter_savu_legacy
10
10
  from httomolibgpu.prep.stripe import (
11
11
  remove_stripe_based_sorting,
12
+ remove_stripe_fw,
12
13
  remove_stripe_ti,
13
14
  remove_all_stripe,
14
15
  raven_filter,
@@ -0,0 +1,155 @@
1
+ template<int WSize>
2
+ __global__ void grouped_convolution_x(
3
+ int dim_x,
4
+ int dim_y,
5
+ int dim_z,
6
+ const float* in,
7
+ int in_stride_x,
8
+ int in_stride_y,
9
+ int in_stride_z,
10
+ float* out,
11
+ int out_stride_z,
12
+ int out_stride_group,
13
+ const float* w
14
+ )
15
+ {
16
+ const int g_thd_x = blockDim.x * blockIdx.x + threadIdx.x;
17
+ const int g_thd_y = blockDim.y * blockIdx.y + threadIdx.y;
18
+ const int g_thd_z = blockDim.z * blockIdx.z + threadIdx.z;
19
+ if (g_thd_x >= dim_x || g_thd_y >= dim_y || g_thd_z >= dim_z)
20
+ {
21
+ return;
22
+ }
23
+
24
+ constexpr int out_groups = 2;
25
+ for (int i = 0; i < out_groups; ++i)
26
+ {
27
+ float acc = 0.F;
28
+ for (int j = 0; j < WSize; ++j)
29
+ {
30
+ const int w_idx = i * WSize + j;
31
+ const int in_idx = (g_thd_x * in_stride_x + j) + g_thd_y * in_stride_y + g_thd_z * in_stride_z;
32
+ acc += w[w_idx] * in[in_idx];
33
+ }
34
+ const int out_idx = g_thd_x + g_thd_y * dim_x + g_thd_z * out_stride_z + i * out_stride_group;
35
+ out[out_idx] = acc;
36
+ }
37
+ }
38
+
39
+ template<int WSize>
40
+ __global__ void grouped_convolution_y(
41
+ int dim_x,
42
+ int dim_y,
43
+ int dim_z,
44
+ const float* in,
45
+ int in_stride_x,
46
+ int in_stride_y,
47
+ int in_stride_z,
48
+ int in_stride_group,
49
+ float* out,
50
+ int out_stride_z,
51
+ int out_stride_group,
52
+ const float* w
53
+ )
54
+ {
55
+ const int g_thd_x = blockDim.x * blockIdx.x + threadIdx.x;
56
+ const int g_thd_y = blockDim.y * blockIdx.y + threadIdx.y;
57
+ const int g_thd_z = blockDim.z * blockIdx.z + threadIdx.z;
58
+ if (g_thd_x >= dim_x || g_thd_y >= dim_y || g_thd_z >= dim_z)
59
+ {
60
+ return;
61
+ }
62
+
63
+ constexpr int in_groups = 2;
64
+ constexpr int out_groups = 2;
65
+ constexpr int item_stride_y = 2;
66
+ for (int group = 0; group < in_groups; ++group)
67
+ {
68
+ for (int i = 0; i < out_groups; ++i)
69
+ {
70
+ float acc = 0.F;
71
+ for (int j = 0; j < WSize; ++j)
72
+ {
73
+ const int w_idx = (out_groups * group + i) * WSize + j;
74
+ const int in_idx = g_thd_x * in_stride_x + (item_stride_y * g_thd_y + j) * in_stride_y + group * in_stride_group + g_thd_z * in_stride_z;
75
+ acc += w[w_idx] * in[in_idx];
76
+ }
77
+ const int out_idx = g_thd_x + g_thd_y * dim_x + g_thd_z * out_stride_z + (out_groups * group + i) * out_stride_group;
78
+ out[out_idx] = acc;
79
+ }
80
+ }
81
+ }
82
+
83
+ template<int WSize>
84
+ __global__ void transposed_convolution_x(
85
+ int dim_x,
86
+ int dim_y,
87
+ int dim_z,
88
+ const float* in,
89
+ int in_dim_x,
90
+ int in_stride_y,
91
+ int in_stride_z,
92
+ const float* w,
93
+ float* out
94
+ )
95
+ {
96
+ const int g_thd_x = blockDim.x * blockIdx.x + threadIdx.x;
97
+ const int g_thd_y = blockDim.y * blockIdx.y + threadIdx.y;
98
+ const int g_thd_z = blockDim.z * blockIdx.z + threadIdx.z;
99
+ if (g_thd_x >= dim_x || g_thd_y >= dim_y || g_thd_z >= dim_z)
100
+ {
101
+ return;
102
+ }
103
+
104
+ constexpr int item_out_stride = 2;
105
+ float acc = 0.F;
106
+ for (int i = 0; i < WSize; ++i)
107
+ {
108
+ const int in_x = (g_thd_x - i) / item_out_stride;
109
+ const int in_x_mod = (g_thd_x - i) % item_out_stride;
110
+ if (in_x_mod == 0 && in_x >= 0 && in_x < in_dim_x)
111
+ {
112
+ const int in_idx = in_x + g_thd_y * in_stride_y + g_thd_z * in_stride_z;
113
+ acc += in[in_idx] * w[i];
114
+ }
115
+ }
116
+ const int out_idx = g_thd_x + dim_x * g_thd_y + dim_x * dim_y * g_thd_z;
117
+ out[out_idx] = acc;
118
+ }
119
+
120
+ template<int WSize>
121
+ __global__ void transposed_convolution_y(
122
+ int dim_x,
123
+ int dim_y,
124
+ int dim_z,
125
+ const float* in,
126
+ int in_dim_y,
127
+ int in_stride_y,
128
+ int in_stride_z,
129
+ const float* w,
130
+ float* out
131
+ )
132
+ {
133
+ const int g_thd_x = blockDim.x * blockIdx.x + threadIdx.x;
134
+ const int g_thd_y = blockDim.y * blockIdx.y + threadIdx.y;
135
+ const int g_thd_z = blockDim.z * blockIdx.z + threadIdx.z;
136
+ if (g_thd_x >= dim_x || g_thd_y >= dim_y || g_thd_z >= dim_z)
137
+ {
138
+ return;
139
+ }
140
+
141
+ constexpr int item_out_stride = 2;
142
+ float acc = 0.F;
143
+ for (int i = 0; i < WSize; ++i)
144
+ {
145
+ const int in_y = (g_thd_y - i) / item_out_stride;
146
+ const int in_y_mod = (g_thd_y - i) % item_out_stride;
147
+ if (in_y_mod == 0 && in_y >= 0 && in_y < in_dim_y)
148
+ {
149
+ const int in_idx = g_thd_x + in_y * in_stride_y + g_thd_z * in_stride_z;
150
+ acc += in[in_idx] * w[i];
151
+ }
152
+ }
153
+ const int out_idx = g_thd_x + dim_x * g_thd_y + dim_x * dim_y * g_thd_z;
154
+ out[out_idx] = acc;
155
+ }
@@ -2,6 +2,7 @@ cupy_run = False
2
2
  try:
3
3
  import cupy as cp
4
4
  import nvtx
5
+ from cupyx.scipy.fft import next_fast_len
5
6
 
6
7
  try:
7
8
  cp.cuda.Device(0).compute_capability
@@ -15,5 +16,6 @@ except ImportError as e:
15
16
  )
16
17
  from unittest.mock import Mock
17
18
  import numpy as cp
19
+ from scipy.fft import next_fast_len
18
20
 
19
21
  nvtx = Mock()
@@ -26,6 +26,7 @@ from httomolibgpu.memory_estimator_helpers import _DeviceMemStack
26
26
 
27
27
  cp = cupywrapper.cp
28
28
  cupy_run = cupywrapper.cupy_run
29
+ next_fast_len = cupywrapper.next_fast_len
29
30
 
30
31
  from unittest.mock import Mock
31
32
 
@@ -38,7 +39,7 @@ else:
38
39
  fftshift = Mock()
39
40
 
40
41
  from numpy import float32
41
- from typing import Optional, Tuple
42
+ from typing import Literal, Optional, Tuple
42
43
  import math
43
44
 
44
45
  __all__ = [
@@ -56,6 +57,10 @@ def paganin_filter(
56
57
  distance: float = 1.0,
57
58
  energy: float = 53.0,
58
59
  ratio_delta_beta: float = 250,
60
+ calculate_padding_value_method: Literal[
61
+ "next_power_of_2", "next_fast_length", "use_pad_x_y"
62
+ ] = "next_power_of_2",
63
+ pad_x_y: Optional[list] = None,
59
64
  calc_peak_gpu_mem: bool = False,
60
65
  ) -> cp.ndarray:
61
66
  """
@@ -74,6 +79,10 @@ def paganin_filter(
74
79
  Beam energy in keV.
75
80
  ratio_delta_beta : float
76
81
  The ratio of delta/beta, where delta is the phase shift and real part of the complex material refractive index and beta is the absorption.
82
+ calculate_padding_value_method: str
83
+ Method to calculate the padded size of the input data. Accepted values are 'next_power_of_2', 'next_fast_length' and 'use_pad_x_y`.
84
+ pad_x_y list | None:
85
+ Padding values in pixels horizontally and vertically. Must be None, unless `calculate_padding_value_method` is 'use_pad_x_y'.
77
86
  calc_peak_gpu_mem: bool
78
87
  Parameter to support memory estimation in HTTomo. Irrelevant to the method itself and can be ignored by user.
79
88
 
@@ -93,9 +102,9 @@ def paganin_filter(
93
102
  mem_stack.malloc(np.prod(tomo) * np.float32().itemsize)
94
103
  dz_orig, dy_orig, dx_orig = tomo.shape if not mem_stack else tomo
95
104
 
96
- # Perform padding to the power of 2 as FFT is O(n*log(n)) complexity
97
- # TODO: adding other options of padding?
98
- padded_tomo, pad_tup = _pad_projections_to_second_power(tomo, mem_stack)
105
+ padded_tomo, pad_tup = _pad_projections(
106
+ tomo, calculate_padding_value_method, pad_x_y, mem_stack
107
+ )
99
108
 
100
109
  dz, dy, dx = padded_tomo.shape if not mem_stack else padded_tomo
101
110
 
@@ -219,21 +228,59 @@ def _shift_bit_length(x: int) -> int:
219
228
  return 1 << (x - 1).bit_length()
220
229
 
221
230
 
222
- def _calculate_pad_size(datashape: tuple) -> list:
231
+ def _calculate_pad_size(
232
+ datashape: tuple,
233
+ calculate_padding_value_method: Literal[
234
+ "next_power_of_2", "next_fast_length", "use_pad_x_y"
235
+ ],
236
+ pad_x_y: Optional[list],
237
+ ) -> list:
223
238
  """Calculating the padding size
224
239
 
225
240
  Args:
226
- datashape (tuple): the shape of the 3D data
241
+ datashape (tuple):
242
+ the shape of the 3D data
243
+ calculate_padding_value_method: str
244
+ Method to calculate the padded size of the input data. Accepted values are 'next_power_of_2', 'next_fast_length' and 'use_pad_x_y`.
245
+ pad_x_y (int, int) | None:
246
+ Padding values in pixels horizontally and vertically. Must be None, unless `calculate_padding_value_method` is 'use_pad_x_y'.
227
247
 
228
248
  Returns:
229
249
  list: the padded dimensions
230
250
  """
251
+ if pad_x_y is not None and calculate_padding_value_method != "use_pad_x_y":
252
+ raise ValueError(
253
+ 'calculate_padding_value_method must be "use_pad_x_y" when pad_x_y is specified'
254
+ )
255
+ elif calculate_padding_value_method == "use_pad_x_y":
256
+ if pad_x_y is None:
257
+ raise ValueError(
258
+ 'pad_x_y must be provided when calculate_padding_value_method is "use_pad_x_y"'
259
+ )
260
+ elif (
261
+ not isinstance(pad_x_y, list)
262
+ or len(pad_x_y) != 2
263
+ or not isinstance(pad_x_y[0], int)
264
+ or not isinstance(pad_x_y[1], int)
265
+ ):
266
+ raise ValueError("pad_x_y must be a list of two integers")
267
+
268
+ if calculate_padding_value_method == "next_power_of_2":
269
+ calculate_padded_dim = lambda _, size: _shift_bit_length(size + 1)
270
+ elif calculate_padding_value_method == "next_fast_length":
271
+ calculate_padded_dim = lambda _, size: next_fast_len(size)
272
+ elif calculate_padding_value_method == "use_pad_x_y":
273
+ calculate_padded_dim = lambda dim, size: size + 2 * pad_x_y[2 - dim]
274
+ else:
275
+ raise ValueError(
276
+ f'Unexpected calculate_padding_value_method: "{calculate_padding_value_method}"'
277
+ )
231
278
  pad_list = []
232
279
  for index, element in enumerate(datashape):
233
280
  if index == 0:
234
281
  pad_width = (0, 0) # do not pad the slicing dim
235
282
  else:
236
- diff = _shift_bit_length(element + 1) - element
283
+ diff = calculate_padded_dim(index, element) - element
237
284
  if element % 2 == 0:
238
285
  pad_width_scalar = diff // 2
239
286
  pad_width = (pad_width_scalar, pad_width_scalar)
@@ -248,17 +295,27 @@ def _calculate_pad_size(datashape: tuple) -> list:
248
295
  return pad_list
249
296
 
250
297
 
251
- def _pad_projections_to_second_power(
252
- tomo: cp.ndarray, mem_stack: Optional[_DeviceMemStack]
298
+ def _pad_projections(
299
+ tomo: cp.ndarray,
300
+ calculate_padding_value_method: Literal[
301
+ "next_power_of_2", "next_fast_length", "use_pad_x_y"
302
+ ],
303
+ pad_x_y: Optional[list],
304
+ mem_stack: Optional[_DeviceMemStack],
253
305
  ) -> Tuple[cp.ndarray, Tuple[int, int]]:
254
306
  """
255
- Performs padding of each projection to the next power of 2.
307
+ Performs padding of each projection to a size optimal for FFT.
256
308
  If the shape is not even we also care of that before padding.
257
309
 
258
310
  Parameters
259
311
  ----------
260
312
  tomo : cp.ndarray
261
313
  3d projection data
314
+ calculate_padding_value_method: str
315
+ Method to calculate the padded size of the input data. Accepted values are 'next_power_of_2', 'next_fast_length' and 'use_pad_x_y`.
316
+ pad_x_y: list | None:
317
+ Padding values in pixels horizontally and vertically. Must be None, unless `calculate_padding_value_method` is 'use_pad_x_y'.
318
+
262
319
 
263
320
  Returns
264
321
  -------
@@ -268,7 +325,9 @@ def _pad_projections_to_second_power(
268
325
  """
269
326
  full_shape_tomo = cp.shape(tomo) if not mem_stack else tomo
270
327
 
271
- pad_list = _calculate_pad_size(full_shape_tomo)
328
+ pad_list = _calculate_pad_size(
329
+ full_shape_tomo, calculate_padding_value_method, pad_x_y
330
+ )
272
331
 
273
332
  if mem_stack:
274
333
  padded_tomo = [