Coverage for tests/test_bbox.py: 11%
134 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 15:13 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 15:13 -0700
1# This file is part of scarlet_lite.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import numpy as np
23from lsst.scarlet.lite import Box
24from utils import ScarletTestCase
27class TestBox(ScarletTestCase):
28 def check_bbox(self, bbox: Box, shape: tuple[int, ...], origin: tuple[int, ...]):
29 """Check the attributes and properties of a Box
31 Parameters
32 ----------
33 bbox:
34 The box to test.
35 shape:
36 The shape of the Box.
37 origin:
38 The origin of the Box.
39 """
40 self.assertTupleEqual(bbox.shape, shape)
41 self.assertTupleEqual(bbox.origin, origin)
42 self.assertEqual(bbox.ndim, len(shape))
43 self.assertTupleEqual(bbox.start, origin)
45 def test_constructors(self):
46 shape = (2, 3, 4)
47 origin = (0, 0, 0)
48 bbox = Box(shape)
49 self.check_bbox(bbox, shape=shape, origin=origin)
51 shape = (2, 4)
52 origin = (5, 6)
53 bbox = Box(shape, origin)
54 self.check_bbox(bbox, shape=shape, origin=origin)
56 bbox = Box.from_bounds((5, 7), (6, 10))
57 self.check_bbox(bbox, shape, origin)
59 def test_from_data(self):
60 x = np.arange(25).reshape(5, 5)
61 x[0] = 0
62 x[:, -2:] = 0
63 bbox = Box.from_data(x)
64 self.assertBoxEqual(bbox, Box((4, 3), origin=(1, 0)))
66 x += 10
67 bbox = Box.from_data(x)
68 self.assertBoxEqual(bbox, Box((5, 5), origin=(0, 0)))
70 bbox = Box.from_data(x, threshold=10)
71 self.assertBoxEqual(bbox, Box((4, 3), origin=(1, 0)))
73 bbox = Box.from_data(x, threshold=100)
74 self.assertBoxEqual(bbox, Box((0, 0), origin=(0, 0)))
76 def test_contains(self):
77 bbox = Box((6, 4, 3), origin=(0, 1, 0))
78 p = (2, 2, 2)
79 self.assertTrue(bbox.contains(p))
81 p = (3, 0, 3)
82 self.assertFalse(bbox.contains(p))
84 p = (7, 3, 3)
85 self.assertFalse(bbox.contains(p))
87 p = (3, 3, -1)
88 self.assertFalse(bbox.contains(p))
90 with self.assertRaises(ValueError):
91 bbox.contains((1, 2))
93 def test_properties(self):
94 shape = (10, 3, 8)
95 origin = (2, 7, 5)
96 bbox = Box(shape, origin)
97 self.assertTupleEqual(bbox.stop, (12, 10, 13))
98 self.assertTupleEqual(bbox.center, (7, 8.5, 9))
99 self.assertTupleEqual(bbox.bounds, ((2, 12), (7, 10), (5, 13)))
100 self.assertTupleEqual(bbox.shape, shape)
101 self.assertTupleEqual(bbox.origin, origin)
102 self.assertEqual(len(bbox.slices), 3)
103 self.assertEqual(bbox.slices[0], slice(2, 12))
104 self.assertEqual(bbox.slices[1], slice(7, 10))
105 self.assertEqual(bbox.slices[2], slice(5, 13))
106 self.assertEqual(hash(bbox), hash((shape, origin)))
108 def test_simple_methods(self):
109 shape = (2, 4, 8, 16)
110 origin = (9, 5, 3, 9)
111 bbox = Box(shape, origin)
112 self.check_bbox(bbox, shape, origin)
114 # Grow the box
115 grown = bbox.grow(3)
116 self.check_bbox(grown, (8, 10, 14, 22), (6, 2, 0, 6))
118 # Shift the box
119 shifted = bbox.shifted_by((0, 5, 2, 10))
120 self.check_bbox(shifted, shape, (9, 10, 5, 19))
122 def test_union(self):
123 bbox1 = Box((3, 4), (20, 34))
124 bbox2 = Box((10, 15), (1, 2))
125 bbox3 = Box((20, 30, 40), (10, 20, 30))
127 result = bbox1 | bbox2
128 truth = Box((22, 36), (1, 2))
129 self.assertBoxEqual(result, truth)
131 with self.assertRaises(ValueError):
132 bbox1 | bbox3
134 def test_intersection(self):
135 bbox1 = Box((3, 4), (20, 34))
136 bbox2 = Box((20, 30), (10, 20))
137 bbox3 = Box((20, 30, 40), (10, 20, 30))
139 result = bbox1 & bbox2
140 truth = Box((3, 4), (20, 34))
141 self.assertBoxEqual(result, truth)
143 with self.assertRaises(ValueError):
144 bbox1 & bbox3
146 def test_intersections(self):
147 bbox1 = Box((3, 4), (20, 34))
148 bbox2 = Box((10, 15), (1, 2))
149 bbox3 = Box((20, 30), (10, 20))
151 # Test intersection test
152 self.assertFalse(bbox1.intersects(bbox2))
153 self.assertTrue(bbox1.intersects(bbox3))
154 self.assertFalse(bbox2.intersects(bbox1))
155 self.assertFalse(bbox2.intersects(bbox3))
156 self.assertTrue(bbox3.intersects(bbox1))
158 # Test overlapping slices
159 slices = bbox1.overlapped_slices(bbox2)
160 self.assertTupleEqual(slices, ((slice(0, 0), slice(0, 0)), (slice(0, 0), slice(0, 0))))
161 slices = bbox1.overlapped_slices(bbox3)
162 self.assertTupleEqual(slices, ((slice(0, 3), slice(0, 4)), (slice(10, 13), (slice(14, 18)))))
164 def test_offset(self):
165 shape = (2, 5, 7)
166 origin = (82, 34, 15)
167 bbox = Box(shape, origin)
168 bbox = bbox + 1
169 self.assertBoxEqual(bbox, Box(shape, (83, 35, 16)))
171 def test_arithmetic(self):
172 shape = (2, 5, 7)
173 origin = (82, 34, 15)
174 bbox = Box(shape, origin)
176 # Check addition
177 shifted = bbox + (2, 4, 6)
178 self.check_bbox(bbox, shape, origin)
179 self.check_bbox(shifted, shape, (84, 38, 21))
181 # Check subtraction
182 shifted = bbox - (2, 4, 6)
183 self.check_bbox(bbox, shape, origin)
184 self.check_bbox(shifted, shape, (80, 30, 9))
186 # Check "matrix multiplication"
187 prebox = Box((2, 5), (3, 4))
188 new_box = prebox @ bbox
189 self.check_bbox(new_box, (2, 5, 2, 5, 7), (3, 4, 82, 34, 15))
191 # Check equality
192 bbox1 = Box((1, 2, 3), (2, 4, 6))
193 bbox2 = Box((1, 2, 3), (2, 4, 6))
194 bbox3 = Box((1, 2), (5, 6))
196 self.assertBoxEqual(bbox1, bbox2)
197 with self.assertRaises(AssertionError):
198 self.assertBoxEqual(bbox2, bbox3)
200 # Check a copy
201 bbox2 = bbox.copy()
202 self.assertBoxEqual(bbox, bbox2)
204 self.assertFalse(bbox1 == shape)
205 self.assertNotEqual(bbox1, bbox2)
206 self.assertEqual(bbox1, bbox1)
208 def test_slicing(self):
209 bbox = Box((1, 2, 3, 4), (2, 4, 6, 8))
210 # Check integer index
211 self.assertBoxEqual(bbox[2], Box((3,), (6,)))
212 # check slice index
213 self.assertBoxEqual(bbox[:3], Box((1, 2, 3), (2, 4, 6)))
214 # check tuple index
215 self.assertBoxEqual(bbox[(3, 1)], Box((4, 2), (8, 4)))