Coverage for python/lsst/cp/verify/verifyFlat.py: 25%
56 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-03 02:51 -0700
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-03 02:51 -0700
1# This file is part of cp_verify.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://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 <http://www.gnu.org/licenses/>.
21import numpy as np
22import lsst.afw.math as afwMath
23from .verifyStats import CpVerifyStatsConfig, CpVerifyStatsTask, CpVerifyStatsConnections
24from .mergeResults import CpVerifyExpMergeConfig, CpVerifyExpMergeTask
26__all__ = ['CpVerifyFlatConfig', 'CpVerifyFlatTask',
27 'CpVerifyFlatExpMergeConfig', 'CpVerifyFlatExpMergeTask']
28# 'CpVerifyFlatRunMergeConfig', 'CpVerifyFlatRunMergeTask',]
31class CpVerifyFlatConfig(CpVerifyStatsConfig,
32 pipelineConnections=CpVerifyStatsConnections):
33 """Inherits from base CpVerifyStatsConfig.
34 """
36 def setDefaults(self):
37 super().setDefaults()
38 self.imageStatKeywords = {'MEAN': 'MEAN', # noqa F841
39 'NOISE': 'STDEVCLIP', }
40 self.detectorStatKeywords = {'MEAN': 'MEAN', # noqa F841
41 'SCATTER': 'STDEV', }
44class CpVerifyFlatTask(CpVerifyStatsTask):
45 """Flat verification sub-class, implementing the verify method.
46 """
47 ConfigClass = CpVerifyFlatConfig
48 _DefaultName = 'cpVerifyFlat'
50 def detectorStatistics(self, statisticsDict, statControl, exposure=None, uncorrectedExposure=None):
51 """Calculate detector level statistics based on the existing
52 per-amplifier measurements.
54 Parameters
55 ----------
56 statisticsDict : `dict` [`str`, `dict` [`str`, scalar]],
57 Dictionary of measured statistics. The inner dictionary
58 should have keys that are statistic names (`str`) with
59 values that are some sort of scalar (`int` or `float` are
60 the mostly likely types).
61 statControl : `lsst.afw.math.StatControl`
62 Statistics control object with parameters defined by
63 the config.
64 exposure : `lsst.afw.image.Exposure`, optional
65 Exposure containing the ISR-processed data to measure.
66 uncorrectedExposure : `lsst.afw.image.Exposure`, optional
67 uncorrected esposure (no defects) containing the
68 ISR-processed data to measure.
70 Returns
71 -------
72 outputStatistics : `dict` [`str`, scalar]
73 A dictionary of the statistics measured and their values.
75 """
76 outputStatistics = {}
78 ampStats = statisticsDict['AMP']
79 amplifierMeans = [stats['MEAN'] for stats in ampStats.values()]
81 statisticToRun, statAccessor = self._configHelper(self.config.detectorStatKeywords)
82 stats = afwMath.makeStatistics(amplifierMeans, statisticToRun, statControl)
84 for k, v in statAccessor.items():
85 outputStatistics[k] = stats.getValue(v)
87 return outputStatistics
89 def verify(self, exposure, statisticsDict):
90 """Verify that the measured statistics meet the verification criteria.
92 Parameters
93 ----------
94 exposure : `lsst.afw.image.Exposure`
95 The exposure the statistics are from.
96 statisticsDict : `dict` [`str`, `dict` [`str`, scalar]],
97 Dictionary of measured statistics. The inner dictionary
98 should have keys that are statistic names (`str`) with
99 values that are some sort of scalar (`int` or `float` are
100 the mostly likely types).
102 Returns
103 -------
104 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]]
105 A dictionary indexed by the amplifier name, containing
106 dictionaries of the verification criteria.
107 success : `bool`
108 A boolean indicating if all tests have passed.
109 """
110 ampStats = statisticsDict['AMP']
111 verifyStats = {}
112 success = True
113 for ampName, stats in ampStats.items():
114 verify = {}
116 # DMTN-101 Test 10.X: confirm that per-amplifier scatter is
117 # consistent with Poissonian
118 verify['NOISE'] = bool(stats['NOISE'] <= np.sqrt(stats['MEAN']))
120 verify['SUCCESS'] = bool(np.all(list(verify.values())))
121 if verify['SUCCESS'] is False:
122 success = False
124 verifyStats[ampName] = verify
126 verifyDet = {}
127 detStats = statisticsDict['DET']
129 # DMTN-101 Test 10.Y: confirm intra-chip scatter is small.
130 verifyDet['SCATTER'] = bool(detStats['SCATTER']/detStats['MEAN'] <= 0.05)
132 verifyDet['SUCCESS'] = bool(np.all(list(verifyDet.values())))
133 if verifyDet['SUCCESS'] is False:
134 success = False
136 return {'AMP': verifyStats, 'DET': verifyDet}, bool(success)
139class CpVerifyFlatExpMergeConfig(CpVerifyExpMergeConfig):
140 """Inherits from base CpVerifyExpMergeConfig
141 """
143 def setDefaults(self):
144 super().setDefaults()
145 self.exposureStatKeywords = {'EXPOSURE_SCATTER': 'STDEV', # noqa F841
146 }
149class CpVerifyFlatExpMergeTask(CpVerifyExpMergeTask):
150 """Inherits from base CpVerifyExpMergeTask
151 """
153 def exposureStatistics(self, statisticsDictionary):
154 """Calculate exposure level statistics based on the existing
155 per-amplifier and per-detector measurements.
157 Parameters
158 ----------
159 statisticsDictionary : `dict [`str`, `dict` [`str`, scalar]],
160 Dictionary of measured statistics. The top level
161 dictionary is keyed on the detector names, and contains
162 the measured statistics from the per-detector
163 measurements.
165 Returns
166 -------
167 outputStatistics : `dict` [`str, scalar]
168 A dictionary of the statistics measured and their values.
169 """
170 detectorMeans = []
171 for detName, stats in statisticsDictionary.items():
172 # Get detector stats:
173 detectorMeans.append(stats['DET']['MEAN'])
175 return {'SCATTER': np.stdev(detectorMeans)}
177 def verify(self, detectorStatistics, statisticsDictionary):
178 """Verify if the measured statistics meet the verification criteria.
180 Parameters
181 ----------
182 detectorStatistics : `dict` [`str`, `dict` [`str`, scalar]]
183 Merged set of input detector level statistics.
184 statisticsDictionary : `dict` [`str`, `dict` [`str`, scalar]],
185 Dictionary of measured statistics. The inner dictionary
186 should have keys that are statistic names (`str`) with
187 values that are some sort of scalar (`int` or `float` are
188 the mostly likely types).
190 Returns
191 -------
192 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]]
193 A dictionary indexed by the amplifier name, containing
194 dictionaries of the verification criteria.
195 success : `bool`
196 A boolean indicating if all tests have passed.
198 """
199 verifyStats = {}
200 success = True
202 # DMTN-101 Test 10.Z: confirm inter-chip scatter is small.
203 verifyStats['SCATTER'] = bool(statisticsDictionary['EXP']['SCATTER'] <= 0.05)
205 success = bool(np.all(list(verifyStats.values())))
207 return {'EXP': verifyStats}, bool(success)