Coverage for python/lsst/cp/verify/verifyDark.py: 18%
39 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-05 12:36 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-05 12:36 -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
23from .verifyStats import CpVerifyStatsConfig, CpVerifyStatsTask, CpVerifyStatsConnections
26__all__ = ['CpVerifyDarkConfig', 'CpVerifyDarkTask']
29class CpVerifyDarkConfig(CpVerifyStatsConfig,
30 pipelineConnections=CpVerifyStatsConnections):
31 """Inherits from base CpVerifyStatsConfig.
32 """
34 def setDefaults(self):
35 super().setDefaults()
36 self.imageStatKeywords = {'MEAN': 'MEAN', # noqa F841
37 'NOISE': 'STDEVCLIP', }
38 self.crImageStatKeywords = {'CR_NOISE': 'STDEV', } # noqa F841
39 self.metadataStatKeywords = {'RESIDUAL STDEV': 'AMP', } # noqa F841
42class CpVerifyDarkTask(CpVerifyStatsTask):
43 """Dark verification sub-class, implementing the verify method.
44 """
45 ConfigClass = CpVerifyDarkConfig
46 _DefaultName = 'cpVerifyDark'
48 def verify(self, exposure, statisticsDict):
49 """Verify that the measured statistics meet the verification criteria.
51 Parameters
52 ----------
53 exposure : `lsst.afw.image.Exposure`
54 The exposure the statistics are from.
55 statisticsDictionary : `dict` [`str`, `dict` [`str`, scalar]],
56 Dictionary of measured statistics. The inner dictionary
57 should have keys that are statistic names (`str`) with
58 values that are some sort of scalar (`int` or `float` are
59 the mostly likely types).
61 Returns
62 -------
63 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]]
64 A dictionary indexed by the amplifier name, containing
65 dictionaries of the verification criteria.
66 success : `bool`
67 A boolean indicating if all tests have passed.
68 """
69 detector = exposure.getDetector()
70 ampStats = statisticsDict['AMP']
71 metadataStats = statisticsDict['METADATA']
73 verifyStats = {}
74 success = True
75 for ampName, stats in ampStats.items():
76 verify = {}
77 readNoiseMatch = True
78 # DMTN-101 Test 5.2: Mean is 0.0:
79 verify['MEAN'] = bool(np.abs(stats['MEAN']) < stats['NOISE'])
81 # DMTN-101 Test 5.3: Clipped mean matches readNoise
82 # The read noise from the detector object may not match
83 # the read noise of the camera taking the images. If
84 # possible, pull the residual remaining after the serial
85 # overscan has been overscan corrected from the task
86 # metadata (stored with the key f"RESIDUAL STDEV {ampName}").
87 # This should provide a measurement of the actual read
88 # noise in the exposure. A test below (that does not
89 # trigger failure) will note if the detector read noise
90 # matched the measured read noise.
91 readNoise = detector[ampName].getReadNoise()
92 if 'RESIDUAL STDEV' in metadataStats and ampName in metadataStats['RESIDUAL STDEV']:
93 overscanReadNoise = metadataStats['RESIDUAL STDEV'][ampName]
94 if overscanReadNoise:
95 if ((overscanReadNoise - readNoise)/readNoise > 0.05):
96 readNoiseMatch = False
97 readNoise = overscanReadNoise
99 verify['NOISE'] = bool(np.abs(stats['NOISE'] - readNoise)/readNoise <= 0.05)
101 # DMTN-101 Test 5.4: CR rejection matches clipped mean
102 verify['CR_NOISE'] = bool(np.abs(stats['NOISE'] - stats['CR_NOISE'])/stats['CR_NOISE'] <= 0.05)
104 # Confirm this hasn't triggered a raise condition.
105 if 'FORCE_FAILURE' in stats:
106 verify['PROCESSING'] = False
108 verify['SUCCESS'] = bool(np.all(list(verify.values())))
109 if verify['SUCCESS'] is False:
110 success = False
111 # This is a notice so we can track the read noise
112 # stability. We shouldn't fail on it.
113 verify['READ_NOISE_CONSISTENT'] = readNoiseMatch
115 verifyStats[ampName] = verify
117 return {'AMP': verifyStats}, bool(success)