Coverage for tests / test_isolated_source.py: 18%
73 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-30 09:05 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-30 09:05 +0000
1# This file is part of lsst.scarlet.lite.
2#
3# Developed for the LSST Data Management System.
4# (https://www.lsst.org).
5# See the COPYRIGHT file at the top-level directory of this distribution
6# for details of code ownership.
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# This product includes software developed by the LSST Project
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/>.
22from unittest import TestCase
24import numpy as np
26import lsst.meas.extensions.scarlet as mes
27import lsst.scarlet.lite as scl
30class ScarletTestCase(TestCase):
31 """A base TestCase for scarlet tests.
32 """
33 def setUp(self) -> None:
34 super().setUp()
35 self.bands = tuple("grizy")
36 peak = (27, 32)
37 bbox = scl.Box((15, 15), (20, 25))
38 morph = scl.utils.integrated_circular_gaussian(sigma=0.8).astype(np.float32)
39 spectrum = np.arange(5, dtype=np.float32)
40 model = morph[None, :, :] * spectrum[:, None, None]
41 model_image = scl.Image(model, yx0=bbox.origin, bands=self.bands)
42 self.component = scl.component.CubeComponent(model=model_image, peak=peak)
44 def test_constructor(self):
45 source = mes.source.IsolatedSource(
46 model=self.component._model,
47 peak=self.component.peak,
48 )
50 np.testing.assert_array_equal(
51 source.component._model.data,
52 self.component._model.data,
53 )
54 self.assertEqual(source.component.peak, self.component.peak)
56 def test_copy(self):
57 source = mes.source.IsolatedSource(
58 model=self.component._model,
59 peak=self.component.peak,
60 )
61 source_copy = source.copy()
63 self.assertIsNot(source_copy, source)
64 self.assertIs(
65 source_copy.component._model.data,
66 source.component._model.data,
67 )
68 self.assertEqual(source_copy.component.peak, source.component.peak)
70 def test_deep_copy(self):
71 source = mes.source.IsolatedSource(
72 model=self.component._model,
73 peak=self.component.peak,
74 )
75 source_copy = source.copy(deep=True)
77 self.assertTupleEqual(source_copy.component.peak, source.component.peak)
79 np.testing.assert_array_equal(
80 source_copy.component._model.data,
81 source.component._model.data,
82 )
83 self.assertIsNot(
84 source_copy.component._model.data,
85 source.component._model.data,
86 )
88 with self.assertRaises(AssertionError):
89 source_copy.component._model._data -= 1
90 np.testing.assert_array_equal(
91 source_copy.component._model.data,
92 source.component._model.data,
93 )
95 def test_slice(self):
96 source = mes.source.IsolatedSource(self.component._model, self.component.peak)
97 source_sliced = source["g":"r"]
98 self.assertTupleEqual(source_sliced.bands, ("g", "r"))
99 np.testing.assert_array_equal(
100 source_sliced.get_model().data,
101 source.get_model().data[:2],
102 )
104 def test_reorder(self):
105 source = mes.source.IsolatedSource(self.component._model, self.component.peak)
106 indices = ("i", "g", "r")
107 source_reordered = source[indices]
108 self.assertTupleEqual(source_reordered.bands, indices)
109 np.testing.assert_array_equal(
110 source_reordered.get_model().data,
111 source.get_model().data[[2, 0, 1]],
112 )
114 source_reordered = source["igr"]
115 self.assertTupleEqual(source_reordered.bands, indices)
116 np.testing.assert_array_equal(
117 source_reordered.get_model().data,
118 source.get_model().data[[2, 0, 1]],
119 )
121 def test_subset(self):
122 source = mes.source.IsolatedSource(self.component._model, self.component.peak)
123 source_subset = source[("r",)]
124 self.assertTupleEqual(source_subset.bands, ("r",))
125 np.testing.assert_array_equal(
126 source_subset.get_model().data,
127 source.get_model().data[1:2],
128 )
130 def test_indexing_errors(self):
131 source = mes.source.IsolatedSource(self.component._model, self.component.peak)
132 with self.assertRaises(IndexError):
133 # "x" is not an a band in the model
134 source["x"]
136 with self.assertRaises(IndexError):
137 # "x" is not an a band in the model
138 source["r":"x"]
140 with self.assertRaises(IndexError):
141 # "x" is not an a band in the model
142 source["x":"i"]
144 with self.assertRaises(IndexError):
145 # "x" is not an a band in the model
146 source["g", "x", "i"]
148 with self.assertRaises(IndexError):
149 # The box doesn't overlap with the model
150 source[scl.Box((0, 0), (10, 10))]
152 with self.assertRaises(IndexError):
153 # Users must provide a Box, not a tuple, for spatial dimensions
154 source[:, 10:20, 10:20]
156 with self.assertRaises(IndexError):
157 # Users must provide a Box, not a slice, for spatial dimensions
158 source[1:]
160 with self.assertRaises(IndexError):
161 # Users must provide a Box, not an int, for spatial dimensions
162 source[1]
164 with self.assertRaises(IndexError):
165 # Users must provide a Box, not a tuple, for spatial dimensions
166 source[0, 1]