oct-to-tiff 0.5.0__py3-none-any.whl → 0.6.0__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.
- oct_to_tiff/cli.py +75 -38
- {oct_to_tiff-0.5.0.dist-info → oct_to_tiff-0.6.0.dist-info}/METADATA +8 -36
- oct_to_tiff-0.6.0.dist-info/RECORD +8 -0
- {oct_to_tiff-0.5.0.dist-info → oct_to_tiff-0.6.0.dist-info}/WHEEL +1 -1
- oct_to_tiff-0.5.0.dist-info/RECORD +0 -8
- {oct_to_tiff-0.5.0.dist-info → oct_to_tiff-0.6.0.dist-info}/entry_points.txt +0 -0
- {oct_to_tiff-0.5.0.dist-info → oct_to_tiff-0.6.0.dist-info/licenses}/LICENSE.txt +0 -0
- {oct_to_tiff-0.5.0.dist-info → oct_to_tiff-0.6.0.dist-info}/top_level.txt +0 -0
oct_to_tiff/cli.py
CHANGED
|
@@ -6,24 +6,25 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
import defusedxml.ElementTree as DET
|
|
8
8
|
import numpy as np
|
|
9
|
+
import numpy.typing as npt
|
|
9
10
|
import tifffile
|
|
10
|
-
from
|
|
11
|
+
from roifile import ROI_TYPE, ImagejRoi, roiwrite
|
|
11
12
|
|
|
12
13
|
logger = logging.getLogger(__name__)
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
def reshape_volume(
|
|
16
|
-
volume: NDArray[Any],
|
|
17
|
+
volume: npt.NDArray[Any],
|
|
17
18
|
frames_per_data_group: int,
|
|
18
19
|
total_data_groups: int,
|
|
19
20
|
oct_window_height: int,
|
|
20
21
|
xy_scan_length: int,
|
|
21
|
-
) -> NDArray[Any]:
|
|
22
|
+
) -> npt.NDArray[Any]:
|
|
22
23
|
"""Reshape a 1-dimensional array to a 3-dimensional array.
|
|
23
24
|
|
|
24
25
|
Parameters
|
|
25
26
|
----------
|
|
26
|
-
volume : NDArray[Any]
|
|
27
|
+
volume : npt.NDArray[Any]
|
|
27
28
|
A 1-dimensional array.
|
|
28
29
|
frames_per_data_group : int
|
|
29
30
|
The number of frames per data group.
|
|
@@ -36,7 +37,7 @@ def reshape_volume(
|
|
|
36
37
|
|
|
37
38
|
Returns
|
|
38
39
|
-------
|
|
39
|
-
volume : NDArray[Any]
|
|
40
|
+
volume : npt.NDArray[Any]
|
|
40
41
|
A 3-dimensional array.
|
|
41
42
|
|
|
42
43
|
"""
|
|
@@ -51,29 +52,9 @@ def reshape_volume(
|
|
|
51
52
|
return volume
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
def rotate_volume(
|
|
55
|
-
volume: NDArray[Any],
|
|
56
|
-
) -> NDArray[Any]:
|
|
57
|
-
"""Rotate a 3-dimensional array 90 degrees left (anti-clockwise) about the z-axis.
|
|
58
|
-
|
|
59
|
-
Parameters
|
|
60
|
-
----------
|
|
61
|
-
volume : NDArray[Any]
|
|
62
|
-
A 3-dimensional array.
|
|
63
|
-
|
|
64
|
-
Returns
|
|
65
|
-
-------
|
|
66
|
-
volume : NDArray[Any]
|
|
67
|
-
A rotated version of the input volume.
|
|
68
|
-
|
|
69
|
-
"""
|
|
70
|
-
volume = np.rot90(volume, k=1, axes=(1, 2))
|
|
71
|
-
return volume
|
|
72
|
-
|
|
73
|
-
|
|
74
55
|
def write_volume(
|
|
75
56
|
output_path: Path,
|
|
76
|
-
volume: NDArray[Any],
|
|
57
|
+
volume: npt.NDArray[Any],
|
|
77
58
|
pixel_size_x: float,
|
|
78
59
|
pixel_size_y: float,
|
|
79
60
|
pixel_size_z: float,
|
|
@@ -84,7 +65,7 @@ def write_volume(
|
|
|
84
65
|
----------
|
|
85
66
|
output_path : Path
|
|
86
67
|
The specified output path.
|
|
87
|
-
volume : NDArray[Any]
|
|
68
|
+
volume : npt.NDArray[Any]
|
|
88
69
|
A 3-dimensional array.
|
|
89
70
|
pixel_size_x : float
|
|
90
71
|
The pixel (voxel) width in mm.
|
|
@@ -110,7 +91,7 @@ def write_volume(
|
|
|
110
91
|
)
|
|
111
92
|
|
|
112
93
|
|
|
113
|
-
def
|
|
94
|
+
def boundaries_to_arrays(input_path: str | Path) -> list[npt.NDArray[np.int_]]:
|
|
114
95
|
"""Extract segmentation lines.
|
|
115
96
|
|
|
116
97
|
Parameters
|
|
@@ -118,6 +99,10 @@ def extract_boundaries(input_path: str | Path) -> None:
|
|
|
118
99
|
input_path : str | Path
|
|
119
100
|
The specified input path.
|
|
120
101
|
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
arrays : list[npt.NDArray[np.int_]]
|
|
105
|
+
A list of 2-dimensional arrays.
|
|
121
106
|
"""
|
|
122
107
|
input_path = Path(input_path)
|
|
123
108
|
tree = DET.parse(input_path)
|
|
@@ -128,14 +113,36 @@ def extract_boundaries(input_path: str | Path) -> None:
|
|
|
128
113
|
int(point.text) if point.text else 0
|
|
129
114
|
for point in root.findall("./Curve_Set/Image/Curve/D")
|
|
130
115
|
]
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
116
|
+
num_arrays = len(data_points) // array_size
|
|
117
|
+
|
|
118
|
+
arrays = []
|
|
119
|
+
for i in range(num_arrays):
|
|
134
120
|
start = i * array_size
|
|
135
121
|
end = start + array_size
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
122
|
+
array = np.column_stack([np.arange(array_size), data_points[start:end]])
|
|
123
|
+
arrays.append(array)
|
|
124
|
+
|
|
125
|
+
return arrays
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def arrays_to_rois(arrays: list[npt.NDArray[np.int_]], output_path: Path) -> None:
|
|
129
|
+
"""
|
|
130
|
+
Convert a list of 2-dimensional arrays to ImageJ ROIs (ZIP file).
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
arrays : list[npt.NDArray[np.int_]]
|
|
135
|
+
A list of 2-dimensional arrays.
|
|
136
|
+
output_path : Path
|
|
137
|
+
The specified output path.
|
|
138
|
+
"""
|
|
139
|
+
rois = []
|
|
140
|
+
for array in arrays:
|
|
141
|
+
roi = ImagejRoi.frompoints(array)
|
|
142
|
+
roi.roitype = ROI_TYPE(4) # FREELINE
|
|
143
|
+
rois.append(roi)
|
|
144
|
+
|
|
145
|
+
roiwrite(output_path, rois, mode="w")
|
|
139
146
|
|
|
140
147
|
|
|
141
148
|
def main() -> None:
|
|
@@ -202,18 +209,22 @@ def main() -> None:
|
|
|
202
209
|
else:
|
|
203
210
|
dir_name = input_path.parent
|
|
204
211
|
file_name = input_path.stem
|
|
205
|
-
|
|
212
|
+
if args.boundaries:
|
|
213
|
+
file_extension = "_rois.zip"
|
|
214
|
+
else:
|
|
215
|
+
file_extension = ".ome.tif"
|
|
206
216
|
output_path = dir_name / (file_name + file_extension)
|
|
207
217
|
|
|
208
218
|
if Path.is_file(output_path):
|
|
209
219
|
if args.overwrite:
|
|
210
|
-
|
|
220
|
+
logger.warning(f"Overwriting {output_path}")
|
|
211
221
|
else:
|
|
212
222
|
logger.error(f"{output_path} already exists.")
|
|
213
223
|
return
|
|
214
224
|
|
|
215
225
|
if args.boundaries:
|
|
216
|
-
|
|
226
|
+
arrays = boundaries_to_arrays(input_path)
|
|
227
|
+
arrays_to_rois(arrays, output_path)
|
|
217
228
|
return
|
|
218
229
|
|
|
219
230
|
with open(input_path, "rb") as f:
|
|
@@ -257,6 +268,32 @@ def main() -> None:
|
|
|
257
268
|
pixel_size_x = 0.007797
|
|
258
269
|
pixel_size_y = 0.003071
|
|
259
270
|
pixel_size_z = 0.040000
|
|
271
|
+
|
|
272
|
+
volume = reshape_volume(
|
|
273
|
+
volume,
|
|
274
|
+
frames_per_data_group,
|
|
275
|
+
total_data_groups,
|
|
276
|
+
oct_window_height,
|
|
277
|
+
xy_scan_length,
|
|
278
|
+
)
|
|
279
|
+
volume = np.rot90(volume, k=1, axes=(1, 2))
|
|
280
|
+
volume_main = volume[:101]
|
|
281
|
+
volume_align = volume[101:frames_per_data_group]
|
|
282
|
+
align_path = dir_name / (file_name + "_Align.ome.tif")
|
|
283
|
+
pixel_size_x_align = 0.003899
|
|
284
|
+
pixel_size_y_align = 0.003071
|
|
285
|
+
pixel_size_z_align = 0.040000
|
|
286
|
+
write_volume(
|
|
287
|
+
output_path, volume_main, pixel_size_x, pixel_size_y, pixel_size_z
|
|
288
|
+
)
|
|
289
|
+
write_volume(
|
|
290
|
+
align_path,
|
|
291
|
+
volume_align,
|
|
292
|
+
pixel_size_x_align,
|
|
293
|
+
pixel_size_y_align,
|
|
294
|
+
pixel_size_z_align,
|
|
295
|
+
)
|
|
296
|
+
return
|
|
260
297
|
elif "3D Disc" in file_name:
|
|
261
298
|
volume = np.frombuffer(f.read(), dtype=np.single)
|
|
262
299
|
frames_per_data_group = 106
|
|
@@ -465,7 +502,7 @@ def main() -> None:
|
|
|
465
502
|
)
|
|
466
503
|
|
|
467
504
|
if not args.en_face and not args.seg_curve:
|
|
468
|
-
volume =
|
|
505
|
+
volume = np.rot90(volume, k=1, axes=(1, 2))
|
|
469
506
|
|
|
470
507
|
write_volume(output_path, volume, pixel_size_x, pixel_size_y, pixel_size_z)
|
|
471
508
|
|
|
@@ -1,63 +1,35 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: oct-to-tiff
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: A command line tool for converting optical coherence tomography angiography (OCTA) data.
|
|
5
5
|
Author-email: Cameron Lloyd <lloyd@med.unideb.hu>
|
|
6
6
|
Maintainer-email: Cameron Lloyd <lloyd@med.unideb.hu>
|
|
7
|
-
License: BSD
|
|
8
|
-
|
|
9
|
-
Copyright (c) 2021, Cameron Lloyd
|
|
10
|
-
All rights reserved.
|
|
11
|
-
|
|
12
|
-
Redistribution and use in source and binary forms, with or without
|
|
13
|
-
modification, are permitted provided that the following conditions are met:
|
|
14
|
-
|
|
15
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
16
|
-
list of conditions and the following disclaimer.
|
|
17
|
-
|
|
18
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
19
|
-
this list of conditions and the following disclaimer in the documentation
|
|
20
|
-
and/or other materials provided with the distribution.
|
|
21
|
-
|
|
22
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
23
|
-
contributors may be used to endorse or promote products derived from
|
|
24
|
-
this software without specific prior written permission.
|
|
25
|
-
|
|
26
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
27
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
28
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
29
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
30
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
31
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
32
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
33
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
34
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
35
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
36
|
-
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
37
8
|
Project-URL: Homepage, https://github.com/camlloyd/oct-to-tiff
|
|
38
9
|
Project-URL: Bug Tracker, https://github.com/camlloyd/oct-to-tiff/issues
|
|
39
10
|
Project-URL: Changelog, https://github.com/camlloyd/oct-to-tiff/blob/main/CHANGELOG.md
|
|
40
11
|
Keywords: angiography,cli,oct,octa
|
|
41
12
|
Classifier: Development Status :: 3 - Alpha
|
|
42
13
|
Classifier: Intended Audience :: Science/Research
|
|
43
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
44
14
|
Classifier: Natural Language :: English
|
|
45
15
|
Classifier: Operating System :: OS Independent
|
|
46
16
|
Classifier: Programming Language :: Python :: 3
|
|
47
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
48
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
49
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
50
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
51
|
-
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Requires-Python: >=3.11
|
|
52
22
|
Description-Content-Type: text/markdown
|
|
53
23
|
License-File: LICENSE.txt
|
|
54
24
|
Requires-Dist: defusedxml
|
|
55
25
|
Requires-Dist: numpy
|
|
26
|
+
Requires-Dist: roifile
|
|
56
27
|
Requires-Dist: tifffile
|
|
57
28
|
Provides-Extra: dev
|
|
58
29
|
Requires-Dist: mypy; extra == "dev"
|
|
59
30
|
Requires-Dist: ruff; extra == "dev"
|
|
60
31
|
Requires-Dist: types-defusedxml; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
61
33
|
|
|
62
34
|
# oct-to-tiff
|
|
63
35
|
|
|
@@ -214,4 +186,4 @@ This project uses [Ruff](https://github.com/astral-sh/ruff) for linting and form
|
|
|
214
186
|
|
|
215
187
|
## Requirements
|
|
216
188
|
|
|
217
|
-
Requires Python 3.
|
|
189
|
+
Requires Python 3.11 or higher.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
oct_to_tiff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
oct_to_tiff/cli.py,sha256=GmIMXLuNfAEZaijX2_93XB95V0Mdr1yb73Q_j8eBiEI,17232
|
|
3
|
+
oct_to_tiff-0.6.0.dist-info/licenses/LICENSE.txt,sha256=8KO0dluzLStmIF0HM18BOP9T2miIcX8q-GOfMOw6Ngk,1521
|
|
4
|
+
oct_to_tiff-0.6.0.dist-info/METADATA,sha256=7atS8U7OhVhVpU48NjbGzqMtbGhlA_l4Dh6jZUiu010,4913
|
|
5
|
+
oct_to_tiff-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
+
oct_to_tiff-0.6.0.dist-info/entry_points.txt,sha256=mKWNdkTThZm2JKtLwp4PGMpXkvAWk-xnQDAOyRsCo9Y,53
|
|
7
|
+
oct_to_tiff-0.6.0.dist-info/top_level.txt,sha256=_ovqm7f48yb_IAiVqWzB3VPnHXwzkkEqQQ_ZJz_McSY,12
|
|
8
|
+
oct_to_tiff-0.6.0.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
oct_to_tiff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
oct_to_tiff/cli.py,sha256=tHRUNBff0TTTtc0pnecF_t5mLWyoGG0kNKNVopyL4Sw,15934
|
|
3
|
-
oct_to_tiff-0.5.0.dist-info/LICENSE.txt,sha256=8KO0dluzLStmIF0HM18BOP9T2miIcX8q-GOfMOw6Ngk,1521
|
|
4
|
-
oct_to_tiff-0.5.0.dist-info/METADATA,sha256=8-nIJ6Pg_vvfxovcjIHgax-D1nMQaWYZ_9cJLT7lq2g,6649
|
|
5
|
-
oct_to_tiff-0.5.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
6
|
-
oct_to_tiff-0.5.0.dist-info/entry_points.txt,sha256=mKWNdkTThZm2JKtLwp4PGMpXkvAWk-xnQDAOyRsCo9Y,53
|
|
7
|
-
oct_to_tiff-0.5.0.dist-info/top_level.txt,sha256=_ovqm7f48yb_IAiVqWzB3VPnHXwzkkEqQQ_ZJz_McSY,12
|
|
8
|
-
oct_to_tiff-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|