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# 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 ABC, 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 

28 

29 

30class StrayLightConfig(Config): 

31 doRotatorAngleCorrection = Field( 

32 dtype=bool, 

33 doc="", 

34 default=False, 

35 ) 

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

37 filters = ListField( 

38 dtype=str, 

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

40 default=[], 

41 ) 

42 

43 

44class StrayLightTask(Task): 

45 """Remove stray light from instruments. 

46 

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

48 """ 

49 ConfigClass = StrayLightConfig 

50 _DefaultName = "isrStrayLight" 

51 

52 def readIsrData(self, dataRef, rawExposure): 

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

54 stray light in the given exposure. 

55 

56 Parameters 

57 ---------- 

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

59 Butler reference of the detector data to be processed 

60 rawExposure : `afw.image.Exposure` 

61 The raw exposure that will later be corrected with the 

62 retrieved calibration data; should not be modified in this 

63 method. 

64 

65 Returns 

66 ------- 

67 straylightData : `object`, optional 

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

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

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

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

72 performed even if there is nothing to read. 

73 

74 Notes 

75 ----- 

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

77 Middleware (i.e. CmdLineTask). 

78 """ 

79 return None 

80 

81 def check(self, exposure): 

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

83 

84 Parameters 

85 ---------- 

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

87 Exposure to correct. 

88 """ 

89 return False 

90 

91 def run(self, exposure, strayLightData): 

92 """Correct stray light. 

93 

94 Parameters 

95 ---------- 

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

97 Exposure to correct. 

98 strayLightData : `object`, optional 

99 An opaque object that contains any calibration data used to 

100 correct for stray light. 

101 """ 

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

103 

104 def checkFilter(self, exposure): 

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

106 

107 Parameters 

108 ---------- 

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

110 Exposure to check the filter of. 

111 

112 Returns 

113 ------- 

114 needsFringe : `bool` 

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

116 configuration, and should have the fringe applied. 

117 """ 

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

119 

120 

121class StrayLightData(ABC): 

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

123 """ 

124 

125 @abstractmethod 

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

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

128 

129 Parameters 

130 ---------- 

131 angle_begin : `float` 

132 Instrument rotation angle at the start of the exposure. 

133 angle_end : `float`, optional 

134 Instrument rotation angle at the end of the exposure. 

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

136 `angle_start`. 

137 

138 Returns 

139 ------- 

140 array : `numpy.ndarray` 

141 A stray-light background image for this exposure. 

142 """ 

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