roifile 2024.5.24__tar.gz → 2025.2.20__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.
Potentially problematic release.
This version of roifile might be problematic. Click here for more details.
- {roifile-2024.5.24 → roifile-2025.2.20}/CHANGES.rst +10 -1
- {roifile-2024.5.24 → roifile-2025.2.20}/LICENSE +1 -1
- {roifile-2024.5.24/roifile.egg-info → roifile-2025.2.20}/PKG-INFO +59 -10
- {roifile-2024.5.24 → roifile-2025.2.20}/README.rst +51 -7
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile/roifile.py +86 -24
- {roifile-2024.5.24 → roifile-2025.2.20/roifile.egg-info}/PKG-INFO +59 -10
- {roifile-2024.5.24 → roifile-2025.2.20}/setup.py +4 -4
- {roifile-2024.5.24 → roifile-2025.2.20}/MANIFEST.in +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile/__init__.py +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile/__main__.py +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile/py.typed +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile.egg-info/SOURCES.txt +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile.egg-info/dependency_links.txt +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile.egg-info/entry_points.txt +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile.egg-info/requires.txt +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile.egg-info/top_level.txt +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/roifile_demo.py +0 -0
- {roifile-2024.5.24 → roifile-2025.2.20}/setup.cfg +0 -0
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
Revisions
|
|
2
2
|
---------
|
|
3
3
|
|
|
4
|
+
2025.2.20
|
|
5
|
+
|
|
6
|
+
- Drop support for Python 3.9.
|
|
7
|
+
|
|
8
|
+
2024.9.15
|
|
9
|
+
|
|
10
|
+
- Improve typing.
|
|
11
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
12
|
+
|
|
4
13
|
2024.5.24
|
|
5
14
|
|
|
6
|
-
- Fix
|
|
15
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
7
16
|
|
|
8
17
|
2024.3.20
|
|
9
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: roifile
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2025.2.20
|
|
4
4
|
Summary: Read and write ImageJ ROI format
|
|
5
5
|
Home-page: https://www.cgohlke.com
|
|
6
6
|
Author: Christoph Gohlke
|
|
@@ -15,17 +15,30 @@ Classifier: Intended Audience :: Science/Research
|
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/x-rst
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: numpy
|
|
26
26
|
Provides-Extra: all
|
|
27
27
|
Requires-Dist: matplotlib; extra == "all"
|
|
28
28
|
Requires-Dist: tifffile; extra == "all"
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: platform
|
|
37
|
+
Dynamic: project-url
|
|
38
|
+
Dynamic: provides-extra
|
|
39
|
+
Dynamic: requires-dist
|
|
40
|
+
Dynamic: requires-python
|
|
41
|
+
Dynamic: summary
|
|
29
42
|
|
|
30
43
|
Read and write ImageJ ROI format
|
|
31
44
|
================================
|
|
@@ -38,7 +51,7 @@ interest, geometric shapes, paths, text, and whatnot for image overlays.
|
|
|
38
51
|
|
|
39
52
|
:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
|
|
40
53
|
:License: BSD 3-Clause
|
|
41
|
-
:Version:
|
|
54
|
+
:Version: 2025.2.20
|
|
42
55
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
43
56
|
|
|
44
57
|
Quickstart
|
|
@@ -64,17 +77,26 @@ Requirements
|
|
|
64
77
|
This revision was tested with the following requirements and dependencies
|
|
65
78
|
(other versions may work):
|
|
66
79
|
|
|
67
|
-
- `CPython <https://www.python.org>`_ 3.
|
|
68
|
-
- `
|
|
69
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_
|
|
70
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
80
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.9, 3.13.2 64-bit
|
|
81
|
+
- `NumPy <https://pypi.org/project/numpy/>`_ 2.2.3
|
|
82
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2025.2.18 (optional)
|
|
83
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.10.0 (optional)
|
|
71
84
|
|
|
72
85
|
Revisions
|
|
73
86
|
---------
|
|
74
87
|
|
|
88
|
+
2025.2.20
|
|
89
|
+
|
|
90
|
+
- Drop support for Python 3.9.
|
|
91
|
+
|
|
92
|
+
2024.9.15
|
|
93
|
+
|
|
94
|
+
- Improve typing.
|
|
95
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
96
|
+
|
|
75
97
|
2024.5.24
|
|
76
98
|
|
|
77
|
-
- Fix
|
|
99
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
78
100
|
|
|
79
101
|
2024.3.20
|
|
80
102
|
|
|
@@ -160,11 +182,38 @@ array([[1.1, 2.2],
|
|
|
160
182
|
[5.5, 6.6]], dtype=float32)
|
|
161
183
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
162
184
|
(1, 2, 7, 8)
|
|
185
|
+
>>> roi2.name = 'test'
|
|
163
186
|
|
|
164
187
|
Plot the ROI using matplotlib:
|
|
165
188
|
|
|
166
189
|
>>> roi.plot()
|
|
167
190
|
|
|
191
|
+
Write the ROIs to a ZIP file:
|
|
192
|
+
|
|
193
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
194
|
+
|
|
195
|
+
Read the ROIs from the ZIP file:
|
|
196
|
+
|
|
197
|
+
>>> rois = roiread('_test.zip')
|
|
198
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
199
|
+
|
|
200
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
201
|
+
|
|
202
|
+
>>> import tifffile
|
|
203
|
+
>>> tifffile.imwrite(
|
|
204
|
+
... '_test.tif',
|
|
205
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
206
|
+
... imagej=True,
|
|
207
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
208
|
+
... )
|
|
209
|
+
|
|
210
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
211
|
+
|
|
212
|
+
>>> rois = roiread('_test.tif')
|
|
213
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
214
|
+
|
|
168
215
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
169
216
|
|
|
170
217
|
python -m roifile _test.roi
|
|
218
|
+
|
|
219
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
@@ -12,7 +12,7 @@ interest, geometric shapes, paths, text, and whatnot for image overlays.
|
|
|
12
12
|
|
|
13
13
|
:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
|
|
14
14
|
:License: BSD 3-Clause
|
|
15
|
-
:Version:
|
|
15
|
+
:Version: 2025.2.20
|
|
16
16
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
17
17
|
|
|
18
18
|
Quickstart
|
|
@@ -38,17 +38,26 @@ Requirements
|
|
|
38
38
|
This revision was tested with the following requirements and dependencies
|
|
39
39
|
(other versions may work):
|
|
40
40
|
|
|
41
|
-
- `CPython <https://www.python.org>`_ 3.
|
|
42
|
-
- `
|
|
43
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_
|
|
44
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
41
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.9, 3.13.2 64-bit
|
|
42
|
+
- `NumPy <https://pypi.org/project/numpy/>`_ 2.2.3
|
|
43
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2025.2.18 (optional)
|
|
44
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.10.0 (optional)
|
|
45
45
|
|
|
46
46
|
Revisions
|
|
47
47
|
---------
|
|
48
48
|
|
|
49
|
+
2025.2.20
|
|
50
|
+
|
|
51
|
+
- Drop support for Python 3.9.
|
|
52
|
+
|
|
53
|
+
2024.9.15
|
|
54
|
+
|
|
55
|
+
- Improve typing.
|
|
56
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
57
|
+
|
|
49
58
|
2024.5.24
|
|
50
59
|
|
|
51
|
-
- Fix
|
|
60
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
52
61
|
|
|
53
62
|
2024.3.20
|
|
54
63
|
|
|
@@ -140,6 +149,7 @@ Read the ImageJ ROI from the file and verify the content:
|
|
|
140
149
|
[5.5, 6.6]], dtype=float32)
|
|
141
150
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
142
151
|
(1, 2, 7, 8)
|
|
152
|
+
>>> roi2.name = 'test'
|
|
143
153
|
|
|
144
154
|
Plot the ROI using matplotlib:
|
|
145
155
|
|
|
@@ -147,6 +157,40 @@ Plot the ROI using matplotlib:
|
|
|
147
157
|
|
|
148
158
|
>>> roi.plot()
|
|
149
159
|
|
|
160
|
+
Write the ROIs to a ZIP file:
|
|
161
|
+
|
|
162
|
+
.. code-block:: python
|
|
163
|
+
|
|
164
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
165
|
+
|
|
166
|
+
Read the ROIs from the ZIP file:
|
|
167
|
+
|
|
168
|
+
.. code-block:: python
|
|
169
|
+
|
|
170
|
+
>>> rois = roiread('_test.zip')
|
|
171
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
172
|
+
|
|
173
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
174
|
+
|
|
175
|
+
.. code-block:: python
|
|
176
|
+
|
|
177
|
+
>>> import tifffile
|
|
178
|
+
>>> tifffile.imwrite(
|
|
179
|
+
... '_test.tif',
|
|
180
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
181
|
+
... imagej=True,
|
|
182
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
183
|
+
... )
|
|
184
|
+
|
|
185
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
186
|
+
|
|
187
|
+
.. code-block:: python
|
|
188
|
+
|
|
189
|
+
>>> rois = roiread('_test.tif')
|
|
190
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
191
|
+
|
|
150
192
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
151
193
|
|
|
152
|
-
python -m roifile _test.roi
|
|
194
|
+
python -m roifile _test.roi
|
|
195
|
+
|
|
196
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# roifile.py
|
|
2
2
|
|
|
3
|
-
# Copyright (c) 2020-
|
|
3
|
+
# Copyright (c) 2020-2025, Christoph Gohlke
|
|
4
4
|
# All rights reserved.
|
|
5
5
|
#
|
|
6
6
|
# Redistribution and use in source and binary forms, with or without
|
|
@@ -39,7 +39,7 @@ interest, geometric shapes, paths, text, and whatnot for image overlays.
|
|
|
39
39
|
|
|
40
40
|
:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
|
|
41
41
|
:License: BSD 3-Clause
|
|
42
|
-
:Version:
|
|
42
|
+
:Version: 2025.2.20
|
|
43
43
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
44
44
|
|
|
45
45
|
Quickstart
|
|
@@ -65,17 +65,26 @@ Requirements
|
|
|
65
65
|
This revision was tested with the following requirements and dependencies
|
|
66
66
|
(other versions may work):
|
|
67
67
|
|
|
68
|
-
- `CPython <https://www.python.org>`_ 3.
|
|
69
|
-
- `
|
|
70
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_
|
|
71
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
68
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.9, 3.13.2 64-bit
|
|
69
|
+
- `NumPy <https://pypi.org/project/numpy/>`_ 2.2.3
|
|
70
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2025.2.18 (optional)
|
|
71
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.10.0 (optional)
|
|
72
72
|
|
|
73
73
|
Revisions
|
|
74
74
|
---------
|
|
75
75
|
|
|
76
|
+
2025.2.20
|
|
77
|
+
|
|
78
|
+
- Drop support for Python 3.9.
|
|
79
|
+
|
|
80
|
+
2024.9.15
|
|
81
|
+
|
|
82
|
+
- Improve typing.
|
|
83
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
84
|
+
|
|
76
85
|
2024.5.24
|
|
77
86
|
|
|
78
|
-
- Fix
|
|
87
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
79
88
|
|
|
80
89
|
2024.3.20
|
|
81
90
|
|
|
@@ -161,22 +170,50 @@ array([[1.1, 2.2],
|
|
|
161
170
|
[5.5, 6.6]], dtype=float32)
|
|
162
171
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
163
172
|
(1, 2, 7, 8)
|
|
173
|
+
>>> roi2.name = 'test'
|
|
164
174
|
|
|
165
175
|
Plot the ROI using matplotlib:
|
|
166
176
|
|
|
167
177
|
>>> roi.plot()
|
|
168
178
|
|
|
179
|
+
Write the ROIs to a ZIP file:
|
|
180
|
+
|
|
181
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
182
|
+
|
|
183
|
+
Read the ROIs from the ZIP file:
|
|
184
|
+
|
|
185
|
+
>>> rois = roiread('_test.zip')
|
|
186
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
187
|
+
|
|
188
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
189
|
+
|
|
190
|
+
>>> import tifffile
|
|
191
|
+
>>> tifffile.imwrite(
|
|
192
|
+
... '_test.tif',
|
|
193
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
194
|
+
... imagej=True,
|
|
195
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
196
|
+
... )
|
|
197
|
+
|
|
198
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
199
|
+
|
|
200
|
+
>>> rois = roiread('_test.tif')
|
|
201
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
202
|
+
|
|
169
203
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
170
204
|
|
|
171
205
|
python -m roifile _test.roi
|
|
172
206
|
|
|
207
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
208
|
+
|
|
173
209
|
"""
|
|
174
210
|
|
|
175
211
|
from __future__ import annotations
|
|
176
212
|
|
|
177
|
-
__version__ = '
|
|
213
|
+
__version__ = '2025.2.20'
|
|
178
214
|
|
|
179
215
|
__all__ = [
|
|
216
|
+
'__version__',
|
|
180
217
|
'roiread',
|
|
181
218
|
'roiwrite',
|
|
182
219
|
'ImagejRoi',
|
|
@@ -200,9 +237,10 @@ from typing import TYPE_CHECKING
|
|
|
200
237
|
import numpy
|
|
201
238
|
|
|
202
239
|
if TYPE_CHECKING:
|
|
203
|
-
from collections.abc import Iterable
|
|
240
|
+
from collections.abc import Iterable, Iterator
|
|
204
241
|
from typing import Any, Literal
|
|
205
242
|
|
|
243
|
+
from matplotlib.axes import Axes
|
|
206
244
|
from numpy.typing import ArrayLike, NDArray
|
|
207
245
|
|
|
208
246
|
|
|
@@ -253,6 +291,7 @@ def roiwrite(
|
|
|
253
291
|
|
|
254
292
|
import zipfile
|
|
255
293
|
|
|
294
|
+
assert mode is not None
|
|
256
295
|
with zipfile.ZipFile(filename, mode) as zf:
|
|
257
296
|
for r in roi:
|
|
258
297
|
if name is None:
|
|
@@ -717,6 +756,7 @@ class ImagejRoi:
|
|
|
717
756
|
mode = 'a' if os.path.exists(filename) else 'w'
|
|
718
757
|
import zipfile
|
|
719
758
|
|
|
759
|
+
assert mode is not None
|
|
720
760
|
with zipfile.ZipFile(filename, mode) as zf:
|
|
721
761
|
with zf.open(name, 'w') as fh:
|
|
722
762
|
fh.write(self.tobytes())
|
|
@@ -892,15 +932,16 @@ class ImagejRoi:
|
|
|
892
932
|
|
|
893
933
|
def plot(
|
|
894
934
|
self,
|
|
895
|
-
ax:
|
|
935
|
+
ax: Axes | None = None,
|
|
896
936
|
*,
|
|
897
937
|
rois: Iterable[ImagejRoi] | None = None,
|
|
898
938
|
title: str | None = None,
|
|
899
939
|
bounds: bool = False,
|
|
900
940
|
invert_yaxis: bool | None = None,
|
|
901
|
-
**kwargs,
|
|
941
|
+
**kwargs: Any,
|
|
902
942
|
) -> None:
|
|
903
943
|
"""Plot a draft of coordinates using matplotlib."""
|
|
944
|
+
fig: Any
|
|
904
945
|
roitype = self.roitype
|
|
905
946
|
subtype = self.subtype
|
|
906
947
|
|
|
@@ -942,8 +983,6 @@ class ImagejRoi:
|
|
|
942
983
|
pyplot.show()
|
|
943
984
|
return
|
|
944
985
|
|
|
945
|
-
if kwargs is None:
|
|
946
|
-
kwargs = {}
|
|
947
986
|
if 'color' not in kwargs and 'c' not in kwargs:
|
|
948
987
|
kwargs['color'] = self.hexcolor(self.stroke_color)
|
|
949
988
|
if 'linewidth' not in kwargs and 'lw' not in kwargs:
|
|
@@ -974,7 +1013,8 @@ class ImagejRoi:
|
|
|
974
1013
|
if 'fontsize' not in kwargs and self.text_size > 0:
|
|
975
1014
|
kwargs['fontsize'] = self.text_size
|
|
976
1015
|
text = ax.text(
|
|
977
|
-
|
|
1016
|
+
coords[1][0],
|
|
1017
|
+
coords[1][1],
|
|
978
1018
|
self.text,
|
|
979
1019
|
va='center_baseline',
|
|
980
1020
|
rotation=self.text_angle,
|
|
@@ -1063,9 +1103,11 @@ class ImagejRoi:
|
|
|
1063
1103
|
multi_coordinates: NDArray[numpy.float32], /
|
|
1064
1104
|
) -> list[NDArray[numpy.float32]]:
|
|
1065
1105
|
"""Return list of coordinate arrays from 2D geometric path."""
|
|
1066
|
-
coordinates = []
|
|
1106
|
+
coordinates: list[NDArray[numpy.float32]] = []
|
|
1067
1107
|
points: list[list[float]] = []
|
|
1068
|
-
path: list[float] =
|
|
1108
|
+
path: list[float] = []
|
|
1109
|
+
|
|
1110
|
+
path = multi_coordinates.tolist() # type: ignore[assignment]
|
|
1069
1111
|
n = 0
|
|
1070
1112
|
m = 0
|
|
1071
1113
|
while n < len(path):
|
|
@@ -1180,17 +1222,37 @@ class ImagejRoi:
|
|
|
1180
1222
|
return indent(*info, end='\n)')
|
|
1181
1223
|
|
|
1182
1224
|
|
|
1183
|
-
def scale_text(
|
|
1225
|
+
def scale_text(
|
|
1226
|
+
text: Any,
|
|
1227
|
+
width: float,
|
|
1228
|
+
*,
|
|
1229
|
+
offset: tuple[float, float] | None = None,
|
|
1230
|
+
) -> None:
|
|
1184
1231
|
"""Scale matplotlib text to width in data coordinates."""
|
|
1185
1232
|
from matplotlib.patheffects import AbstractPathEffect
|
|
1186
1233
|
from matplotlib.transforms import Bbox
|
|
1187
1234
|
|
|
1188
1235
|
class TextScaler(AbstractPathEffect):
|
|
1189
|
-
def __init__(
|
|
1236
|
+
def __init__(
|
|
1237
|
+
self,
|
|
1238
|
+
text: Any,
|
|
1239
|
+
width: float,
|
|
1240
|
+
offset: tuple[float, float] | None = None,
|
|
1241
|
+
) -> None:
|
|
1242
|
+
if offset is None:
|
|
1243
|
+
offset = (0.0, 0.0)
|
|
1244
|
+
super().__init__(offset)
|
|
1190
1245
|
self._text = text
|
|
1191
1246
|
self._width = width
|
|
1192
1247
|
|
|
1193
|
-
def draw_path(
|
|
1248
|
+
def draw_path(
|
|
1249
|
+
self,
|
|
1250
|
+
renderer: Any,
|
|
1251
|
+
gc: Any,
|
|
1252
|
+
tpath: Any,
|
|
1253
|
+
affine: Any,
|
|
1254
|
+
rgbFace: Any = None,
|
|
1255
|
+
) -> None:
|
|
1194
1256
|
ax = self._text.axes
|
|
1195
1257
|
renderer = ax.get_figure().canvas.get_renderer()
|
|
1196
1258
|
bbox = text.get_window_extent(renderer=renderer)
|
|
@@ -1200,7 +1262,7 @@ def scale_text(text: Any, width: float) -> None:
|
|
|
1200
1262
|
affine = affine.from_values(scale, 0, 0, scale, 0, 0) + affine
|
|
1201
1263
|
renderer.draw_path(gc, tpath, affine, rgbFace)
|
|
1202
1264
|
|
|
1203
|
-
text.set_path_effects([TextScaler(text, width)])
|
|
1265
|
+
text.set_path_effects([TextScaler(text, width, offset)])
|
|
1204
1266
|
|
|
1205
1267
|
|
|
1206
1268
|
def oval(rect: ArrayLike, /, points: int = 33) -> NDArray[numpy.float32]:
|
|
@@ -1215,9 +1277,9 @@ def oval(rect: ArrayLike, /, points: int = 33) -> NDArray[numpy.float32]:
|
|
|
1215
1277
|
return c
|
|
1216
1278
|
|
|
1217
1279
|
|
|
1218
|
-
def indent(*args: Any, sep='', end='') -> str:
|
|
1280
|
+
def indent(*args: Any, sep: str = '', end: str = '') -> str:
|
|
1219
1281
|
"""Return joined string representations of objects with indented lines."""
|
|
1220
|
-
text = (sep + '\n').join(
|
|
1282
|
+
text: str = (sep + '\n').join(
|
|
1221
1283
|
arg if isinstance(arg, str) else repr(arg) for arg in args
|
|
1222
1284
|
)
|
|
1223
1285
|
return (
|
|
@@ -1256,7 +1318,7 @@ def logger() -> logging.Logger:
|
|
|
1256
1318
|
def test(verbose: bool = False) -> None:
|
|
1257
1319
|
"""Test roifile.ImagejRoi class."""
|
|
1258
1320
|
# test ROIs from a ZIP file
|
|
1259
|
-
rois = ImagejRoi.fromfile('tests/ijzip.zip')
|
|
1321
|
+
rois: Any = ImagejRoi.fromfile('tests/ijzip.zip')
|
|
1260
1322
|
assert isinstance(rois, list)
|
|
1261
1323
|
assert len(rois) == 7
|
|
1262
1324
|
for roi in rois:
|
|
@@ -1272,7 +1334,7 @@ def test(verbose: bool = False) -> None:
|
|
|
1272
1334
|
except OSError:
|
|
1273
1335
|
pass
|
|
1274
1336
|
|
|
1275
|
-
def roi_iter():
|
|
1337
|
+
def roi_iter() -> Iterator[ImagejRoi]:
|
|
1276
1338
|
# issue #9
|
|
1277
1339
|
yield from rois
|
|
1278
1340
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: roifile
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2025.2.20
|
|
4
4
|
Summary: Read and write ImageJ ROI format
|
|
5
5
|
Home-page: https://www.cgohlke.com
|
|
6
6
|
Author: Christoph Gohlke
|
|
@@ -15,17 +15,30 @@ Classifier: Intended Audience :: Science/Research
|
|
|
15
15
|
Classifier: Intended Audience :: Developers
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
-
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
23
|
Description-Content-Type: text/x-rst
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: numpy
|
|
26
26
|
Provides-Extra: all
|
|
27
27
|
Requires-Dist: matplotlib; extra == "all"
|
|
28
28
|
Requires-Dist: tifffile; extra == "all"
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: platform
|
|
37
|
+
Dynamic: project-url
|
|
38
|
+
Dynamic: provides-extra
|
|
39
|
+
Dynamic: requires-dist
|
|
40
|
+
Dynamic: requires-python
|
|
41
|
+
Dynamic: summary
|
|
29
42
|
|
|
30
43
|
Read and write ImageJ ROI format
|
|
31
44
|
================================
|
|
@@ -38,7 +51,7 @@ interest, geometric shapes, paths, text, and whatnot for image overlays.
|
|
|
38
51
|
|
|
39
52
|
:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
|
|
40
53
|
:License: BSD 3-Clause
|
|
41
|
-
:Version:
|
|
54
|
+
:Version: 2025.2.20
|
|
42
55
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
43
56
|
|
|
44
57
|
Quickstart
|
|
@@ -64,17 +77,26 @@ Requirements
|
|
|
64
77
|
This revision was tested with the following requirements and dependencies
|
|
65
78
|
(other versions may work):
|
|
66
79
|
|
|
67
|
-
- `CPython <https://www.python.org>`_ 3.
|
|
68
|
-
- `
|
|
69
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_
|
|
70
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
80
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.9, 3.13.2 64-bit
|
|
81
|
+
- `NumPy <https://pypi.org/project/numpy/>`_ 2.2.3
|
|
82
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2025.2.18 (optional)
|
|
83
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.10.0 (optional)
|
|
71
84
|
|
|
72
85
|
Revisions
|
|
73
86
|
---------
|
|
74
87
|
|
|
88
|
+
2025.2.20
|
|
89
|
+
|
|
90
|
+
- Drop support for Python 3.9.
|
|
91
|
+
|
|
92
|
+
2024.9.15
|
|
93
|
+
|
|
94
|
+
- Improve typing.
|
|
95
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
96
|
+
|
|
75
97
|
2024.5.24
|
|
76
98
|
|
|
77
|
-
- Fix
|
|
99
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
78
100
|
|
|
79
101
|
2024.3.20
|
|
80
102
|
|
|
@@ -160,11 +182,38 @@ array([[1.1, 2.2],
|
|
|
160
182
|
[5.5, 6.6]], dtype=float32)
|
|
161
183
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
162
184
|
(1, 2, 7, 8)
|
|
185
|
+
>>> roi2.name = 'test'
|
|
163
186
|
|
|
164
187
|
Plot the ROI using matplotlib:
|
|
165
188
|
|
|
166
189
|
>>> roi.plot()
|
|
167
190
|
|
|
191
|
+
Write the ROIs to a ZIP file:
|
|
192
|
+
|
|
193
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
194
|
+
|
|
195
|
+
Read the ROIs from the ZIP file:
|
|
196
|
+
|
|
197
|
+
>>> rois = roiread('_test.zip')
|
|
198
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
199
|
+
|
|
200
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
201
|
+
|
|
202
|
+
>>> import tifffile
|
|
203
|
+
>>> tifffile.imwrite(
|
|
204
|
+
... '_test.tif',
|
|
205
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
206
|
+
... imagej=True,
|
|
207
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
208
|
+
... )
|
|
209
|
+
|
|
210
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
211
|
+
|
|
212
|
+
>>> rois = roiread('_test.tif')
|
|
213
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
214
|
+
|
|
168
215
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
169
216
|
|
|
170
217
|
python -m roifile _test.roi
|
|
218
|
+
|
|
219
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
@@ -8,7 +8,7 @@ import sys
|
|
|
8
8
|
from setuptools import setup
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def search(pattern, string, flags=0):
|
|
11
|
+
def search(pattern: str, string: str, flags: int = 0) -> str:
|
|
12
12
|
"""Return first match of pattern in string."""
|
|
13
13
|
match = re.search(pattern, string, flags)
|
|
14
14
|
if match is None:
|
|
@@ -16,7 +16,7 @@ def search(pattern, string, flags=0):
|
|
|
16
16
|
return match.groups()[0]
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def fix_docstring_examples(docstring):
|
|
19
|
+
def fix_docstring_examples(docstring: str) -> str:
|
|
20
20
|
"""Return docstring with examples fixed for GitHub."""
|
|
21
21
|
start = True
|
|
22
22
|
indent = False
|
|
@@ -99,7 +99,7 @@ setup(
|
|
|
99
99
|
packages=['roifile'],
|
|
100
100
|
package_data={'roifile': ['py.typed']},
|
|
101
101
|
entry_points={'console_scripts': ['roifile = roifile.roifile:main']},
|
|
102
|
-
python_requires='>=3.
|
|
102
|
+
python_requires='>=3.10',
|
|
103
103
|
install_requires=['numpy'],
|
|
104
104
|
extras_require={'all': ['matplotlib', 'tifffile']},
|
|
105
105
|
platforms=['any'],
|
|
@@ -110,9 +110,9 @@ setup(
|
|
|
110
110
|
'Intended Audience :: Developers',
|
|
111
111
|
'Operating System :: OS Independent',
|
|
112
112
|
'Programming Language :: Python :: 3 :: Only',
|
|
113
|
-
'Programming Language :: Python :: 3.9',
|
|
114
113
|
'Programming Language :: Python :: 3.10',
|
|
115
114
|
'Programming Language :: Python :: 3.11',
|
|
116
115
|
'Programming Language :: Python :: 3.12',
|
|
116
|
+
'Programming Language :: Python :: 3.13',
|
|
117
117
|
],
|
|
118
118
|
)
|
|
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
|