Skip to content

Commit 0722b9f

Browse files
committed
Address kwargs and boundary naming conventions
1 parent f25246e commit 0722b9f

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

movement/roi/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ def __init__(
117117
``shapely.Polygon`` for details. Ignored if ``dimensions`` is 1.
118118
name : str, default None
119119
Human-readable name to assign to the given region, for
120-
user-friendliness.
120+
user-friendliness. Default name given is 'Un-named region' if no
121+
explicit name is provided.
121122
122123
"""
123124
self._name = name

movement/roi/line.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ def __init__(
3737
If True, the final point in ``points`` will be connected by an
3838
additional line segment to the first, creating a closed loop.
3939
(See Notes).
40-
name : str
41-
Name of the LoI that is to be created.
40+
name : str, optional
41+
Name of the LoI that is to be created. A default name will be
42+
inherited from the base class if not provided, and
43+
defaults are inherited from.
4244
4345
Notes
4446
-----
@@ -47,5 +49,10 @@ def __init__(
4749
analysis, we recommend you create a ``PolygonOfInterest`` and use
4850
its ``boundary`` property instead.
4951
52+
See Also
53+
--------
54+
movement.roi.base.BaseRegionOfInterest
55+
The base class that constructor arguments are passed to.
56+
5057
"""
5158
super().__init__(points, dimensions=1, closed=loop, name=name)

movement/roi/polygon.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""2-dimensional regions of interest."""
22

3+
from __future__ import annotations
4+
35
from collections.abc import Sequence
46

57
from movement.roi.base import BaseRegionOfInterest, PointLikeList
@@ -18,36 +20,53 @@ class PolygonOfInterest(BaseRegionOfInterest):
1820
interest (RoIs) in an analysis. The basic usage is to construct an
1921
instance of this class by passing in a list of points, which will then be
2022
joined (in sequence) by straight lines between consecutive pairs of points,
21-
to form the boundary of the RoI. Note that the boundary itself is a
22-
(closed) ``LineOfInterest``, and may be treated accordingly.
23+
to form the exterior boundary of the RoI. Note that the exterior boundary
24+
(accessible as via the ``.exterior`` property) is a (closed)
25+
``LineOfInterest``, and may be treated accordingly.
26+
27+
The class also supports holes - subregions properly contained inside the
28+
region that are not part of the region itself. These can be specified by
29+
the ``holes`` argument, and define the interior boundaries of the region.
30+
These interior boundaries are accessible via the ``.interior_boundaries``
31+
property, and the polygonal regions that make up the holes are accessible
32+
via the ``holes`` property.
2333
"""
2434

2535
def __init__(
2636
self,
27-
boundary: PointLikeList,
37+
exterior_boundary: PointLikeList,
2838
holes: Sequence[PointLikeList] | None = None,
2939
name: str | None = None,
3040
) -> None:
3141
"""Create a new region of interest (RoI).
3242
3343
Parameters
3444
----------
35-
boundary : tuple of (x, y) pairs
45+
exterior_boundary : tuple of (x, y) pairs
3646
The points (in sequence) that make up the boundary of the region.
3747
At least three points must be provided.
3848
holes : sequence of sequences of (x, y) pairs, default None
3949
A sequence of items, where each item will be interpreted like
4050
``boundary``. These items will be used to construct internal holes
4151
within the region. See the ``holes`` argument to
4252
``shapely.Polygon`` for details.
43-
name : str
44-
Name of the RoI that is to be created.
53+
name : str, optional
54+
Name of the RoI that is to be created. A default name will be
55+
inherited from the base class if not provided.
56+
57+
See Also
58+
--------
59+
movement.roi.base.BaseRegionOfInterest
60+
The base class that constructor arguments are passed to, and
61+
defaults are inherited from.
4562
4663
"""
47-
super().__init__(points=boundary, dimensions=2, holes=holes, name=name)
64+
super().__init__(
65+
points=exterior_boundary, dimensions=2, holes=holes, name=name
66+
)
4867

4968
@property
50-
def exterior(self) -> LineOfInterest:
69+
def exterior_boundary(self) -> LineOfInterest:
5170
"""The exterior boundary of this RoI."""
5271
return LineOfInterest(
5372
self.region.exterior.coords,
@@ -56,12 +75,26 @@ def exterior(self) -> LineOfInterest:
5675
)
5776

5877
@property
59-
def interiors(self) -> tuple[LineOfInterest, ...]:
60-
"""The interior boundaries of this RoI.
78+
def holes(self) -> tuple[PolygonOfInterest, ...]:
79+
"""The interior holes of this RoI.
6180
62-
Interior boundaries are the boundaries of holes contained within the polygon.
81+
Holes are regions properly contained within the exterior boundary of
82+
the RoI that are not part of the RoI itself (like the centre of a
83+
doughnut, for example). A region with no holes returns the empty tuple.
84+
"""
85+
return tuple(
86+
PolygonOfInterest(
87+
int_boundary.coords, name=f"Hole {i} of {self.name}"
88+
)
89+
for i, int_boundary in enumerate(self.region.interiors)
90+
)
91+
92+
@property
93+
def interior_boundaries(self) -> tuple[LineOfInterest, ...]:
94+
"""The interior boundaries of this RoI.
6395
64-
A region with no interior boundaries returns the empty tuple.
96+
Interior boundaries are the boundaries of holes contained within the
97+
polygon. A region with no holes returns the empty tuple.
6598
"""
6699
return tuple(
67100
LineOfInterest(

tests/test_unit/test_roi/test_polygon_boundary.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ def test_boundary(exterior_boundary, interior_boundaries, request) -> None:
4040
shapely.LinearRing(ib) for ib in interior_boundaries
4141
)
4242

43-
computed_exterior = polygon.exterior
44-
computed_interiors = polygon.interiors
43+
computed_exterior = polygon.exterior_boundary
44+
computed_interiors = polygon.interior_boundaries
4545

4646
assert isinstance(computed_exterior, LineOfInterest)
4747
assert expected_exterior.equals_exact(computed_exterior.region, tolerance)

0 commit comments

Comments
 (0)