Coverage for python/lsst/obs/cfht/cfhtIsrTask.py: 23%

46 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2022-06-26 09:24 +0000

1 

2__all__ = ["CfhtIsrTaskConfig", "CfhtIsrTask"] 

3 

4import numpy as np 

5 

6import lsst.pex.config as pexConfig 

7from lsst.ip.isr import IsrTask 

8 

9 

10class CfhtIsrTaskConfig(IsrTask.ConfigClass): 

11 safe = pexConfig.Field( 

12 dtype=float, 

13 doc="Safety margin for CFHT sensors gain determination", 

14 default=0.95, 

15 ) 

16 

17 def setDefaults(self): 

18 IsrTask.ConfigClass.setDefaults(self) 

19 

20 

21class CfhtIsrTask(IsrTask): 

22 ConfigClass = CfhtIsrTaskConfig 

23 

24 def run(self, ccdExposure, bias=None, linearizer=None, dark=None, flat=None, defects=None, 

25 fringes=None, bfKernel=None, **kwds): 

26 """Perform instrument signature removal on an exposure 

27 

28 Steps include: 

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

30 - Perform CCD assembly 

31 - Interpolate over defects, saturated pixels and all NaNs 

32 - Persist the ISR-corrected exposure as "postISRCCD" if 

33 config.doWrite is True 

34 

35 Parameters 

36 ---------- 

37 ccdExposure : `lsst.afw.image.Exposure` 

38 Detector data. 

39 bias : `lsst.afw.image.exposure` 

40 Exposure of bias frame. 

41 linearizer : `lsst.ip.isr.LinearizeBase` callable 

42 Linearizing functor; a subclass of lsst.ip.isr.LinearizeBase. 

43 dark : `lsst.afw.image.exposure` 

44 Exposure of dark frame. 

45 flat : `lsst.afw.image.exposure` 

46 Exposure of flatfield. 

47 defects : `list` 

48 list of detects 

49 fringes : `lsst.afw.image.Exposure` or list `lsst.afw.image.Exposure` 

50 exposure of fringe frame or list of fringe exposure 

51 bfKernel : None 

52 kernel used for brighter-fatter correction; currently unsupported 

53 **kwds : `dict` 

54 additional kwargs forwarded to IsrTask.run. 

55 

56 Returns 

57 ------- 

58 struct : `lsst.pipe.base.Struct` with fields: 

59 - exposure: the exposure after application of ISR 

60 """ 

61 if bfKernel is not None: 

62 raise ValueError("CFHT ISR does not currently support brighter-fatter correction.") 

63 

64 ccd = ccdExposure.getDetector() 

65 floatExposure = self.convertIntToFloat(ccdExposure) 

66 metadata = floatExposure.getMetadata() 

67 

68 # Detect saturation 

69 # Saturation values recorded in the fits hader is not reliable, try to 

70 # estimate it from the pixel values. 

71 # Find the peak location in the high end part the pixel values' 

72 # histogram and set the saturation level at safe * (peak location) 

73 # where safe is a configurable parameter (typically 0.95) 

74 image = floatExposure.getMaskedImage().getImage() 

75 imageArray = image.getArray() 

76 maxValue = np.max(imageArray) 

77 if maxValue > 60000.0: 

78 hist, bin_edges = np.histogram(imageArray.ravel(), bins=100, range=(60000.0, maxValue+1.0)) 

79 saturate = int(self.config.safe*bin_edges[np.argmax(hist)]) 

80 else: 

81 saturate = metadata.getScalar("SATURATE") 

82 self.log.info("Saturation set to %d", saturate) 

83 

84 tempCcd = ccd.rebuild() 

85 tempCcd.clear() 

86 for amp in ccd: 

87 tempAmp = amp.rebuild() 

88 tempAmp.setSaturation(saturate) 

89 if tempAmp.getName() == "A": 

90 tempAmp.setGain(metadata.getScalar("GAINA")) 

91 rdnA = metadata.getScalar("RDNOISEA") 

92 # Check if the noise value is making sense for this amp. If 

93 # not, replace with value stored in RDNOISE slot. This change 

94 # is necessary to process some old CFHT images 

95 # (visit : 7xxxxx) where RDNOISEA/B = 65535 

96 if rdnA > 60000.0: 

97 rdnA = metadata.getScalar("RDNOISE") 

98 tempAmp.setReadNoise(rdnA) 

99 elif tempAmp.getName() == "B": 

100 tempAmp.setGain(metadata.getScalar("GAINB")) 

101 rdnB = metadata.getScalar("RDNOISEB") 

102 # Check if the noise value is making sense for this amp. 

103 # If not, replace with value 

104 # stored in RDNOISE slot. This change is necessary to process 

105 # some old CFHT images 

106 # (visit : 7xxxxx) where RDNOISEA/B = 65535 

107 if rdnB > 60000.0: 

108 rdnB = metadata.getScalar("RDNOISE") 

109 tempAmp.setReadNoise(rdnB) 

110 else: 

111 raise ValueError("Unexpected amplifier name : %s"%(amp.getName())) 

112 tempCcd.append(tempAmp) 

113 

114 ccd = tempCcd.finish() 

115 ccdExposure.setDetector(ccd) 

116 return IsrTask.run(self, 

117 ccdExposure=ccdExposure, 

118 bias=bias, 

119 linearizer=linearizer, 

120 dark=dark, 

121 flat=flat, 

122 defects=defects, 

123 fringes=fringes, 

124 **kwds 

125 )