Coverage for tests / test_inject_engine.py: 36%
55 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-24 08:56 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-24 08:56 +0000
1# This file is part of source_injection.
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
23from types import GeneratorType
25import galsim
26import numpy as np
27from galsim import BoundsI, GSObject
29import lsst.utils.tests
30from lsst.geom import Point2D, SpherePoint, degrees
31from lsst.source.injection.inject_engine import (
32 generate_galsim_objects,
33 inject_galsim_objects_into_exposure,
34 make_galsim_object,
35)
36from lsst.source.injection.utils.test_utils import make_test_exposure, make_test_injection_catalog
37from lsst.utils.tests import MemoryTestCase, TestCase
40class InjectEngineTestCase(TestCase):
41 """Test the inject_engine.py module."""
43 def setUp(self):
44 """Set up synthetic source injection inputs.
46 This method sets up a noisy synthetic image with Gaussian PSFs injected
47 into the frame, an example source injection catalog, and a generator of
48 GalSim objects intended for injection.
49 """
50 self.exposure = make_test_exposure()
51 self.injection_catalog = make_test_injection_catalog(
52 self.exposure.getWcs(),
53 self.exposure.getBBox(),
54 )
55 self.galsim_objects = generate_galsim_objects(
56 injection_catalog=self.injection_catalog,
57 photo_calib=self.exposure.photoCalib,
58 wcs=self.exposure.wcs,
59 fits_alignment="wcs",
60 stamp_prefix="",
61 )
63 def tearDown(self):
64 del self.exposure
65 del self.injection_catalog
66 del self.galsim_objects
68 def test_make_galsim_object(self):
69 source_data = self.injection_catalog[0]
70 sky_coords = SpherePoint(float(source_data["ra"]), float(source_data["dec"]), degrees)
71 pixel_coords = self.exposure.wcs.skyToPixel(sky_coords)
72 inst_flux = self.exposure.photoCalib.magnitudeToInstFlux(source_data["mag"], pixel_coords)
73 object = make_galsim_object(
74 source_data=source_data,
75 source_type=source_data["source_type"],
76 inst_flux=inst_flux,
77 )
78 self.assertIsInstance(object, GSObject)
79 self.assertIsInstance(object, getattr(galsim, source_data["source_type"]))
81 def test_generate_galsim_objects(self):
82 self.assertTrue(isinstance(self.galsim_objects, GeneratorType))
83 for galsim_object in self.galsim_objects:
84 self.assertIsInstance(galsim_object, tuple)
85 self.assertEqual(len(galsim_object), 4)
86 self.assertIsInstance(galsim_object[0], SpherePoint) # RA/Dec
87 self.assertIsInstance(galsim_object[1], Point2D) # x/y
88 self.assertIsInstance(galsim_object[2], int) # draw size
89 self.assertIsInstance(galsim_object[3], GSObject) # GSObject
91 def test_inject_galsim_objects_into_exposure(self):
92 flux0 = np.sum(self.exposure.image.array)
93 injected_outputs = inject_galsim_objects_into_exposure(
94 exposure=self.exposure,
95 objects=self.galsim_objects,
96 mask_plane_name="INJECTED",
97 calib_flux_radius=12.0,
98 draw_size_max=1000,
99 add_noise=False,
100 )
101 pc = self.exposure.getPhotoCalib()
102 inst_fluxes = [float(pc.magnitudeToInstFlux(mag)) for mag in self.injection_catalog["mag"]]
103 self.assertAlmostEqual(
104 np.sum(self.exposure.image.array) - flux0,
105 np.sum(inst_fluxes),
106 delta=0.00015 * np.sum(inst_fluxes),
107 )
108 self.assertEqual(len(injected_outputs[0]), len(self.injection_catalog["ra"]))
109 self.assertTrue(all(isinstance(injected_output, list) for injected_output in injected_outputs))
110 self.assertTrue(all(isinstance(item, int) for item in injected_outputs[0])) # draw sizes
111 self.assertTrue(all(isinstance(item, BoundsI) for item in injected_outputs[1])) # common bounds
112 self.assertTrue(all(isinstance(item, bool) for item in injected_outputs[2])) # FFT size errors
113 self.assertTrue(all(isinstance(item, bool) for item in injected_outputs[3])) # PSF compute errors
116class MemoryTestCase(MemoryTestCase):
117 """Test memory usage of functions in this script."""
119 pass
122def setup_module(module):
123 """Configure pytest."""
124 lsst.utils.tests.init()
127if __name__ == "__main__": 127 ↛ 128line 127 didn't jump to line 128 because the condition on line 127 was never true
128 lsst.utils.tests.init()
129 unittest.main()