Coverage for python/lsst/ip/isr/isrQa.py: 62%

34 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2022-09-03 04:03 -0700

1# This file is part of ip_isr. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://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 <https://www.gnu.org/licenses/>. 

21# 

22 

23import lsst.afw.display.rgb as afwRGB 

24import lsst.afw.math as afwMath 

25import lsst.pex.config as pexConfig 

26 

27 

28class IsrQaFlatnessConfig(pexConfig.Config): 

29 meshX = pexConfig.Field( 

30 dtype=int, 

31 doc="Mesh size in X for flatness statistics", 

32 default=256, 

33 ) 

34 meshY = pexConfig.Field( 

35 dtype=int, 

36 doc="Mesh size in Y for flatness statistics", 

37 default=256, 

38 ) 

39 doClip = pexConfig.Field( 

40 dtype=bool, 

41 doc="Clip outliers for flatness statistics?", 

42 default=True, 

43 ) 

44 clipSigma = pexConfig.Field( 

45 dtype=float, 

46 doc="Number of sigma deviant a pixel must be to be clipped from flatness statistics.", 

47 default=3.0, 

48 ) 

49 nIter = pexConfig.Field( 

50 dtype=int, 

51 doc="Number of iterations used for outlier clipping in flatness statistics.", 

52 default=3, 

53 ) 

54 

55 

56class IsrQaConfig(pexConfig.Config): 

57 saveStats = pexConfig.Field( 

58 dtype=bool, 

59 doc="Calculate ISR statistics while processing?", 

60 default=True, 

61 ) 

62 

63 flatness = pexConfig.ConfigField( 

64 dtype=IsrQaFlatnessConfig, 

65 doc="Flatness statistics configuration.", 

66 ) 

67 

68 doWriteOss = pexConfig.Field( 

69 dtype=bool, 

70 doc="Write overscan subtracted image?", 

71 default=False, 

72 ) 

73 doThumbnailOss = pexConfig.Field( 

74 dtype=bool, 

75 doc="Write overscan subtracted thumbnail?", 

76 default=False, 

77 ) 

78 

79 doWriteFlattened = pexConfig.Field( 

80 dtype=bool, 

81 doc="Write image after flat-field correction?", 

82 default=False, 

83 ) 

84 doThumbnailFlattened = pexConfig.Field( 

85 dtype=bool, 

86 doc="Write thumbnail after flat-field correction?", 

87 default=False, 

88 ) 

89 

90 thumbnailBinning = pexConfig.Field( 

91 dtype=int, 

92 doc="Thumbnail binning factor.", 

93 default=4, 

94 ) 

95 thumbnailStdev = pexConfig.Field( 

96 dtype=float, 

97 doc="Number of sigma below the background to set the thumbnail minimum.", 

98 default=3.0, 

99 ) 

100 thumbnailRange = pexConfig.Field( 

101 dtype=float, 

102 doc="Total range in sigma for thumbnail mapping.", 

103 default=5.0, 

104 ) 

105 thumbnailQ = pexConfig.Field( 

106 dtype=float, 

107 doc="Softening parameter for thumbnail mapping.", 

108 default=20.0, 

109 ) 

110 thumbnailSatBorder = pexConfig.Field( 

111 dtype=int, 

112 doc="Width of border around saturated pixels in thumbnail.", 

113 default=2, 

114 ) 

115 

116 

117def makeThumbnail(exposure, isrQaConfig=None): 

118 """Create a snapshot thumbnail from input exposure. 

119 

120 The output thumbnail image is constructed based on the parameters 

121 in the configuration file. Currently, the asinh mapping is the 

122 only mapping method used. 

123 

124 Parameters 

125 ---------- 

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

127 The exposure to be converted into a thumbnail. 

128 isrQaConfig : `Config` 

129 Configuration object containing all parameters to control the 

130 thumbnail generation. 

131 

132 Returns 

133 ------- 

134 rgbImage : `numpy.ndarray` 

135 Binned and scaled version of the exposure, converted to an 

136 integer array to allow it to be written as PNG. 

137 """ 

138 if isrQaConfig is not None: 

139 binning = isrQaConfig.thumbnailBinning 

140 binnedImage = afwMath.binImage(exposure.getMaskedImage(), binning, binning, afwMath.MEAN) 

141 

142 statsCtrl = afwMath.StatisticsControl() 

143 statsCtrl.setAndMask(binnedImage.getMask().getPlaneBitMask(["SAT", "BAD", "INTRP"])) 

144 stats = afwMath.makeStatistics(binnedImage, 

145 afwMath.MEDIAN | afwMath.STDEVCLIP | afwMath.MAX, statsCtrl) 

146 

147 low = stats.getValue(afwMath.MEDIAN) - isrQaConfig.thumbnailStdev*stats.getValue(afwMath.STDEVCLIP) 

148 

149 if isrQaConfig.thumbnailSatBorder: 

150 afwRGB.replaceSaturatedPixels(binnedImage, binnedImage, binnedImage, 

151 isrQaConfig.thumbnailSatBorder, stats.getValue(afwMath.MAX)) 

152 

153 asinhMap = afwRGB.AsinhMapping(low, isrQaConfig.thumbnailRange, Q=isrQaConfig.thumbnailQ) 

154 rgbImage = asinhMap.makeRgbImage(binnedImage) 

155 

156 return rgbImage