Coverage for tests/test_hips.py: 23%
99 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-15 02:38 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-15 02:38 -0800
1# This file is part of pipe_tasks.
2#
3# LSST Data Management System
4# This product includes software developed by the
5# LSST Project (http://www.lsst.org/).
6# See COPYRIGHT file at the top of the source tree.
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# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the LSST License Statement and
19# the GNU General Public License along with this program. If not,
20# see <https://www.lsstcorp.org/LegalNotices/>.
21#
22"""Test HIPS code."""
23import unittest
24import numpy as np
25import hpgeom as hpg
27import lsst.utils.tests
28import lsst.daf.butler
29import lsst.afw.image
30import lsst.skymap
31import lsst.geom
33from lsst.pipe.tasks.hips import (
34 HighResolutionHipsTask,
35 HighResolutionHipsConfig,
36 HighResolutionHipsConnections
37)
40class MockCoaddImageHandle(lsst.daf.butler.DeferredDatasetHandle):
41 """Simple object that looks like a Gen3 deferred dataset handle
42 to an exposure.
44 Parameters
45 ----------
46 exposure : `lsst.afw.image.ExposureF`
47 Exposure to hold.
48 """
49 def __init__(self, exposure):
50 self.exposure = exposure
52 def get(self, **kwargs):
53 """Retrieve the dataset using the API of the Gen3 Butler.
55 Returns
56 -------
57 exposure : `lsst.afw.image.ExposureF`
58 Exposure held in mock handle.
59 """
60 return self.exposure
62 def dataId(self):
63 return {'visit': 0, 'detector': 0}
66class HipsTestCase(unittest.TestCase):
67 def test_hips_single(self):
68 """Test creating a single HIPS image."""
69 np.random.seed(12345)
71 config = HighResolutionHipsConfig()
73 skymap = self._make_skymap()
75 tract = 9597
76 patch = 50
77 tract_info = skymap[tract]
78 patch_info = tract_info[patch]
80 exposure = self._make_noise_exposure(patch_info)
81 handles = [MockCoaddImageHandle(exposure)]
83 center = patch_info.wcs.pixelToSky(patch_info.inner_bbox.getCenter())
84 pixel = self._get_pixel(2**config.hips_order, center)
86 hips_task = HighResolutionHipsTask(config=config)
87 output = hips_task.run([pixel], handles)
89 # Check that all the pixels are filled.
90 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum())
91 self.assertEqual(npix, output.hips_exposures[pixel].image.array.size)
93 # Check that metadata is correct
94 self.assertEqual(output.hips_exposures[pixel].getPhotoCalib(), exposure.getPhotoCalib())
95 self.assertEqual(output.hips_exposures[pixel].getFilter(), exposure.getFilter())
97 def test_hips_double(self):
98 """Test creating a HIPS image from two neighboring patches."""
99 np.random.seed(12345)
101 config = HighResolutionHipsConfig()
103 skymap = self._make_skymap()
105 tract = 9597
106 patches = [50, 51]
107 tract_info = skymap[tract]
109 handles = []
110 centers = []
111 for patch in patches:
112 patch_info = tract_info[patch]
113 exposure = self._make_noise_exposure(patch_info)
114 handles.append(MockCoaddImageHandle(exposure))
115 centers.append(patch_info.wcs.pixelToSky(patch_info.inner_bbox.getCenter()))
117 center = lsst.geom.SpherePoint(
118 (centers[0].getRa().asDegrees() + centers[1].getRa().asDegrees())/2.*lsst.geom.degrees,
119 (centers[0].getDec().asDegrees() + centers[1].getDec().asDegrees())/2.*lsst.geom.degrees
120 )
121 pixel = self._get_pixel(2**config.hips_order, center)
123 # Just transform one, make sure it falls off the edge.
124 hips_task = HighResolutionHipsTask(config=config)
125 output = hips_task.run([pixel], [handles[0]])
127 # Check that not all the pixels are filled.
128 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum())
129 self.assertLess(npix, output.hips_exposures[pixel].image.array.size)
131 # Transform both.
132 hips_task = HighResolutionHipsTask(config=config)
133 output = hips_task.run([pixel], handles)
135 # Check that all the pixels are filled.
136 npix = (np.isfinite(output.hips_exposures[pixel].image.array.ravel()).sum())
137 self.assertEqual(npix, output.hips_exposures[pixel].image.array.size)
139 def test_hips_none(self):
140 """Test making a HIPS image with no overlapping inputs."""
141 np.random.seed(12345)
143 config = HighResolutionHipsConfig()
145 skymap = self._make_skymap()
147 tract = 9597
148 patch = 50
149 tract_info = skymap[tract]
150 patch_info = tract_info[patch]
152 exposure = self._make_noise_exposure(patch_info)
153 handles = [MockCoaddImageHandle(exposure)]
155 pixel = 0
157 hips_task = HighResolutionHipsTask(config=config)
158 output = hips_task.run([pixel], handles)
160 # Check that there is no returned image
161 self.assertEqual(len(output.hips_exposures), 0)
163 def test_hips_connections(self):
164 """Test that the HIPS connections validate properly."""
165 config = HighResolutionHipsConfig()
167 # Test that the connections validate
168 _ = HighResolutionHipsConnections(config=config)
170 # Test that changing hips_order will break things because of the
171 # dimensions mismatch.
172 config.hips_order = 5
173 with self.assertRaises(ValueError):
174 _ = HighResolutionHipsConnections(config=config)
176 # I'd like to change the dimensions but I don't know how to do that.
178 def _make_noise_exposure(self, patch_info):
179 """Make a simple noise exposure.
181 Parameters
182 ----------
183 patch_info : `lsst.skymap.PatchInfo`
184 Patch info to use to make the exposure.
186 Returns
187 -------
188 exposure : `lsst.afw.image.ExposureF`
189 Noise exposure.
190 """
191 exposure = lsst.afw.image.ExposureF(patch_info.outer_bbox)
192 exposure.image.array[:, :] = np.random.normal(scale=1.0, size=exposure.image.array.shape)
193 exposure.setWcs(patch_info.wcs)
194 exposure.setPhotoCalib(lsst.afw.image.PhotoCalib(calibrationMean=1.0))
195 exposure.setFilter(lsst.afw.image.FilterLabel(band='i'))
197 return exposure
199 def _make_skymap(self):
200 """Make a testing skymap.
202 Returns
203 -------
204 skymap : `lsst.skymap.RingsSkyMap`
205 """
207 # Generate a skymap
208 skymap_config = lsst.skymap.ringsSkyMap.RingsSkyMapConfig()
209 skymap_config.numRings = 120
210 skymap_config.projection = "TAN"
211 skymap_config.tractOverlap = 1.0/60
212 skymap_config.pixelScale = 0.168
213 return lsst.skymap.ringsSkyMap.RingsSkyMap(skymap_config)
215 def _get_pixel(self, nside, sphpoint):
216 """Get the pixel value from a spherepoint.
218 Parameters
219 ----------
220 nside : `int`
221 Healpix nside
222 sphpoint : `lsst.geom.SpherePoint`
223 Point to compute pixel value.
225 Returns
226 -------
227 pixel : `int`
228 Healpix pixel (nest ordering)
229 """
230 pixel = hpg.angle_to_pixel(
231 nside,
232 sphpoint.getRa().asDegrees(),
233 sphpoint.getDec().asDegrees(),
234 )
235 return pixel
238if __name__ == "__main__": 238 ↛ 239line 238 didn't jump to line 239, because the condition on line 238 was never true
239 unittest.main()