Coverage for python/lsst/cp/verify/verifyFlat.py: 25%
56 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-11 12:23 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-01-11 12:23 +0000
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):
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).
62 Returns
63 -------
64 outputStatistics : `dict` [`str`, scalar]
65 A dictionary of the statistics measured and their values.
67 """
68 outputStatistics = {}
70 ampStats = statisticsDict['AMP']
71 amplifierMeans = [stats['MEAN'] for stats in ampStats.values()]
73 statisticToRun, statAccessor = self._configHelper(self.config.detectorStatKeywords)
74 stats = afwMath.makeStatistics(amplifierMeans, statisticToRun, statControl)
76 for k, v in statAccessor.items():
77 outputStatistics[k] = stats.getValue(v)
79 return outputStatistics
81 def verify(self, exposure, statisticsDict):
82 """Verify that the measured statistics meet the verification criteria.
84 Parameters
85 ----------
86 exposure : `lsst.afw.image.Exposure`
87 The exposure the statistics are from.
88 statisticsDict : `dict` [`str`, `dict` [`str`, scalar]],
89 Dictionary of measured statistics. The inner dictionary
90 should have keys that are statistic names (`str`) with
91 values that are some sort of scalar (`int` or `float` are
92 the mostly likely types).
94 Returns
95 -------
96 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]]
97 A dictionary indexed by the amplifier name, containing
98 dictionaries of the verification criteria.
99 success : `bool`
100 A boolean indicating if all tests have passed.
101 """
102 ampStats = statisticsDict['AMP']
103 verifyStats = {}
104 success = True
105 for ampName, stats in ampStats.items():
106 verify = {}
108 # DMTN-101 Test 10.X: confirm that per-amplifier scatter is
109 # consistent with Poissonian
110 verify['NOISE'] = bool(np.abs(stats['NOISE']) <= np.sqrt(stats['MEAN']))
112 verify['SUCCESS'] = bool(np.all(list(verify.values())))
113 if verify['SUCCESS'] is False:
114 success = False
116 verifyStats[ampName] = verify
118 verifyDet = {}
119 detStats = statisticsDict['DET']
121 # DMTN-101 Test 10.Y: confirm intra-chip scatter is small.
122 verifyDet['SCATTER'] = bool(detStats['SCATTER']/detStats['MEAN'] <= 0.05)
124 verifyDet['SUCCESS'] = bool(np.all(list(verifyDet.values())))
125 if verifyDet['SUCCESS'] is False:
126 success = False
128 return {'AMP': verifyStats, 'DET': verifyDet}, bool(success)
131class CpVerifyFlatExpMergeConfig(CpVerifyExpMergeConfig):
132 """Inherits from base CpVerifyExpMergeConfig
133 """
135 def setDefaults(self):
136 super().setDefaults()
137 self.exposureStatKeywords = {'EXPOSURE_SCATTER': 'STDEV', # noqa F841
138 }
141class CpVerifyFlatExpMergeTask(CpVerifyExpMergeTask):
142 """Inherits from base CpVerifyExpMergeTask
143 """
145 def exposureStatistics(self, statisticsDictionary):
146 """Calculate exposure level statistics based on the existing
147 per-amplifier and per-detector measurements.
149 Parameters
150 ----------
151 statisticsDictionary : `dict [`str`, `dict` [`str`, scalar]],
152 Dictionary of measured statistics. The top level
153 dictionary is keyed on the detector names, and contains
154 the measured statistics from the per-detector
155 measurements.
157 Returns
158 -------
159 outputStatistics : `dict` [`str, scalar]
160 A dictionary of the statistics measured and their values.
161 """
162 detectorMeans = []
163 for detName, stats in statisticsDictionary.items():
164 # Get detector stats:
165 detectorMeans.append(stats['DET']['MEAN'])
167 return {'SCATTER': np.stdev(detectorMeans)}
169 def verify(self, detectorStatistics, statisticsDictionary):
170 """Verify if the measured statistics meet the verification criteria.
172 Parameters
173 ----------
174 detectorStatistics : `dict` [`str`, `dict` [`str`, scalar]]
175 Merged set of input detector level statistics.
176 statisticsDictionary : `dict` [`str`, `dict` [`str`, scalar]],
177 Dictionary of measured statistics. The inner dictionary
178 should have keys that are statistic names (`str`) with
179 values that are some sort of scalar (`int` or `float` are
180 the mostly likely types).
182 Returns
183 -------
184 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]]
185 A dictionary indexed by the amplifier name, containing
186 dictionaries of the verification criteria.
187 success : `bool`
188 A boolean indicating if all tests have passed.
190 """
191 verifyStats = {}
192 success = True
194 # DMTN-101 Test 10.Z: confirm inter-chip scatter is small.
195 verifyStats['SCATTER'] = bool(statisticsDictionary['EXP']['SCATTER'] <= 0.05)
197 success = bool(np.all(list(verifyStats.values())))
199 return {'EXP': verifyStats}, bool(success)