nabu 2023.2.1__py3-none-any.whl → 2024.1.0rc3__py3-none-any.whl
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.
- doc/conf.py +1 -1
- doc/doc_config.py +32 -0
- nabu/__init__.py +2 -1
- nabu/app/bootstrap_stitching.py +1 -1
- nabu/app/cli_configs.py +122 -2
- nabu/app/composite_cor.py +27 -2
- nabu/app/correct_rot.py +70 -0
- nabu/app/create_distortion_map_from_poly.py +42 -18
- nabu/app/diag_to_pix.py +358 -0
- nabu/app/diag_to_rot.py +449 -0
- nabu/app/generate_header.py +4 -3
- nabu/app/histogram.py +2 -2
- nabu/app/multicor.py +6 -1
- nabu/app/parse_reconstruction_log.py +151 -0
- nabu/app/prepare_weights_double.py +83 -22
- nabu/app/reconstruct.py +5 -1
- nabu/app/reconstruct_helical.py +7 -0
- nabu/app/reduce_dark_flat.py +6 -3
- nabu/app/rotate.py +4 -4
- nabu/app/stitching.py +16 -2
- nabu/app/tests/test_reduce_dark_flat.py +18 -2
- nabu/app/validator.py +4 -4
- nabu/cuda/convolution.py +8 -376
- nabu/cuda/fft.py +4 -0
- nabu/cuda/kernel.py +4 -4
- nabu/cuda/medfilt.py +5 -158
- nabu/cuda/padding.py +5 -71
- nabu/cuda/processing.py +23 -2
- nabu/cuda/src/ElementOp.cu +78 -0
- nabu/cuda/src/backproj.cu +28 -2
- nabu/cuda/src/fourier_wavelets.cu +2 -2
- nabu/cuda/src/normalization.cu +23 -0
- nabu/cuda/src/padding.cu +2 -2
- nabu/cuda/src/transpose.cu +16 -0
- nabu/cuda/utils.py +39 -0
- nabu/estimation/alignment.py +10 -1
- nabu/estimation/cor.py +808 -38
- nabu/estimation/cor_sino.py +7 -9
- nabu/estimation/tests/test_cor.py +85 -3
- nabu/io/reader.py +26 -18
- nabu/io/tests/test_cast_volume.py +3 -3
- nabu/io/tests/test_detector_distortion.py +3 -3
- nabu/io/tiffwriter_zmm.py +2 -2
- nabu/io/utils.py +14 -4
- nabu/io/writer.py +5 -3
- nabu/misc/fftshift.py +6 -0
- nabu/misc/histogram.py +5 -285
- nabu/misc/histogram_cuda.py +8 -104
- nabu/misc/kernel_base.py +3 -121
- nabu/misc/padding_base.py +5 -69
- nabu/misc/processing_base.py +3 -107
- nabu/misc/rotation.py +5 -62
- nabu/misc/rotation_cuda.py +5 -65
- nabu/misc/transpose.py +6 -0
- nabu/misc/unsharp.py +3 -78
- nabu/misc/unsharp_cuda.py +5 -52
- nabu/misc/unsharp_opencl.py +8 -85
- nabu/opencl/fft.py +6 -0
- nabu/opencl/kernel.py +21 -6
- nabu/opencl/padding.py +5 -72
- nabu/opencl/processing.py +27 -5
- nabu/opencl/src/backproj.cl +3 -3
- nabu/opencl/src/fftshift.cl +65 -12
- nabu/opencl/src/padding.cl +2 -2
- nabu/opencl/src/roll.cl +96 -0
- nabu/opencl/src/transpose.cl +16 -0
- nabu/pipeline/config_validators.py +63 -3
- nabu/pipeline/dataset_validator.py +2 -2
- nabu/pipeline/estimators.py +193 -35
- nabu/pipeline/fullfield/chunked.py +34 -17
- nabu/pipeline/fullfield/chunked_cuda.py +7 -5
- nabu/pipeline/fullfield/computations.py +48 -13
- nabu/pipeline/fullfield/nabu_config.py +13 -13
- nabu/pipeline/fullfield/processconfig.py +10 -5
- nabu/pipeline/fullfield/reconstruction.py +1 -2
- nabu/pipeline/helical/fbp.py +5 -0
- nabu/pipeline/helical/filtering.py +12 -9
- nabu/pipeline/helical/gridded_accumulator.py +179 -33
- nabu/pipeline/helical/helical_chunked_regridded.py +262 -151
- nabu/pipeline/helical/helical_chunked_regridded_cuda.py +4 -11
- nabu/pipeline/helical/helical_reconstruction.py +56 -18
- nabu/pipeline/helical/span_strategy.py +1 -1
- nabu/pipeline/helical/tests/test_accumulator.py +4 -0
- nabu/pipeline/params.py +23 -2
- nabu/pipeline/processconfig.py +3 -8
- nabu/pipeline/tests/test_chunk_reader.py +78 -0
- nabu/pipeline/tests/test_estimators.py +120 -2
- nabu/pipeline/utils.py +25 -0
- nabu/pipeline/writer.py +2 -0
- nabu/preproc/ccd_cuda.py +9 -7
- nabu/preproc/ctf.py +21 -26
- nabu/preproc/ctf_cuda.py +25 -25
- nabu/preproc/double_flatfield.py +14 -2
- nabu/preproc/double_flatfield_cuda.py +7 -11
- nabu/preproc/flatfield_cuda.py +23 -27
- nabu/preproc/phase.py +19 -24
- nabu/preproc/phase_cuda.py +21 -21
- nabu/preproc/shift_cuda.py +58 -28
- nabu/preproc/tests/test_ctf.py +5 -5
- nabu/preproc/tests/test_double_flatfield.py +2 -2
- nabu/preproc/tests/test_vshift.py +13 -2
- nabu/processing/__init__.py +0 -0
- nabu/processing/convolution_cuda.py +375 -0
- nabu/processing/fft_base.py +163 -0
- nabu/processing/fft_cuda.py +256 -0
- nabu/processing/fft_opencl.py +54 -0
- nabu/processing/fftshift.py +134 -0
- nabu/processing/histogram.py +286 -0
- nabu/processing/histogram_cuda.py +103 -0
- nabu/processing/kernel_base.py +126 -0
- nabu/processing/medfilt_cuda.py +159 -0
- nabu/processing/muladd.py +29 -0
- nabu/processing/muladd_cuda.py +68 -0
- nabu/processing/padding_base.py +71 -0
- nabu/processing/padding_cuda.py +75 -0
- nabu/processing/padding_opencl.py +77 -0
- nabu/processing/processing_base.py +123 -0
- nabu/processing/roll_opencl.py +64 -0
- nabu/processing/rotation.py +63 -0
- nabu/processing/rotation_cuda.py +66 -0
- nabu/processing/tests/__init__.py +0 -0
- nabu/processing/tests/test_fft.py +268 -0
- nabu/processing/tests/test_fftshift.py +71 -0
- nabu/{misc → processing}/tests/test_histogram.py +2 -4
- nabu/{cuda → processing}/tests/test_medfilt.py +1 -1
- nabu/processing/tests/test_muladd.py +54 -0
- nabu/{cuda → processing}/tests/test_padding.py +119 -75
- nabu/processing/tests/test_roll.py +63 -0
- nabu/{misc → processing}/tests/test_rotation.py +3 -2
- nabu/processing/tests/test_transpose.py +72 -0
- nabu/{misc → processing}/tests/test_unsharp.py +41 -8
- nabu/processing/transpose.py +126 -0
- nabu/processing/unsharp.py +79 -0
- nabu/processing/unsharp_cuda.py +53 -0
- nabu/processing/unsharp_opencl.py +75 -0
- nabu/reconstruction/fbp.py +34 -10
- nabu/reconstruction/fbp_base.py +35 -16
- nabu/reconstruction/fbp_opencl.py +7 -12
- nabu/reconstruction/filtering.py +2 -2
- nabu/reconstruction/filtering_cuda.py +13 -14
- nabu/reconstruction/filtering_opencl.py +3 -4
- nabu/reconstruction/projection.py +2 -0
- nabu/reconstruction/rings.py +158 -1
- nabu/reconstruction/rings_cuda.py +218 -58
- nabu/reconstruction/sinogram_cuda.py +16 -12
- nabu/reconstruction/tests/test_deringer.py +116 -14
- nabu/reconstruction/tests/test_fbp.py +22 -31
- nabu/reconstruction/tests/test_filtering.py +11 -2
- nabu/resources/dataset_analyzer.py +89 -26
- nabu/resources/nxflatfield.py +2 -2
- nabu/resources/tests/test_nxflatfield.py +1 -1
- nabu/resources/utils.py +9 -2
- nabu/stitching/alignment.py +184 -0
- nabu/stitching/config.py +241 -39
- nabu/stitching/definitions.py +6 -0
- nabu/stitching/frame_composition.py +4 -2
- nabu/stitching/overlap.py +99 -3
- nabu/stitching/sample_normalization.py +60 -0
- nabu/stitching/slurm_utils.py +10 -10
- nabu/stitching/tests/test_alignment.py +99 -0
- nabu/stitching/tests/test_config.py +16 -1
- nabu/stitching/tests/test_overlap.py +68 -2
- nabu/stitching/tests/test_sample_normalization.py +49 -0
- nabu/stitching/tests/test_slurm_utils.py +5 -5
- nabu/stitching/tests/test_utils.py +3 -33
- nabu/stitching/tests/test_z_stitching.py +391 -22
- nabu/stitching/utils.py +144 -202
- nabu/stitching/z_stitching.py +309 -126
- nabu/testutils.py +18 -0
- nabu/thirdparty/tomocupy_remove_stripe.py +586 -0
- nabu/utils.py +32 -6
- {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/LICENSE +1 -1
- {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/METADATA +5 -5
- nabu-2024.1.0rc3.dist-info/RECORD +296 -0
- {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/WHEEL +1 -1
- {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/entry_points.txt +5 -1
- nabu/conftest.py +0 -14
- nabu/opencl/fftshift.py +0 -92
- nabu/opencl/tests/test_fftshift.py +0 -55
- nabu/opencl/tests/test_padding.py +0 -84
- nabu-2023.2.1.dist-info/RECORD +0 -252
- /nabu/cuda/src/{fftshift.cu → dfi_fftshift.cu} +0 -0
- {nabu-2023.2.1.dist-info → nabu-2024.1.0rc3.dist-info}/top_level.txt +0 -0
nabu/misc/processing_base.py
CHANGED
@@ -1,108 +1,4 @@
|
|
1
|
-
|
1
|
+
from nabu.processing.processing_base import ProcessingBase
|
2
|
+
from ..utils import deprecated_class
|
2
3
|
|
3
|
-
|
4
|
-
class ProcessingBase:
|
5
|
-
_array_class = None
|
6
|
-
|
7
|
-
def __init__(self):
|
8
|
-
self._allocated = {}
|
9
|
-
|
10
|
-
def init_arrays_to_none(self, arrays_names):
|
11
|
-
"""
|
12
|
-
Initialize arrays to None. After calling this method, the current instance will
|
13
|
-
have self.array_name = None, and self._old_array_name = None.
|
14
|
-
|
15
|
-
Parameters
|
16
|
-
----------
|
17
|
-
arrays_names: list of str
|
18
|
-
List of arrays names.
|
19
|
-
"""
|
20
|
-
for array_name in arrays_names:
|
21
|
-
setattr(self, array_name, None)
|
22
|
-
setattr(self, "_old_" + array_name, None)
|
23
|
-
self._allocated[array_name] = False
|
24
|
-
|
25
|
-
def recover_arrays_references(self, arrays_names):
|
26
|
-
"""
|
27
|
-
Performs self._array_name = self._old_array_name,
|
28
|
-
for each array_name in arrays_names.
|
29
|
-
|
30
|
-
Parameters
|
31
|
-
----------
|
32
|
-
arrays_names: list of str
|
33
|
-
List of array names
|
34
|
-
"""
|
35
|
-
for array_name in arrays_names:
|
36
|
-
old_arr = getattr(self, "_old_" + array_name, None)
|
37
|
-
if old_arr is not None:
|
38
|
-
setattr(self, array_name, old_arr)
|
39
|
-
|
40
|
-
def _allocate_array_mem(self, shape, dtype):
|
41
|
-
raise ValueError("Base class")
|
42
|
-
|
43
|
-
def allocate_array(self, array_name, shape, dtype=np.float32):
|
44
|
-
"""
|
45
|
-
Allocate a GPU array on the current context/stream/device,
|
46
|
-
and set 'self.array_name' to this array.
|
47
|
-
|
48
|
-
Parameters
|
49
|
-
----------
|
50
|
-
array_name: str
|
51
|
-
Name of the array (for book-keeping)
|
52
|
-
shape: tuple of int
|
53
|
-
Array shape
|
54
|
-
dtype: numpy.dtype, optional
|
55
|
-
Data type. Default is float32.
|
56
|
-
"""
|
57
|
-
if not self._allocated.get(array_name, False):
|
58
|
-
new_device_arr = self._allocate_array_mem(shape, dtype)
|
59
|
-
setattr(self, array_name, new_device_arr)
|
60
|
-
self._allocated[array_name] = True
|
61
|
-
return getattr(self, array_name)
|
62
|
-
|
63
|
-
def set_array(self, array_name, array_ref, dtype=np.float32):
|
64
|
-
"""
|
65
|
-
Set the content of a device array.
|
66
|
-
|
67
|
-
Parameters
|
68
|
-
----------
|
69
|
-
array_name: str
|
70
|
-
Array name. This method will look for self.array_name.
|
71
|
-
array_ref: array (numpy or GPU array)
|
72
|
-
Array containing the data to copy to 'array_name'.
|
73
|
-
dtype: numpy.dtype, optional
|
74
|
-
Data type. Default is float32.
|
75
|
-
"""
|
76
|
-
if isinstance(array_ref, self._array_class):
|
77
|
-
current_arr = getattr(self, array_name, None)
|
78
|
-
setattr(self, "_old_" + array_name, current_arr)
|
79
|
-
setattr(self, array_name, array_ref)
|
80
|
-
elif isinstance(array_ref, np.ndarray):
|
81
|
-
self.allocate_array(array_name, array_ref.shape, dtype=dtype)
|
82
|
-
getattr(self, array_name).set(array_ref)
|
83
|
-
else:
|
84
|
-
raise ValueError("Expected numpy array or pycuda array")
|
85
|
-
return getattr(self, array_name)
|
86
|
-
|
87
|
-
def get_array(self, array_name):
|
88
|
-
return getattr(self, array_name, None)
|
89
|
-
|
90
|
-
# COMPAT.
|
91
|
-
_init_arrays_to_none = init_arrays_to_none
|
92
|
-
_recover_arrays_references = recover_arrays_references
|
93
|
-
_allocate_array = allocate_array
|
94
|
-
_set_array = set_array
|
95
|
-
|
96
|
-
def check_array(self, arr, expected_shape, expected_dtype="f", check_contiguous=True):
|
97
|
-
"""
|
98
|
-
Check whether a given array is suitable for being processed (shape, dtype, contiguous)
|
99
|
-
"""
|
100
|
-
if arr.shape != expected_shape:
|
101
|
-
raise ValueError("Expected shape %s but got %s" % (str(expected_shape), str(arr.shape)))
|
102
|
-
if arr.dtype != np.dtype(expected_dtype):
|
103
|
-
raise ValueError("Expected data type %s but got %s" % (str(expected_dtype), str(arr.dtype)))
|
104
|
-
if check_contiguous:
|
105
|
-
if isinstance(arr, np.ndarray) and not (arr.flags["C_CONTIGUOUS"]):
|
106
|
-
raise ValueError("Expected C-contiguous array")
|
107
|
-
if isinstance(arr, self._array_class) and not arr.flags.c_contiguous:
|
108
|
-
raise ValueError("Expected C-contiguous array")
|
4
|
+
ProcessingBase = deprecated_class("ProcessingBase has been moved to nabu.processing", do_print=True)(ProcessingBase)
|
nabu/misc/rotation.py
CHANGED
@@ -1,63 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
from ..processing.rotation import *
|
2
|
+
from ..utils import deprecation_warning
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class Rotation:
|
10
|
-
supported_modes = {
|
11
|
-
"constant": "constant",
|
12
|
-
"zeros": "constant",
|
13
|
-
"edge": "edge",
|
14
|
-
"edges": "edge",
|
15
|
-
"symmetric": "symmetric",
|
16
|
-
"sym": "symmetric",
|
17
|
-
"reflect": "reflect",
|
18
|
-
"wrap": "wrap",
|
19
|
-
"periodic": "wrap",
|
20
|
-
}
|
21
|
-
|
22
|
-
def __init__(self, shape, angle, center=None, mode="edge", reshape=False, **sk_kwargs):
|
23
|
-
"""
|
24
|
-
Initiate a Rotation object.
|
25
|
-
|
26
|
-
Parameters
|
27
|
-
----------
|
28
|
-
shape: tuple of int
|
29
|
-
Shape of the images to process
|
30
|
-
angle: float
|
31
|
-
Rotation angle in DEGREES
|
32
|
-
center: tuple of float, optional
|
33
|
-
Coordinates of the center of rotation, in the format (X, Y) (mind the non-python
|
34
|
-
convention !).
|
35
|
-
Default is ((Nx - 1)/2.0, (Ny - 1)/2.0)
|
36
|
-
mode: str, optional
|
37
|
-
Padding mode. Default is "edge".
|
38
|
-
reshape: bool, optional
|
39
|
-
|
40
|
-
|
41
|
-
Other Parameters
|
42
|
-
-----------------
|
43
|
-
All the other parameters are passed directly to scikit image 'rotate' function:
|
44
|
-
order, cval, clip, preserve_range.
|
45
|
-
"""
|
46
|
-
self.shape = shape
|
47
|
-
self.angle = angle
|
48
|
-
self.center = center
|
49
|
-
self.mode = mode
|
50
|
-
self.reshape = reshape
|
51
|
-
self.sk_kwargs = sk_kwargs
|
52
|
-
|
53
|
-
def rotate(self, img, output=None):
|
54
|
-
if not __have__skimage__:
|
55
|
-
raise ValueError("scikit-image is needed for using rotate()")
|
56
|
-
res = rotate(img, self.angle, resize=self.reshape, center=self.center, mode=self.mode, **self.sk_kwargs)
|
57
|
-
if output is not None:
|
58
|
-
output[:] = res[:]
|
59
|
-
return output
|
60
|
-
else:
|
61
|
-
return res
|
62
|
-
|
63
|
-
__call__ = rotate
|
4
|
+
deprecation_warning(
|
5
|
+
"nabu.misc.rotation has been moved to nabu.processing.rotation", do_print=True, func_name="rotation"
|
6
|
+
)
|
nabu/misc/rotation_cuda.py
CHANGED
@@ -1,66 +1,6 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
from ..utils import get_cuda_srcfile, updiv
|
4
|
-
from ..cuda.utils import __has_pycuda__, copy_array
|
5
|
-
from ..cuda.processing import CudaProcessing
|
1
|
+
from ..processing.rotation_cuda import *
|
2
|
+
from ..utils import deprecation_warning
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class CudaRotation(Rotation):
|
13
|
-
def __init__(self, shape, angle, center=None, mode="edge", reshape=False, cuda_options=None, **sk_kwargs):
|
14
|
-
if center is None:
|
15
|
-
center = ((shape[1] - 1) / 2.0, (shape[0] - 1) / 2.0)
|
16
|
-
super().__init__(shape, angle, center=center, mode=mode, reshape=reshape, **sk_kwargs)
|
17
|
-
self._init_cuda_rotation(cuda_options)
|
18
|
-
|
19
|
-
def _init_cuda_rotation(self, cuda_options):
|
20
|
-
cuda_options = cuda_options or {}
|
21
|
-
self.cuda_processing = CudaProcessing(**cuda_options)
|
22
|
-
self._allocate_arrays()
|
23
|
-
self._init_rotation_kernel()
|
24
|
-
|
25
|
-
def _allocate_arrays(self):
|
26
|
-
self._d_image_cua = cuda.np_to_array(np.zeros(self.shape, "f"), "C")
|
27
|
-
self.cuda_processing.init_arrays_to_none(["d_output"])
|
28
|
-
|
29
|
-
def _init_rotation_kernel(self):
|
30
|
-
self.cuda_rotation_kernel = CudaKernel("rotate", get_cuda_srcfile("rotation.cu"))
|
31
|
-
self.texref_image = self.cuda_rotation_kernel.module.get_texref("tex_image")
|
32
|
-
self.texref_image.set_filter_mode(cuda.filter_mode.LINEAR) # bilinear
|
33
|
-
self.texref_image.set_address_mode(0, cuda.address_mode.CLAMP) # TODO tune
|
34
|
-
self.texref_image.set_address_mode(1, cuda.address_mode.CLAMP) # TODO tune
|
35
|
-
self.cuda_rotation_kernel.prepare("Piiffff", [self.texref_image])
|
36
|
-
self.texref_image.set_array(self._d_image_cua)
|
37
|
-
self._cos_theta = np.cos(np.deg2rad(self.angle))
|
38
|
-
self._sin_theta = np.sin(np.deg2rad(self.angle))
|
39
|
-
self._Nx = np.int32(self.shape[1])
|
40
|
-
self._Ny = np.int32(self.shape[0])
|
41
|
-
self._center_x = np.float32(self.center[0])
|
42
|
-
self._center_y = np.float32(self.center[1])
|
43
|
-
self._block = (32, 32, 1) # tune ?
|
44
|
-
self._grid = (updiv(self.shape[1], self._block[1]), updiv(self.shape[0], self._block[0]), 1)
|
45
|
-
|
46
|
-
def rotate(self, img, output=None, do_checks=True):
|
47
|
-
copy_array(self._d_image_cua, img, check=do_checks)
|
48
|
-
if output is not None:
|
49
|
-
d_out = output
|
50
|
-
else:
|
51
|
-
self.cuda_processing.allocate_array("d_output", self.shape, np.float32)
|
52
|
-
d_out = self.cuda_processing.d_output
|
53
|
-
self.cuda_rotation_kernel(
|
54
|
-
d_out,
|
55
|
-
self._Nx,
|
56
|
-
self._Ny,
|
57
|
-
self._cos_theta,
|
58
|
-
self._sin_theta,
|
59
|
-
self._center_x,
|
60
|
-
self._center_y,
|
61
|
-
grid=self._grid,
|
62
|
-
block=self._block,
|
63
|
-
)
|
64
|
-
return d_out
|
65
|
-
|
66
|
-
__call__ = rotate
|
4
|
+
deprecation_warning(
|
5
|
+
"nabu.misc.rotation_cuda has been moved to nabu.processing.rotation_cuda", do_print=True, func_name="rotation_cuda"
|
6
|
+
)
|
nabu/misc/transpose.py
ADDED
nabu/misc/unsharp.py
CHANGED
@@ -1,79 +1,4 @@
|
|
1
|
-
|
2
|
-
from
|
3
|
-
from silx.image.utils import gaussian_kernel
|
1
|
+
from ..processing.unsharp import *
|
2
|
+
from ..utils import deprecation_warning
|
4
3
|
|
5
|
-
|
6
|
-
class UnsharpMask:
|
7
|
-
"""
|
8
|
-
A helper class for unsharp masking.
|
9
|
-
"""
|
10
|
-
|
11
|
-
avail_methods = ["gaussian", "log", "imagej"]
|
12
|
-
|
13
|
-
def __init__(self, shape, sigma, coeff, mode="reflect", method="gaussian"):
|
14
|
-
"""
|
15
|
-
Initialize a Unsharp mask.
|
16
|
-
`UnsharpedImage = (1 + coeff)*Image - coeff * ConvolutedImage`
|
17
|
-
|
18
|
-
If method == "log":
|
19
|
-
`UnsharpedImage = Image + coeff*ConvolutedImage`
|
20
|
-
|
21
|
-
Parameters
|
22
|
-
-----------
|
23
|
-
shape: tuple
|
24
|
-
Shape of the image.
|
25
|
-
sigma: float
|
26
|
-
Standard deviation of the Gaussian kernel
|
27
|
-
coeff: float
|
28
|
-
Coefficient in the linear combination of unsharp mask
|
29
|
-
mode: str, optional
|
30
|
-
Convolution mode. Default is "reflect"
|
31
|
-
method: str, optional
|
32
|
-
Method of unsharp mask. Can be "gaussian" (default) or "log" (Laplacian of Gaussian),
|
33
|
-
or "imagej".
|
34
|
-
|
35
|
-
|
36
|
-
Notes
|
37
|
-
-----
|
38
|
-
The computation is the following depending on the method:
|
39
|
-
|
40
|
-
- For method="gaussian": output = (1 + coeff) * image - coeff * image_blurred
|
41
|
-
- For method="log": output = image + coeff * image_blurred
|
42
|
-
- For method="imagej": output = (image - coeff*image_blurred)/(1-coeff)
|
43
|
-
"""
|
44
|
-
self.shape = shape
|
45
|
-
self.ndim = len(self.shape)
|
46
|
-
self.sigma = sigma
|
47
|
-
self.coeff = coeff
|
48
|
-
self._set_method(method)
|
49
|
-
self.mode = mode
|
50
|
-
self._compute_gaussian_kernel()
|
51
|
-
|
52
|
-
def _set_method(self, method):
|
53
|
-
if method not in self.avail_methods:
|
54
|
-
raise ValueError("Unknown unsharp method '%s'. Available are %s" % (method, str(self.avail_methods)))
|
55
|
-
self.method = method
|
56
|
-
|
57
|
-
def _compute_gaussian_kernel(self):
|
58
|
-
self._gaussian_kernel = np.ascontiguousarray(gaussian_kernel(self.sigma), dtype=np.float32)
|
59
|
-
|
60
|
-
def _blur2d(self, image):
|
61
|
-
res1 = convolve1d(image, self._gaussian_kernel, axis=1, mode=self.mode)
|
62
|
-
res = convolve1d(res1, self._gaussian_kernel, axis=0, mode=self.mode)
|
63
|
-
return res
|
64
|
-
|
65
|
-
def unsharp(self, image, output=None):
|
66
|
-
"""
|
67
|
-
Reference unsharp mask implementation.
|
68
|
-
"""
|
69
|
-
image_b = self._blur2d(image)
|
70
|
-
if self.method == "gaussian":
|
71
|
-
res = (1 + self.coeff) * image - self.coeff * image_b
|
72
|
-
elif self.method == "log":
|
73
|
-
res = image + self.coeff * image_b
|
74
|
-
else: # "imagej":
|
75
|
-
res = (image - self.coeff * image_b) / (1 - self.coeff)
|
76
|
-
if output is not None:
|
77
|
-
output[:] = res[:]
|
78
|
-
return output
|
79
|
-
return res
|
4
|
+
deprecation_warning("nabu.misc.unsharp has been moved to nabu.processing.unsharp", do_print=True, func_name="unsharp")
|
nabu/misc/unsharp_cuda.py
CHANGED
@@ -1,53 +1,6 @@
|
|
1
|
-
from ..
|
2
|
-
from ..
|
3
|
-
from ..cuda.processing import CudaProcessing
|
4
|
-
from .unsharp import UnsharpMask
|
1
|
+
from ..processing.unsharp_cuda import *
|
2
|
+
from ..utils import deprecation_warning
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class CudaUnsharpMask(UnsharpMask):
|
11
|
-
def __init__(self, shape, sigma, coeff, mode="reflect", method="gaussian", cuda_options=None):
|
12
|
-
"""
|
13
|
-
Unsharp Mask, cuda backend.
|
14
|
-
"""
|
15
|
-
super().__init__(shape, sigma, coeff, mode=mode, method=method)
|
16
|
-
self.cuda_processing = CudaProcessing(**(cuda_options or {}))
|
17
|
-
self._init_convolution()
|
18
|
-
self._init_mad_kernel()
|
19
|
-
self.cuda_processing.init_arrays_to_none(["_d_out"])
|
20
|
-
|
21
|
-
def _init_convolution(self):
|
22
|
-
self.convolution = Convolution(
|
23
|
-
self.shape,
|
24
|
-
self._gaussian_kernel,
|
25
|
-
mode=self.mode,
|
26
|
-
extra_options={ # Use the lowest amount of memory
|
27
|
-
"allocate_input_array": False,
|
28
|
-
"allocate_output_array": False,
|
29
|
-
"allocate_tmp_array": True,
|
30
|
-
},
|
31
|
-
)
|
32
|
-
|
33
|
-
def _init_mad_kernel(self):
|
34
|
-
# garray.GPUArray.mul_add is out of place...
|
35
|
-
self.mad_kernel = ElementwiseKernel(
|
36
|
-
"float* array, float fac, float* other, float otherfac",
|
37
|
-
"array[i] = fac * array[i] + otherfac * other[i]",
|
38
|
-
name="mul_add",
|
39
|
-
)
|
40
|
-
|
41
|
-
def unsharp(self, image, output=None):
|
42
|
-
if output is None:
|
43
|
-
output = self.cuda_processing.allocate_array("_d_out", self.shape, "f")
|
44
|
-
self.convolution(image, output=output)
|
45
|
-
if self.method == "gaussian":
|
46
|
-
self.mad_kernel(output, -self.coeff, image, 1.0 + self.coeff)
|
47
|
-
elif self.method == "log":
|
48
|
-
# output = output * coeff + image where output was image_blurred
|
49
|
-
self.mad_kernel(output, self.coeff, image, 1.0)
|
50
|
-
else: # "imagej":
|
51
|
-
# output = (image - coeff*image_blurred)/(1-coeff) where output was image_blurred
|
52
|
-
self.mad_kernel(output, -self.coeff / (1 - self.coeff), image, 1.0 / (1 - self.coeff))
|
53
|
-
return output
|
4
|
+
deprecation_warning(
|
5
|
+
"nabu.misc.unsharp_cuda has been moved to nabu.processing.unsharp_cuda", do_print=True, func_name="unsharp_cuda"
|
6
|
+
)
|
nabu/misc/unsharp_opencl.py
CHANGED
@@ -1,85 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
__have_opencl__ = False
|
10
|
-
from .unsharp import UnsharpMask
|
11
|
-
|
12
|
-
|
13
|
-
class OpenclUnsharpMask(UnsharpMask, OpenclProcessing):
|
14
|
-
def __init__(
|
15
|
-
self,
|
16
|
-
shape,
|
17
|
-
sigma,
|
18
|
-
coeff,
|
19
|
-
mode="reflect",
|
20
|
-
method="gaussian",
|
21
|
-
ctx=None,
|
22
|
-
devicetype="all",
|
23
|
-
platformid=None,
|
24
|
-
deviceid=None,
|
25
|
-
block_size=None,
|
26
|
-
memory=None,
|
27
|
-
profile=False,
|
28
|
-
):
|
29
|
-
"""
|
30
|
-
NB: For now, this class is designed to use the lowest amount of GPU memory
|
31
|
-
as possible. Therefore, the input and output image/volumes are assumed
|
32
|
-
to be already on device.
|
33
|
-
"""
|
34
|
-
if not (__have_opencl__):
|
35
|
-
raise ImportError("Need silx and pyopencl")
|
36
|
-
OpenclProcessing.__init__(
|
37
|
-
self,
|
38
|
-
ctx=ctx,
|
39
|
-
devicetype=devicetype,
|
40
|
-
platformid=platformid,
|
41
|
-
deviceid=deviceid,
|
42
|
-
block_size=block_size,
|
43
|
-
memory=memory,
|
44
|
-
profile=profile,
|
45
|
-
)
|
46
|
-
UnsharpMask.__init__(self, shape, sigma, coeff, mode=mode, method=method)
|
47
|
-
self._init_convolution()
|
48
|
-
self._init_mad_kernel()
|
49
|
-
|
50
|
-
def _init_convolution(self):
|
51
|
-
self.convolution = CLConvolution(
|
52
|
-
self.shape,
|
53
|
-
self._gaussian_kernel,
|
54
|
-
mode=self.mode,
|
55
|
-
ctx=self.ctx,
|
56
|
-
profile=self.profile,
|
57
|
-
extra_options={ # Use the lowest amount of memory
|
58
|
-
"allocate_input_array": False,
|
59
|
-
"allocate_output_array": False,
|
60
|
-
"allocate_tmp_array": True,
|
61
|
-
"dont_use_textures": True,
|
62
|
-
},
|
63
|
-
)
|
64
|
-
|
65
|
-
def _init_mad_kernel(self):
|
66
|
-
# parray.Array.mul_add is out of place...
|
67
|
-
self.mad_kernel = ElementwiseKernel(
|
68
|
-
self.ctx,
|
69
|
-
"float* array, float fac, float* other, float otherfac",
|
70
|
-
"array[i] = fac * array[i] + otherfac * other[i]",
|
71
|
-
name="mul_add",
|
72
|
-
)
|
73
|
-
|
74
|
-
def unsharp(self, image, output):
|
75
|
-
# For now image and output are assumed to be already allocated on device
|
76
|
-
assert isinstance(image, parray.Array)
|
77
|
-
assert isinstance(output, parray.Array)
|
78
|
-
self.convolution(image, output=output)
|
79
|
-
if self.method == "gaussian":
|
80
|
-
self.mad_kernel(output, -self.coeff, image, 1.0 + self.coeff)
|
81
|
-
elif self.method == "log":
|
82
|
-
self.mad_kernel(output, self.coeff, image, 1.0)
|
83
|
-
else: # "imagej":
|
84
|
-
self.mad_kernel(output, -self.coeff / (1 - self.coeff), image, 1.0 / (1 - self.coeff))
|
85
|
-
return output
|
1
|
+
from ..processing.unsharp_opencl import *
|
2
|
+
from ..utils import deprecation_warning
|
3
|
+
|
4
|
+
deprecation_warning(
|
5
|
+
"nabu.misc.unsharp_opencl has been moved to nabu.processing.unsharp_opencl",
|
6
|
+
do_print=True,
|
7
|
+
func_name="unsharp_opencl",
|
8
|
+
)
|
nabu/opencl/fft.py
ADDED
nabu/opencl/kernel.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import pyopencl.array as parray
|
2
2
|
from pyopencl import Program, CommandQueue, kernel_work_group_info
|
3
|
-
from ..utils import
|
4
|
-
from ..
|
3
|
+
from ..utils import deprecation_warning
|
4
|
+
from ..processing.kernel_base import KernelBase
|
5
5
|
|
6
6
|
|
7
7
|
class OpenCLKernel(KernelBase):
|
@@ -14,6 +14,8 @@ class OpenCLKernel(KernelBase):
|
|
14
14
|
Name of the OpenCL kernel.
|
15
15
|
ctx: pyopencl.Context
|
16
16
|
OpenCL context to use.
|
17
|
+
queue: pyopencl.CommandQueue
|
18
|
+
OpenCL queue to use. If provided, will use this queue's context instead of 'ctx'
|
17
19
|
filename: str, optional
|
18
20
|
Path to the file name containing kernels definitions
|
19
21
|
src: str, optional
|
@@ -28,13 +30,19 @@ class OpenCLKernel(KernelBase):
|
|
28
30
|
self,
|
29
31
|
kernel_name,
|
30
32
|
ctx,
|
33
|
+
queue=None,
|
31
34
|
filename=None,
|
32
35
|
src=None,
|
33
36
|
automation_params=None,
|
34
37
|
**build_kwargs,
|
35
38
|
):
|
36
39
|
super().__init__(kernel_name, filename=filename, src=src, automation_params=automation_params)
|
37
|
-
|
40
|
+
if queue is not None:
|
41
|
+
self.ctx = queue.context
|
42
|
+
self.queue = queue
|
43
|
+
else:
|
44
|
+
self.ctx = ctx
|
45
|
+
self.queue = None
|
38
46
|
self.compile_kernel_source(kernel_name, build_kwargs)
|
39
47
|
self.get_kernel()
|
40
48
|
|
@@ -105,9 +113,16 @@ class OpenCLKernel(KernelBase):
|
|
105
113
|
args[i] = arg.data
|
106
114
|
return tuple(args)
|
107
115
|
|
108
|
-
def call(self,
|
109
|
-
if not isinstance(
|
110
|
-
|
116
|
+
def call(self, *args, **kwargs):
|
117
|
+
if not isinstance(args[0], CommandQueue):
|
118
|
+
queue = self.queue
|
119
|
+
if queue is None:
|
120
|
+
raise ValueError(
|
121
|
+
"First argument must be a pyopencl queue - otherwise provide OpenCLKernel(..., queue=queue)"
|
122
|
+
)
|
123
|
+
else:
|
124
|
+
queue = args[0]
|
125
|
+
args = args[1:]
|
111
126
|
global_size, local_size, args, kwargs = self._prepare_call(*args, **kwargs)
|
112
127
|
|
113
128
|
kwargs.pop("global_size", None)
|
nabu/opencl/padding.py
CHANGED
@@ -1,73 +1,6 @@
|
|
1
|
-
|
2
|
-
from ..utils import
|
3
|
-
from .kernel import OpenCLKernel
|
4
|
-
from .processing import OpenCLProcessing
|
5
|
-
from .memcpy import OpenCLMemcpy2D
|
6
|
-
import pyopencl.array as parray
|
7
|
-
from ..misc.padding_base import PaddingBase
|
1
|
+
from ..processing.padding_opencl import *
|
2
|
+
from ..utils import deprecation_warning
|
8
3
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
A class for performing padding on GPU using Cuda
|
13
|
-
"""
|
14
|
-
|
15
|
-
# TODO docstring from base class
|
16
|
-
def __init__(self, shape, pad_width, mode="constant", opencl_options=None, **kwargs):
|
17
|
-
super().__init__(shape, pad_width, mode=mode, **kwargs)
|
18
|
-
self.opencl_processing = OpenCLProcessing(**(opencl_options or {}))
|
19
|
-
self.queue = self.opencl_processing.queue
|
20
|
-
self._init_opencl_coordinate_transform()
|
21
|
-
|
22
|
-
def _init_opencl_coordinate_transform(self):
|
23
|
-
if self.mode == "constant":
|
24
|
-
self.d_padded_array_constant = parray.to_device(self.queue, self.padded_array_constant)
|
25
|
-
self.memcpy2D = OpenCLMemcpy2D(ctx=self.opencl_processing.ctx, queue=self.queue)
|
26
|
-
return
|
27
|
-
self._coords_transform_kernel = OpenCLKernel(
|
28
|
-
"coordinate_transform",
|
29
|
-
self.opencl_processing.ctx,
|
30
|
-
filename=get_opencl_srcfile("padding.cl"),
|
31
|
-
)
|
32
|
-
self._coords_transform_global_size = self.padded_shape[::-1]
|
33
|
-
self.d_coords_rows = parray.to_device(self.queue, self.coords_rows)
|
34
|
-
self.d_coords_cols = parray.to_device(self.queue, self.coords_cols)
|
35
|
-
|
36
|
-
def _pad_constant(self, image, output):
|
37
|
-
pad_y, pad_x = self.pad_width
|
38
|
-
# the following line is not implemented in pyopencl
|
39
|
-
# self.d_padded_array_constant[pad_y[0] : pad_y[0] + self.shape[0], pad_x[0] : pad_x[0] + self.shape[1]] = image[:]
|
40
|
-
# cl.enqueue_copy is too cumbersome to use for Buffer <-> Buffer.
|
41
|
-
# Use a dedicated kernel instead.
|
42
|
-
# This is not optimal (two copies) - TODO write a constant padding kernel
|
43
|
-
self.memcpy2D(self.d_padded_array_constant, image, image.shape[::-1], dst_offset_xy=(pad_x[0], pad_y[0]))
|
44
|
-
output[:] = self.d_padded_array_constant[:]
|
45
|
-
return output
|
46
|
-
|
47
|
-
def pad(self, image, output=None):
|
48
|
-
"""
|
49
|
-
Pad an array.
|
50
|
-
|
51
|
-
Parameters
|
52
|
-
----------
|
53
|
-
image: pycuda.gpuarray.GPUArray
|
54
|
-
Image to pad
|
55
|
-
output: pycuda.gpuarray.GPUArray, optional
|
56
|
-
Output image. If provided, must be in the expected shape.
|
57
|
-
"""
|
58
|
-
if output is None:
|
59
|
-
output = self.opencl_processing.allocate_array("d_output", self.padded_shape)
|
60
|
-
if self.mode == "constant":
|
61
|
-
return self._pad_constant(image, output)
|
62
|
-
self._coords_transform_kernel(
|
63
|
-
self.queue,
|
64
|
-
image,
|
65
|
-
output,
|
66
|
-
self.d_coords_cols,
|
67
|
-
self.d_coords_rows,
|
68
|
-
np.int32(self.shape[1]),
|
69
|
-
np.int32(self.padded_shape[1]),
|
70
|
-
np.int32(self.padded_shape[0]),
|
71
|
-
global_size=self._coords_transform_global_size,
|
72
|
-
)
|
73
|
-
return output
|
4
|
+
deprecation_warning(
|
5
|
+
"nabu.opencl.padding has been moved to nabu.processing.padding_opencl", do_print=True, func_name="padding_opencl"
|
6
|
+
)
|