-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcontour.py
61 lines (47 loc) · 2.4 KB
/
contour.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Copyright 2018-2025
# Institute of Neuroscience and Medicine (INM-1), Forschungszentrum Jülich GmbH
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from ..locations import point, pointcloud, boundingbox
import numpy as np
class Contour(pointcloud.PointCloud):
"""
A PointCloud that represents a contour line.
The only difference is that the point order is relevant,
and consecutive points are thought as being connected by an edge.
In fact, PointCloud assumes order as well, but no connections between points.
"""
def __init__(self, coordinates, space=None, sigma_mm=0, labels: list = None):
pointcloud.PointCloud.__init__(self, coordinates, space, sigma_mm, labels)
def crop(self, voi: boundingbox.BoundingBox):
"""
Crop the contour with a volume of interest.
Since the contour might be split from the cropping,
returns a set of contour segments.
"""
segments = []
# set the contour point labels to a linear numbering
# so we can use them after the intersection to detect splits.
old_labels = self.labels
self.labels = list(range(len(self)))
cropped = self.intersection(voi)
if cropped is not None and not isinstance(cropped, point.Point):
assert isinstance(cropped, pointcloud.PointCloud)
# Identify contour splits are by discontinuouities ("jumps")
# of their labels, which denote positions in the original contour
jumps = np.diff([self.labels.index(lb) for lb in cropped.labels])
splits = [0] + list(np.where(jumps > 1)[0] + 1) + [len(cropped)]
for i, j in zip(splits[:-1], splits[1:]):
segments.append(
self.__class__(cropped.coordinates[i:j, :], space=cropped.space)
)
# reset labels of the input contour points.
self.labels = old_labels
return segments