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.

@@ -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 GitHub not correctly rendering docstring examples.
15
+ - Fix docstring examples not correctly rendered on GitHub.
7
16
 
8
17
  2024.3.20
9
18
 
@@ -1,6 +1,6 @@
1
1
  BSD 3-Clause License
2
2
 
3
- Copyright (c) 2020-2024, Christoph Gohlke
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
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: roifile
3
- Version: 2024.5.24
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
- Requires-Python: >=3.9
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: 2024.5.24
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.9.13, 3.10.11, 3.11.9, 3.12.3
68
- - `Numpy <https://pypi.org/project/numpy/>`_ 1.26.4
69
- - `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.5.22 (optional)
70
- - `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.8.4 (optional)
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 GitHub not correctly rendering docstring examples.
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: 2024.5.24
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.9.13, 3.10.11, 3.11.9, 3.12.3
42
- - `Numpy <https://pypi.org/project/numpy/>`_ 1.26.4
43
- - `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.5.22 (optional)
44
- - `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.8.4 (optional)
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 GitHub not correctly rendering docstring examples.
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-2024, Christoph Gohlke
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: 2024.5.24
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.9.13, 3.10.11, 3.11.9, 3.12.3
69
- - `Numpy <https://pypi.org/project/numpy/>`_ 1.26.4
70
- - `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.5.22 (optional)
71
- - `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.8.4 (optional)
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 GitHub not correctly rendering docstring examples.
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__ = '2024.5.24'
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: Any | None = None,
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
- *coords[1],
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] = multi_coordinates.tolist()
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(text: Any, width: float) -> None:
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__(self, text, width):
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(self, renderer, gc, tpath, affine, rgbFace=None):
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
1
+ Metadata-Version: 2.2
2
2
  Name: roifile
3
- Version: 2024.5.24
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
- Requires-Python: >=3.9
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: 2024.5.24
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.9.13, 3.10.11, 3.11.9, 3.12.3
68
- - `Numpy <https://pypi.org/project/numpy/>`_ 1.26.4
69
- - `Tifffile <https://pypi.org/project/tifffile/>`_ 2024.5.22 (optional)
70
- - `Matplotlib <https://pypi.org/project/matplotlib/>`_ 3.8.4 (optional)
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 GitHub not correctly rendering docstring examples.
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.9',
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