Coverage for tests/test_brightStarStamps.py: 14%
100 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-30 03:08 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-30 03:08 -0700
1# This file is part of meas_algorithms.
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 unittest
23import numpy as np
24import tempfile
26from lsst.meas.algorithms import brightStarStamps
27from lsst.afw import image as afwImage
28from lsst.geom import Point2I
29from lsst.daf.base import PropertyList
30import lsst.utils.tests
33class BrightStarStampsTestCase(lsst.utils.tests.TestCase):
34 """Test BrightStarStamps.
35 """
36 def setUp(self):
37 np.random.seed(12)
38 stampSize = (25, 25)
39 # create dummy star stamps
40 starImages = [afwImage.MaskedImageF(*stampSize)
41 for _ in range(3)]
42 for starIm in starImages:
43 starImArray = starIm.image.array
44 starImArray += np.random.rand(*stampSize)
45 ids = ["111", "aaa", "bbb"]
46 positions = [Point2I(x0, y0)
47 for x0, y0 in zip(np.random.randint(11, size=3), np.random.randint(11, size=3))]
48 mags = np.random.rand(3)
49 # faint object to test magnitude cuts
50 self.faintObjIdx = 1
51 mags[self.faintObjIdx] = 18.
52 ids[self.faintObjIdx] = "faint"
53 fluxes = np.random.rand(3)
54 self.starStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm,
55 gaiaGMag=mag,
56 position=pos,
57 gaiaId=gaiaId,
58 annularFlux=flux)
59 for starIm, mag, gaiaId, pos, flux in
60 zip(starImages, mags, ids, positions, fluxes)]
61 self.unnormalizedStarStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm,
62 gaiaGMag=mag,
63 position=pos,
64 gaiaId=gaiaId)
65 for starIm, mag, gaiaId, pos, flux in
66 zip(starImages, mags, ids, positions, fluxes)]
67 self.toBeNormalizedStarStamps = [brightStarStamps.BrightStarStamp(stamp_im=starIm,
68 gaiaGMag=mag,
69 position=pos,
70 gaiaId=gaiaId)
71 for starIm, mag, gaiaId, pos, flux in
72 zip(starImages, mags, ids, positions, fluxes)]
73 self.innerRadius = 5
74 self.outerRadius = 10
75 self.nb90Rots = 2
76 self.bss = brightStarStamps.BrightStarStamps(self.starStamps,
77 innerRadius=self.innerRadius,
78 outerRadius=self.outerRadius,
79 nb90Rots=self.nb90Rots)
81 def tearDown(self):
82 del self.bss
83 del self.starStamps
84 del self.unnormalizedStarStamps
85 del self.toBeNormalizedStarStamps
86 del self.innerRadius
87 del self.outerRadius
88 del self.faintObjIdx
90 def testIO(self):
91 """Test the class' write and readFits methods.
93 The ``options`` argument to the read method is only used to read
94 sub-BBoxes, which is handled by the Butler. Tests of this are done in
95 afw.
96 """
97 with tempfile.NamedTemporaryFile() as f:
98 self.bss.writeFits(f.name)
99 options = PropertyList()
100 bss2 = brightStarStamps.BrightStarStamps.readFitsWithOptions(f.name, options)
101 self.assertEqual(len(self.bss), len(bss2))
102 for mi1, mi2 in zip(self.bss.getMaskedImages(), bss2.getMaskedImages()):
103 self.assertMaskedImagesAlmostEqual(mi1, mi2)
104 np.testing.assert_almost_equal(self.bss.getMagnitudes(), bss2.getMagnitudes())
105 np.testing.assert_almost_equal(self.bss.getAnnularFluxes(), bss2.getAnnularFluxes())
106 for id1, id2 in zip(self.bss.getGaiaIds(), bss2.getGaiaIds()):
107 self.assertEqual(id1, id2)
108 for pos1, pos2 in zip(self.bss.getPositions(), bss2.getPositions()):
109 self.assertEqual(pos1[0], pos2[0])
110 self.assertEqual(pos1[1], pos2[1])
111 self.assertEqual(bss2.nb90Rots, self.nb90Rots)
113 def testMagnitudeSelection(self):
114 brightOnly = self.bss.selectByMag(magMax=7)
115 self.assertEqual(len(brightOnly), 2)
116 self.assertFalse("faint" in brightOnly.getGaiaIds())
118 faintOnly = self.bss.selectByMag(magMin=7)
119 self.assertEqual(len(faintOnly), 1)
120 self.assertEqual(faintOnly.getGaiaIds()[0], "faint")
121 faintObj = self.bss[self.faintObjIdx]
122 self.assertMaskedImagesAlmostEqual(faintObj.stamp_im, faintOnly.getMaskedImages()[0])
124 def testTypeMismatchHandling(self):
125 fullStar = self.bss[0]
126 # try passing on a dictionary and a maskedImage instead of a
127 # BrightStarStamp
128 falseStar = {"starStamp": fullStar.stamp_im, "gaiaGMag": fullStar.gaiaGMag,
129 "gaiaId": fullStar.gaiaId, "annularFlux": fullStar.annularFlux}
130 starIm = fullStar.stamp_im
131 for wrongType in [falseStar, starIm]:
132 # test at initialization
133 with self.assertRaises(ValueError):
134 _ = brightStarStamps.BrightStarStamps([fullStar, wrongType], innerRadius=self.innerRadius,
135 outerRadius=self.outerRadius)
136 # test at appending time
137 with self.assertRaises(ValueError):
138 self.bss.append(wrongType, innerRadius=self.innerRadius, outerRadius=self.outerRadius)
140 def testAnnulusMismatch(self):
141 """Test an exception is raised if mismatching annulus radii are
142 given (as the annularFlux values would then be meaningless)."""
143 # starStamps are already normalized; an Exception should be raised when
144 # trying to pass them onto the initAndNormalize classmethod
145 with self.assertRaises(AttributeError):
146 _ = brightStarStamps.BrightStarStamps.initAndNormalize(self.starStamps,
147 innerRadius=self.innerRadius,
148 outerRadius=self.outerRadius)
149 # unnormalizedStarStamps can be kept unnormalized provided no radii are
150 # passed on as arguments
151 bss2 = brightStarStamps.BrightStarStamps(self.unnormalizedStarStamps)
152 with self.assertRaises(AttributeError):
153 _ = brightStarStamps.BrightStarStamps(self.unnormalizedStarStamps,
154 innerRadius=self.innerRadius,
155 outerRadius=self.outerRadius)
156 # or normalized at initialization, in which case radii must be passed
157 # on
158 bss3 = brightStarStamps.BrightStarStamps.initAndNormalize(self.toBeNormalizedStarStamps,
159 innerRadius=self.innerRadius,
160 outerRadius=self.outerRadius)
161 # BrightStarStamps instances can be concatenated if the radii used are
162 # the same
163 self.bss.extend(bss3)
164 # but an Exception should be raised when trying to concatenate a mix of
165 # normalized and unnormalized stamps
166 with self.assertRaises(AttributeError):
167 self.bss.extend(bss2)
168 # or stamps normalized with different annular radii
169 bss4 = brightStarStamps.BrightStarStamps.initAndNormalize(self.unnormalizedStarStamps,
170 innerRadius=int(self.innerRadius/2),
171 outerRadius=self.outerRadius)
172 with self.assertRaises(AttributeError):
173 self.bss.extend(bss4)
174 # or when appending an extra stamp with different annulus radii
175 fullStar = self.bss[0]
176 with self.assertRaises(AttributeError):
177 self.bss.append(fullStar, innerRadius=int(self.innerRadius/2), outerRadius=self.outerRadius + 1)
178 # or a normalized stamp to unnormalized BrightStarStamps, or vice-versa
179 with self.assertRaises(AttributeError):
180 bss2.append(fullStar, innerRadius=self.innerRadius, outerRadius=self.outerRadius)
181 unNormFullStar = bss2[0]
182 with self.assertRaises(AttributeError):
183 self.bss.append(unNormFullStar)
186class MemoryTester(lsst.utils.tests.MemoryTestCase):
187 pass
190def setup_module(module):
191 lsst.utils.tests.init()
194if __name__ == "__main__": 194 ↛ 195line 194 didn't jump to line 195, because the condition on line 194 was never true
195 lsst.utils.tests.init()
196 unittest.main()