Skip to content

Commit ce1c15f

Browse files
authored
moving all gpu related imports under try (#152)
* moving all gpu related imports under try * adding pypi ci * fixing classifiers * correcting the publisher name * further import changes * remove nvtx to check docs * removing nvtx instances to allow docs to build, removing function doubleundescore duplications
1 parent 3a4524d commit ce1c15f

File tree

13 files changed

+117
-449
lines changed

13 files changed

+117
-449
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Upload Python Package to PyPI when Release is Created
2+
3+
on:
4+
release:
5+
types: [created]
6+
7+
jobs:
8+
pypi-publish:
9+
name: Publish release to PyPI
10+
runs-on: ubuntu-latest
11+
environment:
12+
name: pypi
13+
url: https://pypi.org/p/httomolibgpu
14+
permissions:
15+
id-token: write
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: "3.10"
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install setuptools wheel
26+
pip install --upgrade build
27+
- name: Build package
28+
run: |
29+
python -m build
30+
- name: Publish package distributions to PyPI
31+
uses: pypa/gh-action-pypi-publish@release/v1

conda/environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ channels:
44
- httomo
55
dependencies:
66
- conda-forge::cupy=12.3.0
7-
- conda-forge::numpy<=1.25
7+
- conda-forge::numpy
88
- conda-forge::nvtx
99
- conda-forge::scipy
1010
- conda-forge::python

httomolibgpu/cupywrapper.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
cupy_run = False
21
try:
32
import cupy as cp
43
import nvtx
5-
import cupyx
64

75
try:
86
cp.cuda.Device(0).compute_capability
@@ -17,5 +15,6 @@
1715
from unittest.mock import Mock
1816
import numpy as cp
1917

18+
cupy_run = False
19+
2020
nvtx = Mock()
21-
cupyx = Mock()

httomolibgpu/misc/corr.py

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@
2828
from httomolibgpu import cupywrapper
2929

3030
cp = cupywrapper.cp
31-
nvtx = cupywrapper.nvtx
31+
cupy_run = cupywrapper.cupy_run
3232

3333
from numpy import float32
34-
from httomolibgpu.cuda_kernels import load_cuda_module
34+
from unittest.mock import Mock
35+
36+
if cupy_run:
37+
from httomolibgpu.cuda_kernels import load_cuda_module
38+
else:
39+
load_cuda_module = Mock()
40+
3541

3642
__all__ = [
3743
"median_filter",
@@ -67,19 +73,6 @@ def median_filter(
6773
ValueError
6874
If the input array is not three dimensional.
6975
"""
70-
if cupywrapper.cupy_run:
71-
return __median_filter(data, kernel_size, dif)
72-
else:
73-
print("median_filter won't be executed because CuPy is not installed")
74-
return data
75-
76-
77-
@nvtx.annotate()
78-
def __median_filter(
79-
data: cp.ndarray,
80-
kernel_size: int = 3,
81-
dif: float = 0.0,
82-
) -> cp.ndarray:
8376
input_type = data.dtype
8477

8578
if input_type not in ["float32", "uint16"]:
@@ -148,8 +141,4 @@ def remove_outlier(
148141
if dif <= 0.0:
149142
raise ValueError("Threshold value (dif) must be positive and nonzero.")
150143

151-
if cupywrapper.cupy_run:
152-
return __median_filter(data, kernel_size, dif)
153-
else:
154-
print("remove_outlier won't be executed because CuPy is not installed")
155-
return data
144+
return median_filter(data, kernel_size, dif)

httomolibgpu/misc/morph.py

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@
2424
from httomolibgpu import cupywrapper
2525

2626
cp = cupywrapper.cp
27-
nvtx = cupywrapper.nvtx
28-
cupyx = cupywrapper.cupyx
27+
cupy_run = cupywrapper.cupy_run
2928

30-
from cupyx.scipy.interpolate import interpn
29+
from unittest.mock import Mock
30+
31+
if cupy_run:
32+
from cupyx.scipy.interpolate import interpn
33+
else:
34+
interpn = Mock()
3135

3236
from typing import Literal
3337

@@ -59,17 +63,6 @@ def sino_360_to_180(
5963
cp.ndarray
6064
Output 3D data.
6165
"""
62-
if cupywrapper.cupy_run:
63-
return __sino_360_to_180(data, overlap, rotation)
64-
else:
65-
print("sino_360_to_180 won't be executed because CuPy is not installed")
66-
return data
67-
68-
69-
@nvtx.annotate()
70-
def __sino_360_to_180(
71-
data: cp.ndarray, overlap: int = 0, rotation: Literal["left", "right"] = "left"
72-
) -> cp.ndarray:
7366
if data.ndim != 3:
7467
raise ValueError("only 3D data is supported")
7568

@@ -80,8 +73,8 @@ def __sino_360_to_180(
8073
raise ValueError("overlap must be less than data.shape[2]")
8174
if overlap < 0:
8275
raise ValueError("only positive overlaps are allowed.")
83-
84-
if rotation not in ['left', 'right']:
76+
77+
if rotation not in ["left", "right"]:
8578
raise ValueError('rotation parameter must be either "left" or "right"')
8679

8780
n = dx // 2
@@ -128,18 +121,6 @@ def data_resampler(
128121
Returns:
129122
cp.ndarray: Up/Down-scaled 3D cupy array
130123
"""
131-
if cupywrapper.cupy_run:
132-
return __data_resampler(data, newshape, axis, interpolation)
133-
else:
134-
print("data_resampler won't be executed because CuPy is not installed")
135-
return data
136-
137-
138-
@nvtx.annotate()
139-
def __data_resampler(
140-
data: cp.ndarray, newshape: list, axis: int = 1, interpolation: str = "linear"
141-
) -> cp.ndarray:
142-
143124
if data.ndim != 3:
144125
raise ValueError("only 3D data is supported")
145126

httomolibgpu/misc/rescale.py

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
cp = cupywrapper.cp
2626

27-
nvtx = cupywrapper.nvtx
2827
from typing import Literal, Optional, Tuple, Union
2928

3029
__all__ = [
@@ -70,53 +69,6 @@ def rescale_to_int(
7069
The original data, clipped to the range specified with the perc_range_min and
7170
perc_range_max, and scaled to the full range of the output integer type
7271
"""
73-
if cupywrapper.cupy_run:
74-
return __rescale_to_int(data, perc_range_min, perc_range_max, bits, glob_stats)
75-
else:
76-
print("rescale_to_int won't be executed because CuPy is not installed")
77-
return data
78-
79-
80-
@nvtx.annotate()
81-
def __rescale_to_int(
82-
data: cp.ndarray,
83-
perc_range_min: float = 0.0,
84-
perc_range_max: float = 100.0,
85-
bits: Literal[8, 16, 32] = 8,
86-
glob_stats: Optional[Tuple[float, float, float, int]] = None,
87-
):
88-
"""
89-
Rescales the data and converts it fit into the range of an unsigned integer type
90-
with the given number of bits.
91-
92-
Parameters
93-
----------
94-
data : cp.ndarray
95-
Required input data array, on GPU
96-
perc_range_min: float, optional
97-
The lower cutoff point in the input data, in percent of the data range (defaults to 0).
98-
The lower bound is computed as min + perc_range_min/100*(max-min)
99-
perc_range_max: float, optional
100-
The upper cutoff point in the input data, in percent of the data range (defaults to 100).
101-
The upper bound is computed as min + perc_range_max/100*(max-min)
102-
bits: Literal[8, 16, 32], optional
103-
The number of bits in the output integer range (defaults to 8).
104-
Allowed values are:
105-
- 8 -> uint8
106-
- 16 -> uint16
107-
- 32 -> uint32
108-
glob_stats: tuple, optional
109-
Global statistics of the full dataset (beyond the data passed into this call).
110-
It's a tuple with (min, max, sum, num_items). If not given, the min/max is
111-
computed from the given data.
112-
113-
Returns
114-
-------
115-
cp.ndarray
116-
The original data, clipped to the range specified with the perc_range_min and
117-
perc_range_max, and scaled to the full range of the output integer type
118-
"""
119-
12072
if bits == 8:
12173
output_dtype: Union[type[np.uint8], type[np.uint16], type[np.uint32]] = np.uint8
12274
elif bits == 16:

httomolibgpu/prep/alignment.py

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@
2424
from httomolibgpu import cupywrapper
2525

2626
cp = cupywrapper.cp
27-
nvtx = cupywrapper.nvtx
28-
cupyx = cupywrapper.cupyx
27+
cupy_run = cupywrapper.cupy_run
2928

30-
from cupyx.scipy.ndimage import map_coordinates
29+
from unittest.mock import Mock
30+
31+
if cupy_run:
32+
from cupyx.scipy.ndimage import map_coordinates
33+
else:
34+
map_coordinates = Mock()
3135

3236
from typing import Dict, List
3337

@@ -77,55 +81,6 @@ def distortion_correction_proj_discorpy(
7781
cp.ndarray
7882
3D array. Distortion-corrected array.
7983
"""
80-
if cupywrapper.cupy_run:
81-
return __distortion_correction_proj_discorpy(
82-
data, metadata_path, preview, order, mode
83-
)
84-
else:
85-
print(
86-
"distortion_correction_proj_discorpy won't be executed because CuPy is not installed"
87-
)
88-
return data
89-
90-
91-
@nvtx.annotate()
92-
def __distortion_correction_proj_discorpy(
93-
data: cp.ndarray,
94-
metadata_path: str,
95-
preview: Dict[str, List[int]],
96-
order: int = 1,
97-
mode: str = "reflect",
98-
):
99-
"""Unwarp a stack of images using a backward model.
100-
101-
Parameters
102-
----------
103-
data : cp.ndarray
104-
3D array.
105-
106-
metadata_path : str
107-
The path to the file containing the distortion coefficients for the
108-
data.
109-
110-
preview : Dict[str, List[int]]
111-
A dict containing three key-value pairs:
112-
- a list containing the `start` value of each dimension
113-
- a list containing the `stop` value of each dimension
114-
- a list containing the `step` value of each dimension
115-
116-
order : int, optional.
117-
The order of the spline interpolation.
118-
119-
mode : {'reflect', 'grid-mirror', 'constant', 'grid-constant', 'nearest',
120-
'mirror', 'grid-wrap', 'wrap'}, optional
121-
To determine how to handle image boundaries.
122-
123-
Returns
124-
-------
125-
cp.ndarray
126-
3D array. Distortion-corrected image(s).
127-
"""
128-
12984
# Check if it's a stack of 2D images, or only a single 2D image
13085
if len(data.shape) == 2:
13186
data = cp.expand_dims(data, axis=0)

httomolibgpu/prep/normalize.py

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@
2424
from httomolibgpu import cupywrapper
2525

2626
cp = cupywrapper.cp
27-
nvtx = cupywrapper.nvtx
27+
cupy_run = cupywrapper.cupy_run
2828

29-
from cupy import mean
29+
from unittest.mock import Mock
30+
31+
if cupy_run:
32+
from cupy import mean
33+
else:
34+
mean = Mock()
3035

3136
from numpy import float32
3237
from typing import Tuple
@@ -69,26 +74,6 @@ def normalize(
6974
cp.ndarray
7075
Normalised 3D tomographic data as a CuPy array.
7176
"""
72-
if cupywrapper.cupy_run:
73-
return __normalize(
74-
data, flats, darks, cutoff, minus_log, nonnegativity, remove_nans
75-
)
76-
else:
77-
print("normalize won't be executed because CuPy is not installed")
78-
return data
79-
80-
81-
@nvtx.annotate()
82-
def __normalize(
83-
data: cp.ndarray,
84-
flats: cp.ndarray,
85-
darks: cp.ndarray,
86-
cutoff: float = 10.0,
87-
minus_log: bool = True,
88-
nonnegativity: bool = False,
89-
remove_nans: bool = True,
90-
) -> cp.ndarray:
91-
9277
_check_valid_input(data, flats, darks)
9378

9479
dark0 = cp.empty(darks.shape[1:], dtype=float32)

0 commit comments

Comments
 (0)