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

# 

# LSST Data Management System 

# Copyright 2008-2016 AURA/LSST. 

# 

# This product includes software developed by the 

# LSST Project (http://www.lsst.org/). 

# 

# 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 LSST License Statement and 

# the GNU General Public License along with this program. If not, 

# see <http://www.lsstcorp.org/LegalNotices/>. 

# 

 

import numpy 

 

import lsst.afw.image 

import lsst.ip.isr as ip_isr 

import lsst.pipe.base as pipe_base 

from lsst.obs.base import MakeRawVisitInfo 

 

 

class MonocamIsrTask(ip_isr.IsrTask, MakeRawVisitInfo): 

 

@pipe_base.timeMethod 

def run(self, ccdExposure, bias=None, dark=None, flat=None, defects=None, fringes=None, bfKernel=None, 

linearizer=None): 

"""!Perform instrument signature removal on an exposure 

 

Steps include: 

- Detect saturation, apply overscan correction, bias, dark and flat 

- Perform CCD assembly 

- Interpolate over defects, saturated pixels and all NaNs 

 

@param[in] ccdExposure -- lsst.afw.image.exposure of detector data 

@param[in] bias -- exposure of bias frame 

@param[in] dark -- exposure of dark frame 

@param[in] flat -- exposure of flatfield 

@param[in] defects -- list of detects 

@param[in] fringes -- a pipe_base.Struct with field fringes containing 

exposure of fringe frame or list of fringe 

exposure 

@param[in] bfKernel -- kernel for brighter-fatter correction 

@param[in] linearizer -- object for applying linearization 

 

@return a pipe_base.Struct with field: 

- exposure 

""" 

 

# Validate Input 

if self.config.doBias and bias is None: 

raise RuntimeError("Must supply a bias exposure if config.doBias True") 

if self.config.doDark and dark is None: 

raise RuntimeError("Must supply a dark exposure if config.doDark True") 

if self.config.doFlat and flat is None: 

raise RuntimeError("Must supply a flat exposure if config.doFlat True") 

if self.config.doBrighterFatter and bfKernel is None: 

raise RuntimeError("Must supply a kernel if config.doBrighterFatter True") 

if fringes is None: 

fringes = pipe_base.Struct(fringes=None) 

if self.config.doFringe and not isinstance(fringes, pipe_base.Struct): 

raise RuntimeError("Must supply fringe exposure as a pipe_base.Struct") 

 

defects = [] if defects is None else defects 

 

ccd = ccdExposure.getDetector() 

 

if self.config.doBias: 

self.biasCorrection(ccdExposure, bias) 

 

if self.config.doBrighterFatter: 

self.brighterFatterCorrection(ccdExposure, bfKernel, 

self.config.brighterFatterMaxIter, 

self.config.brighterFatterThreshold, 

self.config.brighterFatterApplyGain, 

) 

 

if self.config.doDark: 

self.darkCorrection(ccdExposure, dark) 

 

for amp in ccd: 

# if ccdExposure is one amp, check for coverage to prevent 

# performing ops multiple times 

if ccdExposure.getBBox().contains(amp.getBBox()): 

ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox()) 

self.updateVariance(ampExposure, amp) 

 

# Don't trust the variance not to be negative (over-subtraction of 

# dark?) 

# Where it's negative, set it to a robust measure of the variance on 

# the image. 

variance = ccdExposure.getMaskedImage().getVariance().getArray() 

quartiles = numpy.percentile(ccdExposure.getMaskedImage().getImage().getArray(), [25.0, 75.0]) 

stdev = 0.74*(quartiles[1] - quartiles[0]) 

variance[:] = numpy.where(variance > 0, variance, stdev**2) 

 

if self.config.doFringe and not self.config.fringeAfterFlat: 

self.fringe.run(ccdExposure, **fringes.getDict()) 

 

if self.config.doFlat: 

self.flatCorrection(ccdExposure, flat) 

 

self.maskAndInterpDefect(ccdExposure, defects) 

 

self.saturationInterpolation(ccdExposure) 

 

self.maskAndInterpNan(ccdExposure) 

 

if self.config.doFringe and self.config.fringeAfterFlat: 

self.fringe.run(ccdExposure, **fringes.getDict()) 

 

ccdExposure.setPhotoCalib(lsst.afw.image.makePhotoCalibFromCalibZeroPoint(self.config.fluxMag0T1, 0)) 

 

return pipe_base.Struct( 

exposure=ccdExposure, 

) 

 

@pipe_base.timeMethod 

def runDataRef(self, sensorRef): 

"""!Perform instrument signature removal on a ButlerDataRef of a Sensor 

 

- Read in necessary detrending/isr/calibration data 

- Process raw exposure in run() 

- Persist the ISR-corrected exposure as "postISRCCD" if config.doWrite 

is True 

 

@param[in] sensorRef -- daf.persistence.butlerSubset.ButlerDataRef 

of the detector data to be processed 

@return a pipe_base.Struct with fields: 

- exposure: the exposure after application of ISR 

""" 

self.log.info("Performing ISR on sensor %s" % (sensorRef.dataId)) 

# We should probably loop over this using the butler. 

ampDict = {} 

for channel in range(16): 

sensorRef.dataId['channel'] = channel+1 # to get the correct channel 

ampExposure = sensorRef.get('raw_amp', immediate=True) 

# ampExposure = sensorRef.get('raw', immediate=True) 

ampExposure = self.convertIntToFloat(ampExposure) 

# assumes amps are in order of the channels 

amp = ampExposure.getDetector()[channel] 

 

self.saturationDetection(ampExposure, amp) 

self.overscanCorrection(ampExposure, amp) 

ampDict[amp.getName()] = ampExposure 

 

ccdExposure = self.assembleCcd.assembleCcd(ampDict) 

 

isrData = self.readIsrData(sensorRef, ccdExposure) 

 

result = self.run(ccdExposure, **isrData.getDict()) 

 

if self.config.doWrite: 

sensorRef.put(result.exposure, "postISRCCD") 

 

return result