roifile 2024.3.20__py3-none-any.whl → 2024.9.15__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.
Potentially problematic release.
This version of roifile might be problematic. Click here for more details.
- roifile/roifile.py +77 -20
- {roifile-2024.3.20.dist-info → roifile-2024.9.15.dist-info}/METADATA +45 -9
- roifile-2024.9.15.dist-info/RECORD +10 -0
- {roifile-2024.3.20.dist-info → roifile-2024.9.15.dist-info}/WHEEL +1 -1
- roifile-2024.3.20.dist-info/RECORD +0 -10
- {roifile-2024.3.20.dist-info → roifile-2024.9.15.dist-info}/LICENSE +0 -0
- {roifile-2024.3.20.dist-info → roifile-2024.9.15.dist-info}/entry_points.txt +0 -0
- {roifile-2024.3.20.dist-info → roifile-2024.9.15.dist-info}/top_level.txt +0 -0
roifile/roifile.py
CHANGED
|
@@ -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: 2024.
|
|
42
|
+
:Version: 2024.9.15
|
|
43
43
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
44
44
|
|
|
45
45
|
Quickstart
|
|
@@ -65,14 +65,23 @@ 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
|
-
- `Numpy <https://pypi.org/project/numpy/>`_
|
|
70
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.
|
|
71
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
68
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.5, 3.13.0rc2
|
|
69
|
+
- `Numpy <https://pypi.org/project/numpy/>`_ 2.2.1
|
|
70
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.8.30 (optional)
|
|
71
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.9.2 (optional)
|
|
72
72
|
|
|
73
73
|
Revisions
|
|
74
74
|
---------
|
|
75
75
|
|
|
76
|
+
2024.9.15
|
|
77
|
+
|
|
78
|
+
- Improve typing.
|
|
79
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
80
|
+
|
|
81
|
+
2024.5.24
|
|
82
|
+
|
|
83
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
84
|
+
|
|
76
85
|
2024.3.20
|
|
77
86
|
|
|
78
87
|
- Fix writing generator of ROIs (#9).
|
|
@@ -157,20 +166,47 @@ array([[1.1, 2.2],
|
|
|
157
166
|
[5.5, 6.6]], dtype=float32)
|
|
158
167
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
159
168
|
(1, 2, 7, 8)
|
|
169
|
+
>>> roi2.name = 'test'
|
|
160
170
|
|
|
161
171
|
Plot the ROI using matplotlib:
|
|
162
172
|
|
|
163
173
|
>>> roi.plot()
|
|
164
174
|
|
|
175
|
+
Write the ROIs to a ZIP file:
|
|
176
|
+
|
|
177
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
178
|
+
|
|
179
|
+
Read the ROIs from the ZIP file:
|
|
180
|
+
|
|
181
|
+
>>> rois = roiread('_test.zip')
|
|
182
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
183
|
+
|
|
184
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
185
|
+
|
|
186
|
+
>>> import tifffile
|
|
187
|
+
>>> tifffile.imwrite(
|
|
188
|
+
... '_test.tif',
|
|
189
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
190
|
+
... imagej=True,
|
|
191
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
192
|
+
... )
|
|
193
|
+
|
|
194
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
195
|
+
|
|
196
|
+
>>> rois = roiread('_test.tif')
|
|
197
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
198
|
+
|
|
165
199
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
166
200
|
|
|
167
201
|
python -m roifile _test.roi
|
|
168
202
|
|
|
203
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
204
|
+
|
|
169
205
|
"""
|
|
170
206
|
|
|
171
207
|
from __future__ import annotations
|
|
172
208
|
|
|
173
|
-
__version__ = '2024.
|
|
209
|
+
__version__ = '2024.9.15'
|
|
174
210
|
|
|
175
211
|
__all__ = [
|
|
176
212
|
'roiread',
|
|
@@ -197,8 +233,9 @@ import numpy
|
|
|
197
233
|
|
|
198
234
|
if TYPE_CHECKING:
|
|
199
235
|
from collections.abc import Iterable
|
|
200
|
-
from typing import Any, Literal
|
|
236
|
+
from typing import Any, Iterator, Literal
|
|
201
237
|
|
|
238
|
+
from matplotlib.axes import Axes
|
|
202
239
|
from numpy.typing import ArrayLike, NDArray
|
|
203
240
|
|
|
204
241
|
|
|
@@ -888,15 +925,16 @@ class ImagejRoi:
|
|
|
888
925
|
|
|
889
926
|
def plot(
|
|
890
927
|
self,
|
|
891
|
-
ax:
|
|
928
|
+
ax: Axes | None = None,
|
|
892
929
|
*,
|
|
893
930
|
rois: Iterable[ImagejRoi] | None = None,
|
|
894
931
|
title: str | None = None,
|
|
895
932
|
bounds: bool = False,
|
|
896
933
|
invert_yaxis: bool | None = None,
|
|
897
|
-
**kwargs,
|
|
934
|
+
**kwargs: Any,
|
|
898
935
|
) -> None:
|
|
899
936
|
"""Plot a draft of coordinates using matplotlib."""
|
|
937
|
+
fig: Any
|
|
900
938
|
roitype = self.roitype
|
|
901
939
|
subtype = self.subtype
|
|
902
940
|
|
|
@@ -938,8 +976,6 @@ class ImagejRoi:
|
|
|
938
976
|
pyplot.show()
|
|
939
977
|
return
|
|
940
978
|
|
|
941
|
-
if kwargs is None:
|
|
942
|
-
kwargs = {}
|
|
943
979
|
if 'color' not in kwargs and 'c' not in kwargs:
|
|
944
980
|
kwargs['color'] = self.hexcolor(self.stroke_color)
|
|
945
981
|
if 'linewidth' not in kwargs and 'lw' not in kwargs:
|
|
@@ -970,7 +1006,8 @@ class ImagejRoi:
|
|
|
970
1006
|
if 'fontsize' not in kwargs and self.text_size > 0:
|
|
971
1007
|
kwargs['fontsize'] = self.text_size
|
|
972
1008
|
text = ax.text(
|
|
973
|
-
|
|
1009
|
+
coords[1][0],
|
|
1010
|
+
coords[1][1],
|
|
974
1011
|
self.text,
|
|
975
1012
|
va='center_baseline',
|
|
976
1013
|
rotation=self.text_angle,
|
|
@@ -1176,17 +1213,37 @@ class ImagejRoi:
|
|
|
1176
1213
|
return indent(*info, end='\n)')
|
|
1177
1214
|
|
|
1178
1215
|
|
|
1179
|
-
def scale_text(
|
|
1216
|
+
def scale_text(
|
|
1217
|
+
text: Any,
|
|
1218
|
+
width: float,
|
|
1219
|
+
*,
|
|
1220
|
+
offset: tuple[float, float] | None = None,
|
|
1221
|
+
) -> None:
|
|
1180
1222
|
"""Scale matplotlib text to width in data coordinates."""
|
|
1181
1223
|
from matplotlib.patheffects import AbstractPathEffect
|
|
1182
1224
|
from matplotlib.transforms import Bbox
|
|
1183
1225
|
|
|
1184
1226
|
class TextScaler(AbstractPathEffect):
|
|
1185
|
-
def __init__(
|
|
1227
|
+
def __init__(
|
|
1228
|
+
self,
|
|
1229
|
+
text: Any,
|
|
1230
|
+
width: float,
|
|
1231
|
+
offset: tuple[float, float] | None = None,
|
|
1232
|
+
) -> None:
|
|
1233
|
+
if offset is None:
|
|
1234
|
+
offset = (0.0, 0.0)
|
|
1235
|
+
super().__init__(offset)
|
|
1186
1236
|
self._text = text
|
|
1187
1237
|
self._width = width
|
|
1188
1238
|
|
|
1189
|
-
def draw_path(
|
|
1239
|
+
def draw_path(
|
|
1240
|
+
self,
|
|
1241
|
+
renderer: Any,
|
|
1242
|
+
gc: Any,
|
|
1243
|
+
tpath: Any,
|
|
1244
|
+
affine: Any,
|
|
1245
|
+
rgbFace: Any = None,
|
|
1246
|
+
) -> None:
|
|
1190
1247
|
ax = self._text.axes
|
|
1191
1248
|
renderer = ax.get_figure().canvas.get_renderer()
|
|
1192
1249
|
bbox = text.get_window_extent(renderer=renderer)
|
|
@@ -1196,7 +1253,7 @@ def scale_text(text: Any, width: float) -> None:
|
|
|
1196
1253
|
affine = affine.from_values(scale, 0, 0, scale, 0, 0) + affine
|
|
1197
1254
|
renderer.draw_path(gc, tpath, affine, rgbFace)
|
|
1198
1255
|
|
|
1199
|
-
text.set_path_effects([TextScaler(text, width)])
|
|
1256
|
+
text.set_path_effects([TextScaler(text, width, offset)])
|
|
1200
1257
|
|
|
1201
1258
|
|
|
1202
1259
|
def oval(rect: ArrayLike, /, points: int = 33) -> NDArray[numpy.float32]:
|
|
@@ -1211,9 +1268,9 @@ def oval(rect: ArrayLike, /, points: int = 33) -> NDArray[numpy.float32]:
|
|
|
1211
1268
|
return c
|
|
1212
1269
|
|
|
1213
1270
|
|
|
1214
|
-
def indent(*args: Any, sep='', end='') -> str:
|
|
1271
|
+
def indent(*args: Any, sep: str = '', end: str = '') -> str:
|
|
1215
1272
|
"""Return joined string representations of objects with indented lines."""
|
|
1216
|
-
text = (sep + '\n').join(
|
|
1273
|
+
text: str = (sep + '\n').join(
|
|
1217
1274
|
arg if isinstance(arg, str) else repr(arg) for arg in args
|
|
1218
1275
|
)
|
|
1219
1276
|
return (
|
|
@@ -1252,7 +1309,7 @@ def logger() -> logging.Logger:
|
|
|
1252
1309
|
def test(verbose: bool = False) -> None:
|
|
1253
1310
|
"""Test roifile.ImagejRoi class."""
|
|
1254
1311
|
# test ROIs from a ZIP file
|
|
1255
|
-
rois = ImagejRoi.fromfile('tests/ijzip.zip')
|
|
1312
|
+
rois: Any = ImagejRoi.fromfile('tests/ijzip.zip')
|
|
1256
1313
|
assert isinstance(rois, list)
|
|
1257
1314
|
assert len(rois) == 7
|
|
1258
1315
|
for roi in rois:
|
|
@@ -1268,7 +1325,7 @@ def test(verbose: bool = False) -> None:
|
|
|
1268
1325
|
except OSError:
|
|
1269
1326
|
pass
|
|
1270
1327
|
|
|
1271
|
-
def roi_iter():
|
|
1328
|
+
def roi_iter() -> Iterator[ImagejRoi]:
|
|
1272
1329
|
# issue #9
|
|
1273
1330
|
yield from rois
|
|
1274
1331
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: roifile
|
|
3
|
-
Version: 2024.
|
|
3
|
+
Version: 2024.9.15
|
|
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,17 @@ 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
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Requires-Python: >=3.9
|
|
23
23
|
Description-Content-Type: text/x-rst
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: numpy
|
|
26
26
|
Provides-Extra: all
|
|
27
|
-
Requires-Dist: matplotlib
|
|
28
|
-
Requires-Dist: tifffile
|
|
27
|
+
Requires-Dist: matplotlib; extra == "all"
|
|
28
|
+
Requires-Dist: tifffile; extra == "all"
|
|
29
29
|
|
|
30
30
|
Read and write ImageJ ROI format
|
|
31
31
|
================================
|
|
@@ -38,7 +38,7 @@ interest, geometric shapes, paths, text, and whatnot for image overlays.
|
|
|
38
38
|
|
|
39
39
|
:Author: `Christoph Gohlke <https://www.cgohlke.com>`_
|
|
40
40
|
:License: BSD 3-Clause
|
|
41
|
-
:Version: 2024.
|
|
41
|
+
:Version: 2024.9.15
|
|
42
42
|
:DOI: `10.5281/zenodo.6941603 <https://doi.org/10.5281/zenodo.6941603>`_
|
|
43
43
|
|
|
44
44
|
Quickstart
|
|
@@ -64,14 +64,23 @@ Requirements
|
|
|
64
64
|
This revision was tested with the following requirements and dependencies
|
|
65
65
|
(other versions may work):
|
|
66
66
|
|
|
67
|
-
- `CPython <https://www.python.org>`_ 3.
|
|
68
|
-
- `Numpy <https://pypi.org/project/numpy/>`_
|
|
69
|
-
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.
|
|
70
|
-
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.
|
|
67
|
+
- `CPython <https://www.python.org>`_ 3.10.11, 3.11.9, 3.12.5, 3.13.0rc2
|
|
68
|
+
- `Numpy <https://pypi.org/project/numpy/>`_ 2.2.1
|
|
69
|
+
- `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.8.30 (optional)
|
|
70
|
+
- `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.9.2 (optional)
|
|
71
71
|
|
|
72
72
|
Revisions
|
|
73
73
|
---------
|
|
74
74
|
|
|
75
|
+
2024.9.15
|
|
76
|
+
|
|
77
|
+
- Improve typing.
|
|
78
|
+
- Deprecate Python 3.9, support Python 3.13.
|
|
79
|
+
|
|
80
|
+
2024.5.24
|
|
81
|
+
|
|
82
|
+
- Fix docstring examples not correctly rendered on GitHub.
|
|
83
|
+
|
|
75
84
|
2024.3.20
|
|
76
85
|
|
|
77
86
|
- Fix writing generator of ROIs (#9).
|
|
@@ -156,11 +165,38 @@ array([[1.1, 2.2],
|
|
|
156
165
|
[5.5, 6.6]], dtype=float32)
|
|
157
166
|
>>> roi.left, roi.top, roi.right, roi.bottom
|
|
158
167
|
(1, 2, 7, 8)
|
|
168
|
+
>>> roi2.name = 'test'
|
|
159
169
|
|
|
160
170
|
Plot the ROI using matplotlib:
|
|
161
171
|
|
|
162
172
|
>>> roi.plot()
|
|
163
173
|
|
|
174
|
+
Write the ROIs to a ZIP file:
|
|
175
|
+
|
|
176
|
+
>>> roiwrite('_test.zip', [roi, roi2], mode='w')
|
|
177
|
+
|
|
178
|
+
Read the ROIs from the ZIP file:
|
|
179
|
+
|
|
180
|
+
>>> rois = roiread('_test.zip')
|
|
181
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
182
|
+
|
|
183
|
+
Write the ROIs to an ImageJ formatted TIFF file:
|
|
184
|
+
|
|
185
|
+
>>> import tifffile
|
|
186
|
+
>>> tifffile.imwrite(
|
|
187
|
+
... '_test.tif',
|
|
188
|
+
... numpy.zeros((9, 9), 'u1'),
|
|
189
|
+
... imagej=True,
|
|
190
|
+
... metadata={'Overlays': [roi.tobytes(), roi2.tobytes()]},
|
|
191
|
+
... )
|
|
192
|
+
|
|
193
|
+
Read the ROIs embedded in an ImageJ formatted TIFF file:
|
|
194
|
+
|
|
195
|
+
>>> rois = roiread('_test.tif')
|
|
196
|
+
>>> assert len(rois) == 2 and rois[0] == roi and rois[1].name == 'test'
|
|
197
|
+
|
|
164
198
|
View the overlays stored in a ROI, ZIP, or TIFF file from a command line::
|
|
165
199
|
|
|
166
200
|
python -m roifile _test.roi
|
|
201
|
+
|
|
202
|
+
For an advanced example, see `roifile_demo.py` in the source distribution.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
roifile/__init__.py,sha256=leII9J_JWVpi0O9sAnG8s4SpcdwdqEeisFEFsnmN56c,101
|
|
2
|
+
roifile/__main__.py,sha256=Mfn3wm-4cRRChIRonbEcZZT7eRX6RFlS31S8wS1JAVM,132
|
|
3
|
+
roifile/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
roifile/roifile.py,sha256=4DEDDd_hzjhPdrByjDRBYOEzkcjVvg9X3urOOmvStYI,48478
|
|
5
|
+
roifile-2024.9.15.dist-info/LICENSE,sha256=4bDcZTEFGF584Dw8M-07T5qfat7bsrfr8uuffsbFJYU,1559
|
|
6
|
+
roifile-2024.9.15.dist-info/METADATA,sha256=_jKO-ffueSPxsvfJ-b2oTOAA99QgkgI8sTdGe_IMi88,5471
|
|
7
|
+
roifile-2024.9.15.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
8
|
+
roifile-2024.9.15.dist-info/entry_points.txt,sha256=xP8cwEUbAUeROLXNRanJnAIl13tagbjSSDGfVWf2vh0,49
|
|
9
|
+
roifile-2024.9.15.dist-info/top_level.txt,sha256=QlfLomxPxuYNU0TTR7MXoVBAEAXCj2WJyKvoCJxNwek,8
|
|
10
|
+
roifile-2024.9.15.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
roifile/__init__.py,sha256=leII9J_JWVpi0O9sAnG8s4SpcdwdqEeisFEFsnmN56c,101
|
|
2
|
-
roifile/__main__.py,sha256=Mfn3wm-4cRRChIRonbEcZZT7eRX6RFlS31S8wS1JAVM,132
|
|
3
|
-
roifile/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
roifile/roifile.py,sha256=E2-7K86Bk28V7OL75dNDjxfVF3CPaHfBVpt1mU3MXN4,47036
|
|
5
|
-
roifile-2024.3.20.dist-info/LICENSE,sha256=4bDcZTEFGF584Dw8M-07T5qfat7bsrfr8uuffsbFJYU,1559
|
|
6
|
-
roifile-2024.3.20.dist-info/METADATA,sha256=qqhZMep2Kjp_DDjC3HYC6tZhsylVxgXguyTGpf92XAc,4566
|
|
7
|
-
roifile-2024.3.20.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
8
|
-
roifile-2024.3.20.dist-info/entry_points.txt,sha256=xP8cwEUbAUeROLXNRanJnAIl13tagbjSSDGfVWf2vh0,49
|
|
9
|
-
roifile-2024.3.20.dist-info/top_level.txt,sha256=QlfLomxPxuYNU0TTR7MXoVBAEAXCj2WJyKvoCJxNwek,8
|
|
10
|
-
roifile-2024.3.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|