Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

# This file is part of ip_isr. 

# 

# Developed for the LSST Data Management System. 

# This product includes software developed by the LSST Project 

# (https://www.lsst.org). 

# See the COPYRIGHT file at the top-level directory of this distribution 

# for details of code ownership. 

# 

# This program is free software: you can redistribute it and/or modify 

# it under the terms of the GNU General Public License as published by 

# the Free Software Foundation, either version 3 of the License, or 

# (at your option) any later version. 

# 

# This program is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

# GNU General Public License for more details. 

# 

# You should have received a copy of the GNU General Public License 

# along with this program. If not, see <https://www.gnu.org/licenses/>. 

# 

import os 

import errno 

 

import lsst.afw.display.rgb as afwRGB 

import lsst.afw.math as afwMath 

import lsst.pex.config as pexConfig 

 

 

class IsrQaFlatnessConfig(pexConfig.Config): 

meshX = pexConfig.Field( 

dtype=int, 

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

default=256, 

) 

meshY = pexConfig.Field( 

dtype=int, 

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

default=256, 

) 

doClip = pexConfig.Field( 

dtype=bool, 

doc="Clip outliers for flatness statistics?", 

default=True, 

) 

clipSigma = pexConfig.Field( 

dtype=float, 

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

default=3.0, 

) 

nIter = pexConfig.Field( 

dtype=int, 

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

default=3, 

) 

 

 

class IsrQaConfig(pexConfig.Config): 

saveStats = pexConfig.Field( 

dtype=bool, 

doc="Calculate ISR statistics while processing?", 

default=True, 

) 

 

flatness = pexConfig.ConfigField( 

dtype=IsrQaFlatnessConfig, 

doc="Flatness statistics configuration.", 

) 

 

doWriteOss = pexConfig.Field( 

dtype=bool, 

doc="Write overscan subtracted image?", 

default=False, 

) 

doThumbnailOss = pexConfig.Field( 

dtype=bool, 

doc="Write overscan subtracted thumbnail?", 

default=False, 

) 

 

doWriteFlattened = pexConfig.Field( 

dtype=bool, 

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

default=False, 

) 

doThumbnailFlattened = pexConfig.Field( 

dtype=bool, 

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

default=False, 

) 

 

thumbnailBinning = pexConfig.Field( 

dtype=int, 

doc="Thumbnail binning factor.", 

default=4, 

) 

thumbnailStdev = pexConfig.Field( 

dtype=float, 

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

default=3.0, 

) 

thumbnailRange = pexConfig.Field( 

dtype=float, 

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

default=5.0, 

) 

thumbnailQ = pexConfig.Field( 

dtype=float, 

doc="Softening parameter for thumbnail mapping.", 

default=20.0, 

) 

thumbnailSatBorder = pexConfig.Field( 

dtype=int, 

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

default=2, 

) 

 

 

def makeThumbnail(exposure, isrQaConfig=None): 

"""Create a snapshot thumbnail from input exposure. 

 

The output thumbnail image is constructed based on the parameters 

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

only mapping method used. 

 

Parameters 

---------- 

exposure : `lsst.afw.image.Exposure` 

The exposure to be converted into a thumbnail. 

isrQaConfig : `Config` 

Configuration object containing all parameters to control the 

thumbnail generation. 

 

Returns 

------- 

rgbImage : `numpy.ndarray` 

Binned and scaled version of the exposure, converted to an 

integer array to allow it to be written as PNG. 

""" 

if isrQaConfig is not None: 

binning = isrQaConfig.thumbnailBinning 

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

 

statsCtrl = afwMath.StatisticsControl() 

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

stats = afwMath.makeStatistics(binnedImage, 

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

 

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

 

if isrQaConfig.thumbnailSatBorder: 

afwRGB.replaceSaturatedPixels(binnedImage, binnedImage, binnedImage, 

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

 

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

rgbImage = asinhMap.makeRgbImage(binnedImage) 

 

return rgbImage 

 

 

def writeThumbnail(dataRef, thumb, dataset): 

"""Write snapshot thumbnail to disk. 

 

Parameters 

---------- 

dataRef : `daf.persistence.butlerSubset.ButlerDataRef` 

Butler dataref to use to construct the output filename. 

thumb : `numpy.ndarray` 

Binned and scaled image to be written as a PNG. 

dataset : `str` 

String containing the dataset for this thumbnail. 

 

Raises 

------ 

OSError 

Raised if the output directory cannot be created and does not 

exist. 

""" 

filename = dataRef.get(dataset + "_filename")[0] 

directory = os.path.dirname(filename) 

if not os.path.exists(directory): 

try: 

os.makedirs(directory) 

except OSError as e: 

# Don't fail if directory exists due to race condition. 

if e.errno != errno.EEXIST: 

raise e 

afwRGB.writeRGB(filename, thumb)