Coverage for python/lsst/ip/isr/straylight.py: 84%

25 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-07-20 03:12 -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/>. 

21from abc import abstractmethod 

22from typing import Optional 

23 

24from lsst.pex.config import Config, Field, ListField 

25from lsst.pipe.base import Task 

26from lsst.geom import Angle 

27from .isrFunctions import checkFilter 

28from .calibType import IsrCalib 

29 

30 

31class StrayLightConfig(Config): 

32 doRotatorAngleCorrection = Field( 

33 dtype=bool, 

34 doc="", 

35 default=False, 

36 ) 

37 # TODO DM-28093: change the doc to specify that these are physical labels 

38 filters = ListField( 

39 dtype=str, 

40 doc="Filters that need straylight correction.", 

41 default=[], 

42 ) 

43 

44 

45class StrayLightTask(Task): 

46 """Remove stray light from instruments. 

47 

48 This is a dummy task to be retargeted with an camera-specific version. 

49 """ 

50 ConfigClass = StrayLightConfig 

51 _DefaultName = "isrStrayLight" 

52 

53 def readIsrData(self, dataRef, rawExposure): 

54 """Read and return calibration products relevant for correcting 

55 stray light in the given exposure. 

56 

57 Parameters 

58 ---------- 

59 dataRef : `daf.persistence.butlerSubset.ButlerDataRef` 

60 Butler reference of the detector data to be processed 

61 rawExposure : `afw.image.Exposure` 

62 The raw exposure that will later be corrected with the 

63 retrieved calibration data; should not be modified in this 

64 method. 

65 

66 Returns 

67 ------- 

68 straylightData : `object`, optional 

69 An opaque object that should be passed as the second argument to 

70 the `run` method. If `None`, no stray light correction will be 

71 performed for the given image. Any other object (e.g. `True`) 

72 may be used to signal that stray light correction should be 

73 performed even if there is nothing to read. 

74 

75 Notes 

76 ----- 

77 This method will be called only when `IsrTask` is run by the Gen2 

78 Middleware (i.e. CmdLineTask). 

79 """ 

80 return None 

81 

82 def check(self, exposure): 

83 """Check if stray light correction should be run. 

84 

85 Parameters 

86 ---------- 

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

88 Exposure to correct. 

89 """ 

90 return False 

91 

92 def run(self, exposure, strayLightData): 

93 """Correct stray light. 

94 

95 Parameters 

96 ---------- 

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

98 Exposure to correct. 

99 strayLightData : `object`, optional 

100 An opaque object that contains any calibration data used to 

101 correct for stray light. 

102 """ 

103 raise NotImplementedError("Must be implemented by subclasses.") 

104 

105 def checkFilter(self, exposure): 

106 """Check whether we should fringe-subtract the science exposure. 

107 

108 Parameters 

109 ---------- 

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

111 Exposure to check the filter of. 

112 

113 Returns 

114 ------- 

115 needsFringe : `bool` 

116 If True, then the exposure has a filter listed in the 

117 configuration, and should have the fringe applied. 

118 """ 

119 return checkFilter(exposure, self.config.filters, log=self.log) 

120 

121 

122class StrayLightData(IsrCalib): 

123 """An abstract base class for rotator-dependent stray light information. 

124 """ 

125 

126 @abstractmethod 

127 def evaluate(self, angle_start: Angle, angle_end: Optional[Angle] = None): 

128 """Get a stray light array for a range of rotator angles. 

129 

130 Parameters 

131 ---------- 

132 angle_begin : `float` 

133 Instrument rotation angle at the start of the exposure. 

134 angle_end : `float`, optional 

135 Instrument rotation angle at the end of the exposure. 

136 If not provided, the returned array will reflect a snapshot at 

137 `angle_start`. 

138 

139 Returns 

140 ------- 

141 array : `numpy.ndarray` 

142 A stray-light background image for this exposure. 

143 """ 

144 raise NotImplementedError("Must be implemented by subclasses.")