Coverage for python/lsst/cp/verify/verifyDefects.py: 23%

41 statements  

« prev     ^ index     » next       coverage.py v7.2.1, created at 2023-03-12 03:58 -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 scipy 

23 

24from .verifyStats import CpVerifyStatsConfig, CpVerifyStatsTask, CpVerifyStatsConnections 

25 

26 

27__all__ = ['CpVerifyDefectsConfig', 'CpVerifyDefectsTask'] 

28 

29 

30class CpVerifyDefectsConfig(CpVerifyStatsConfig, 

31 pipelineConnections=CpVerifyStatsConnections): 

32 """Inherits from base CpVerifyStatsConfig. 

33 """ 

34 

35 def setDefaults(self): 

36 super().setDefaults() 

37 self.maskNameList = ['BAD'] # noqa F821 

38 

39 self.imageStatKeywords = {'DEFECT_PIXELS': 'NMASKED', # noqa F821 

40 'OUTLIERS': 'NCLIPPED', 

41 'MEDIAN': 'MEDIAN', 

42 'STDEV': 'STDEVCLIP', 

43 'MIN': 'MIN', 

44 'MAX': 'MAX', } 

45 self.unmaskedImageStatKeywords = {'UNMASKED_MIN': 'MIN', # noqa F821 

46 'UNMASKED_MAX': 'MAX', 

47 'UNMASKED_OUTLIERS': 'NCLIPPED', } 

48 

49 

50class CpVerifyDefectsTask(CpVerifyStatsTask): 

51 """Defects verification sub-class, implementing the verify method. 

52 

53 This also applies additional image processing statistics. 

54 """ 

55 ConfigClass = CpVerifyDefectsConfig 

56 _DefaultName = 'cpVerifyDefects' 

57 

58 def imageStatistics(self, exposure, statControl): 

59 """Measure additional defect statistics. 

60 

61 This calls the parent class method first, then adds additional 

62 measurements. 

63 

64 Parameters 

65 ---------- 

66 exposure : `lsst.afw.image.Exposure` 

67 Exposure containing the ISR processed data to measure. 

68 statControl : `lsst.afw.math.StatControl` 

69 Statistics control object with parameters defined by 

70 the config. 

71 

72 Returns 

73 ------- 

74 outputStatistics : `dict` [`str`, `dict` [`str`, scalar]] 

75 A dictionary indexed by the amplifier name, containing 

76 dictionaries of the statistics measured and their values. 

77 """ 

78 outputStatistics = super().imageStatistics(exposure, statControl) 

79 

80 # Is this a useful test? It saves having to do chi^2 fits, 

81 # which are going to be biased by the bulk of points. 

82 for amp in exposure.getDetector(): 

83 ampName = amp.getName() 

84 ampExp = exposure.Factory(exposure, amp.getBBox()) 

85 

86 normImage = ampExp.getImage() 

87 normArray = normImage.getArray() 

88 

89 normArray -= outputStatistics[ampName]['MEDIAN'] 

90 normArray /= outputStatistics[ampName]['STDEV'] 

91 

92 probability = scipy.stats.norm.pdf(normArray) 

93 outliers = np.where(probability < 1.0 / probability.size, 1.0, 0.0) 

94 outputStatistics[ampName]['STAT_OUTLIERS'] = np.sum(outliers) 

95 

96 return outputStatistics 

97 

98 def verify(self, exposure, statisticsDict): 

99 """Verify that the measured statistics meet the verification criteria. 

100 

101 Parameters 

102 ---------- 

103 exposure : `lsst.afw.image.Exposure` 

104 The exposure the statistics are from. 

105 statisticsDictionary : `dict` [`str`, `dict` [`str`, scalar]], 

106 Dictionary of measured statistics. The inner dictionary 

107 should have keys that are statistic names (`str`) with 

108 values that are some sort of scalar (`int` or `float` are 

109 the mostly likely types). 

110 

111 Returns 

112 ------- 

113 outputStatistics : `dict` [`str`, `dict` [`str`, `bool`]] 

114 A dictionary indexed by the amplifier name, containing 

115 dictionaries of the verification criteria. 

116 success : `bool` 

117 A boolean indicating if all tests have passed. 

118 """ 

119 ampStats = statisticsDict['AMP'] 

120 verifyStats = {} 

121 success = True 

122 for ampName, stats in ampStats.items(): 

123 verify = {} 

124 

125 # These are not defined in DMTN-101 yet. 

126 verify['OUTLIERS'] = bool(stats['UNMASKED_OUTLIERS'] > stats['OUTLIERS']) 

127 verify['MIN'] = bool(stats['MIN'] >= stats['UNMASKED_MIN']) 

128 verify['MAX'] = bool(stats['MAX'] <= stats['UNMASKED_MAX']) 

129 

130 verify['PROB_TEST'] = bool(stats['STAT_OUTLIERS'] == stats['DEFECT_PIXELS']) 

131 

132 verify['SUCCESS'] = bool(np.all(list(verify.values()))) 

133 if verify['SUCCESS'] is False: 

134 success = False 

135 

136 verifyStats[ampName] = verify 

137 

138 return {'AMP': verifyStats}, bool(success)