Coverage for tests/test_brighterFatterKernel.py: 24%
68 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 10:30 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-24 10:30 +0000
1#
2# LSST Data Management System
3#
4# Copyright 2008-2017 AURA/LSST.
5#
6# This product includes software developed by the
7# LSST Project (http://www.lsst.org/).
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 LSST License Statement and
20# the GNU General Public License along with this program. If not,
21# see <https://www.lsstcorp.org/LegalNotices/>.
22#
23"""Test cases for lsst.cp.pipe.BrighterFatterKernelSolveTask.
24"""
26import unittest
27import numpy as np
29import lsst.utils
30import lsst.utils.tests
32import lsst.ip.isr as ipIsr
33import lsst.cp.pipe as cpPipe
34import lsst.afw.cameraGeom as cameraGeom
37class BfkSolveTaskTestCase(lsst.utils.tests.TestCase):
38 """A test case for the brighter fatter kernel solver.
39 """
41 def setUp(self):
42 """Set up a plausible PTC dataset, with 1% of the expected variance
43 shifted into covariance terms.
44 """
45 cameraBuilder = cameraGeom.Camera.Builder('fake camera')
46 detectorWrapper = cameraGeom.testUtils.DetectorWrapper(numAmps=1, cameraBuilder=cameraBuilder)
47 self.detector = detectorWrapper.detector
48 self.camera = cameraBuilder.finish()
50 self.defaultConfig = cpPipe.BrighterFatterKernelSolveConfig()
51 self.ptc = ipIsr.PhotonTransferCurveDataset(ampNames=['amp 1'], ptcFitType='FULLCOVARIANCE',
52 covMatrixSide=3)
53 self.ptc.expIdMask['amp 1'] = np.array([False, True, True, True, True, True, True, True, True, True])
54 self.ptc.rawMeans['amp 1'] = np.array([1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000])
55 self.ptc.finalMeans['amp 1'] = self.ptc.rawMeans['amp 1'][self.ptc.expIdMask['amp 1']]
56 self.ptc.rawVars['amp 1'] = 0.99 * np.array(self.ptc.rawMeans['amp 1'], dtype=float)
57 self.ptc.finalVars['amp 1'] = self.ptc.rawVars['amp 1'][self.ptc.expIdMask['amp 1']]
58 self.ptc.covariances['amp 1'] = []
59 for mean, variance in zip(self.ptc.rawMeans['amp 1'], self.ptc.rawVars['amp 1']):
60 residual = mean - variance
61 covariance = [[variance, 0.5 * residual, 0.1 * residual],
62 [0.2 * residual, 0.1 * residual, 0.05 * residual],
63 [0.025 * residual, 0.015 * residual, 0.01 * residual]]
64 self.ptc.covariances['amp 1'].append(covariance)
66 self.ptc.gain['amp 1'] = 1.0
67 self.ptc.noise['amp 1'] = 5.0
69 # This is empirically determined from the above parameters.
70 self.ptc.aMatrix['amp 1'] = np.array([[2.14329806e-06, -4.28659612e-07, -5.35824515e-08],
71 [-1.07164903e-06, -2.14329806e-07, -3.21494709e-08],
72 [-2.14329806e-07, -1.07164903e-07, -2.14329806e-08]])
74 # This is empirically determined from the above parameters.
75 self.expectation = np.array([[4.88348887e-08, 1.01136877e-07, 1.51784114e-07,
76 1.77570668e-07, 1.51784114e-07, 1.01136877e-07, 4.88348887e-08],
77 [9.42026776e-08, 2.03928507e-07, 3.28428909e-07,
78 4.06714446e-07, 3.28428909e-07, 2.03928507e-07, 9.42026776e-08],
79 [1.24047315e-07, 2.70512582e-07, 4.44123665e-07,
80 5.78099493e-07, 4.44123665e-07, 2.70512582e-07, 1.24047315e-07],
81 [1.31474000e-07, 2.77801372e-07, 3.85123870e-07,
82 -5.42128333e-08, 3.85123870e-07, 2.77801372e-07, 1.31474000e-07],
83 [1.24047315e-07, 2.70512582e-07, 4.44123665e-07,
84 5.78099493e-07, 4.44123665e-07, 2.70512582e-07, 1.24047315e-07],
85 [9.42026776e-08, 2.03928507e-07, 3.28428909e-07,
86 4.06714446e-07, 3.28428909e-07, 2.03928507e-07, 9.42026776e-08],
87 [4.88348887e-08, 1.01136877e-07, 1.51784114e-07,
88 1.77570668e-07, 1.51784114e-07, 1.01136877e-07, 4.88348887e-08]])
90 def test_averaged(self):
91 """Test "averaged" brighter-fatter kernel.
92 """
93 task = cpPipe.BrighterFatterKernelSolveTask()
95 results = task.run(self.ptc, ['this is a dummy exposure'], self.camera, {'detector': 1})
96 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], self.expectation, atol=1e-5)
98 def test_aMatrix(self):
99 """Test solution from Astier et al. 2019 "A" matrix
100 """
101 config = cpPipe.BrighterFatterKernelSolveConfig()
102 config.useAmatrix = True
103 task = cpPipe.BrighterFatterKernelSolveTask(config=config)
105 results = task.run(self.ptc, ['this is a dummy exposure'], self.camera, {'detector': 1})
106 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], self.expectation, atol=1e-5)
108 def test_quadratic(self):
109 """Test quadratic correlation solver.
111 This requires a different model for the variance, so cannot
112 use the one generated by setUp. This model is not entirely
113 physical, but will ensure that accidental code changes are
114 detected.
115 """
116 config = cpPipe.BrighterFatterKernelSolveConfig()
117 config.correlationQuadraticFit = True
118 config.forceZeroSum = True
119 task = cpPipe.BrighterFatterKernelSolveTask(config=config)
121 ptc = ipIsr.PhotonTransferCurveDataset(ampNames=['amp 1'], ptcFitType='FULLCOVARIANCE',
122 covMatrixSide=3)
123 ptc.expIdMask['amp 1'] = np.array([False, True, True, True, True, True, True, True, True, True])
124 ptc.rawMeans['amp 1'] = np.array([1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000])
125 ptc.finalMeans['amp 1'] = ptc.rawMeans['amp 1'][ptc.expIdMask['amp 1']]
126 ptc.rawVars['amp 1'] = 9e-5 * np.square(np.array(ptc.rawMeans['amp 1'], dtype=float))
127 ptc.finalVars['amp 1'] = ptc.rawVars['amp 1'][ptc.expIdMask['amp 1']]
128 ptc.covariances['amp 1'] = []
129 for mean, variance in zip(ptc.rawMeans['amp 1'], ptc.rawVars['amp 1']):
130 residual = variance
131 covariance = [[variance, 0.5 * residual, 0.1 * residual],
132 [0.2 * residual, 0.1 * residual, 0.05 * residual],
133 [0.025 * residual, 0.015 * residual, 0.01 * residual]]
134 ptc.covariances['amp 1'].append(covariance)
136 ptc.gain['amp 1'] = 1.0
137 ptc.noise['amp 1'] = 5.0
139 results = task.run(ptc, ['this is a dummy exposure'], self.camera, {'detector': 1})
141 expectation = np.array([[4.05330882e-08, 2.26654412e-07, 5.66636029e-07, 7.56066176e-07,
142 5.66636029e-07, 2.26654412e-07, 4.05330882e-08],
143 [-6.45220588e-08, 2.99448529e-07, 1.28382353e-06, 1.89099265e-06,
144 1.28382353e-06, 2.99448529e-07, -6.45220588e-08],
145 [-5.98069853e-07, -1.14816176e-06, -2.12178309e-06, -4.75974265e-06,
146 -2.12178309e-06, -1.14816176e-06, -5.98069853e-07],
147 [-1.17959559e-06, -3.52224265e-06, -1.28630515e-05, -6.16863971e-05,
148 -1.28630515e-05, -3.52224265e-06, -1.17959559e-06],
149 [-5.98069853e-07, -1.14816176e-06, -2.12178309e-06, -4.75974265e-06,
150 -2.12178309e-06, -1.14816176e-06, -5.98069853e-07],
151 [-6.45220588e-08, 2.99448529e-07, 1.28382353e-06, 1.89099265e-06,
152 1.28382353e-06, 2.99448529e-07, -6.45220588e-08],
153 [4.05330882e-08, 2.26654412e-07, 5.66636029e-07, 7.56066176e-07,
154 5.66636029e-07, 2.26654412e-07, 4.05330882e-08]])
155 self.assertFloatsAlmostEqual(results.outputBFK.ampKernels['amp 1'], expectation, atol=1e-5)
158class TestMemory(lsst.utils.tests.MemoryTestCase):
159 pass
162def setup_module(module):
163 lsst.utils.tests.init()
166if __name__ == "__main__": 166 ↛ 167line 166 didn't jump to line 167, because the condition on line 166 was never true
167 lsst.utils.tests.init()
168 unittest.main()