Coverage for python/lsst/pipe/tasks/coaddBase.py: 52%

52 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-07-12 10:09 +0000

1# This file is part of pipe_tasks. 

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/>. 

21 

22__all__ = ["CoaddBaseTask", "makeSkyInfo"] 

23 

24import lsst.pex.config as pexConfig 

25import lsst.afw.image as afwImage 

26import lsst.pipe.base as pipeBase 

27import lsst.meas.algorithms as measAlg 

28 

29from lsst.meas.algorithms import ScaleVarianceTask 

30from .selectImages import PsfWcsSelectImagesTask 

31from .coaddInputRecorder import CoaddInputRecorderTask 

32 

33 

34class CoaddBaseConfig(pexConfig.Config): 

35 """Configuration parameters for CoaddBaseTask 

36 

37 Configuration parameters shared between MakeCoaddTempExp and AssembleCoadd 

38 """ 

39 

40 coaddName = pexConfig.Field( 

41 doc="Coadd name: typically one of deep or goodSeeing.", 

42 dtype=str, 

43 default="deep", 

44 ) 

45 select = pexConfig.ConfigurableField( 

46 doc="Image selection subtask.", 

47 target=PsfWcsSelectImagesTask, 

48 ) 

49 badMaskPlanes = pexConfig.ListField( 

50 dtype=str, 

51 doc="Mask planes that, if set, the associated pixel should not be included in the coaddTempExp.", 

52 default=("NO_DATA",), 

53 ) 

54 inputRecorder = pexConfig.ConfigurableField( 

55 doc="Subtask that helps fill CoaddInputs catalogs added to the final Exposure", 

56 target=CoaddInputRecorderTask 

57 ) 

58 doPsfMatch = pexConfig.Field( 

59 dtype=bool, 

60 doc="Match to modelPsf? Sets makePsfMatched=True, makeDirect=False", 

61 deprecated="This field is no longer used. Will be removed after v27.", # TODO: DM-39841 

62 default=False 

63 ) 

64 modelPsf = measAlg.GaussianPsfFactory.makeField(doc="Model Psf factory") 

65 doApplyExternalPhotoCalib = pexConfig.Field( 

66 dtype=bool, 

67 default=False, 

68 doc=("Whether to apply external photometric calibration via an " 

69 "`lsst.afw.image.PhotoCalib` object. Uses the " 

70 "`externalPhotoCalibName` field to determine which calibration " 

71 "to load.") 

72 ) 

73 useGlobalExternalPhotoCalib = pexConfig.Field( 

74 dtype=bool, 

75 default=True, 

76 doc=("When using doApplyExternalPhotoCalib, use 'global' calibrations " 

77 "that are not run per-tract. When False, use per-tract photometric " 

78 "calibration files.") 

79 ) 

80 externalPhotoCalibName = pexConfig.ChoiceField( 

81 # TODO: Remove this config with the removal of Gen2 in DM-20572. 

82 dtype=str, 

83 doc=("Type of external PhotoCalib if `doApplyExternalPhotoCalib` is True. " 

84 "This field is only used for Gen2 middleware."), 

85 default="jointcal", 

86 allowed={ 

87 "jointcal": "Use jointcal_photoCalib", 

88 "fgcm": "Use fgcm_photoCalib", 

89 "fgcm_tract": "Use fgcm_tract_photoCalib" 

90 }, 

91 deprecated="This configuration is no longer used, and will be removed after v25.0", 

92 ) 

93 doApplyExternalSkyWcs = pexConfig.Field( 

94 dtype=bool, 

95 default=False, 

96 doc=("Whether to apply external astrometric calibration via an " 

97 "`lsst.afw.geom.SkyWcs` object. Uses `externalSkyWcsName` " 

98 "field to determine which calibration to load.") 

99 ) 

100 useGlobalExternalSkyWcs = pexConfig.Field( 

101 dtype=bool, 

102 default=True, 

103 doc=("When using doApplyExternalSkyWcs, use 'global' calibrations " 

104 "that are not run per-tract. When False, use per-tract wcs " 

105 "files.") 

106 ) 

107 externalSkyWcsName = pexConfig.ChoiceField( 

108 # TODO: Remove this config with the removal of Gen2 in DM-20572. 

109 dtype=str, 

110 doc=("Type of external SkyWcs if `doApplyExternalSkyWcs` is True. " 

111 "This field is only used for Gen2 middleware."), 

112 default="jointcal", 

113 allowed={ 

114 "jointcal": "Use jointcal_wcs" 

115 }, 

116 deprecated="This configuration is no longer used, and will be removed after v25.0", 

117 ) 

118 includeCalibVar = pexConfig.Field( 

119 dtype=bool, 

120 doc="Add photometric calibration variance to warp variance plane.", 

121 default=False 

122 ) 

123 matchingKernelSize = pexConfig.Field( 123 ↛ exitline 123 didn't jump to the function exit

124 dtype=int, 

125 doc="Size in pixels of matching kernel. Must be odd.", 

126 default=21, 

127 check=lambda x: x % 2 == 1 

128 ) 

129 

130 

131class CoaddBaseTask(pipeBase.PipelineTask): 

132 """Base class for coaddition. 

133 

134 Subclasses must specify _DefaultName 

135 """ 

136 

137 ConfigClass = CoaddBaseConfig 

138 

139 def __init__(self, **kwargs): 

140 super().__init__(**kwargs) 

141 self.makeSubtask("select") 

142 self.makeSubtask("inputRecorder") 

143 

144 def getTempExpDatasetName(self, warpType="direct"): 

145 """Return warp name for given warpType and task config 

146 

147 Parameters 

148 ---------- 

149 warpType : `str` 

150 Either 'direct' or 'psfMatched'. 

151 

152 Returns 

153 ------- 

154 WarpDatasetName : `str` 

155 """ 

156 return self.config.coaddName + "Coadd_" + warpType + "Warp" 

157 

158 def getBadPixelMask(self): 

159 """Convenience method to provide the bitmask from the mask plane names 

160 """ 

161 return afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes) 

162 

163 

164def makeSkyInfo(skyMap, tractId, patchId): 

165 """Constructs SkyInfo used by coaddition tasks for multiple 

166 patchId formats. 

167 

168 Parameters 

169 ---------- 

170 skyMap : `lsst.skyMap.SkyMap` 

171 Sky map. 

172 tractId : `int` 

173 The ID of the tract. 

174 patchId : `str` or `int` or `tuple` of `int` 

175 Either Gen2-style comma delimited string (e.g. '4,5'), 

176 tuple of integers (e.g (4, 5), Gen3-style integer. 

177 

178 Returns 

179 ------- 

180 makeSkyInfo : `lsst.pipe.base.Struct` 

181 pipe_base Struct with attributes: 

182 

183 ``skyMap`` 

184 Sky map (`lsst.skyMap.SkyMap`). 

185 ``tractInfo`` 

186 Information for chosen tract of sky map (`lsst.skyMap.TractInfo`). 

187 ``patchInfo`` 

188 Information about chosen patch of tract (`lsst.skyMap.PatchInfo`). 

189 ``wcs`` 

190 WCS of tract (`lsst.afw.image.SkyWcs`). 

191 ``bbox`` 

192 Outer bbox of patch, as an geom Box2I (`lsst.afw.geom.Box2I`). 

193 """ 

194 tractInfo = skyMap[tractId] 

195 

196 if isinstance(patchId, str) and ',' in patchId: 

197 # patch format is "xIndex,yIndex" 

198 patchIndex = tuple(int(i) for i in patchId.split(",")) 

199 else: 

200 patchIndex = patchId 

201 

202 patchInfo = tractInfo.getPatchInfo(patchIndex) 

203 

204 return pipeBase.Struct( 

205 skyMap=skyMap, 

206 tractInfo=tractInfo, 

207 patchInfo=patchInfo, 

208 wcs=tractInfo.getWcs(), 

209 bbox=patchInfo.getOuterBBox(), 

210 ) 

211 

212 

213def scaleVariance(maskedImage, maskPlanes, log=None): 

214 """Scale the variance in a maskedImage 

215 

216 This is deprecated. Use the ScaleVarianceTask instead. 

217 

218 Parameters 

219 ---------- 

220 maskedImage : `lsst.afw.image.MaskedImage` 

221 MaskedImage to operate on; variance will be scaled. 

222 maskPlanes : `list` 

223 List of mask planes for pixels to reject. 

224 log : `Unknown` 

225 Log for reporting the renormalization factor; or None. 

226 

227 Returns 

228 ------- 

229 task.run : `Unknown` 

230 Renormalization factor. 

231 

232 Notes 

233 ----- 

234 The variance plane in a convolved or warped image (or a coadd derived 

235 from warped images) does not accurately reflect the noise properties of 

236 the image because variance has been lost to covariance. This function 

237 attempts to correct for this by scaling the variance plane to match 

238 the observed variance in the image. This is not perfect (because we're 

239 not tracking the covariance) but it's simple and is often good enough. 

240 """ 

241 config = ScaleVarianceTask.ConfigClass() 

242 config.maskPlanes = maskPlanes 

243 task = ScaleVarianceTask(config=config, name="scaleVariance", log=log) 

244 return task.run(maskedImage) 

245 

246 

247def reorderAndPadList(inputList, inputKeys, outputKeys, padWith=None): 

248 """Match the order of one list to another, padding if necessary 

249 

250 Parameters 

251 ---------- 

252 inputList : `list` 

253 List to be reordered and padded. Elements can be any type. 

254 inputKeys : `iterable` 

255 Iterable of values to be compared with outputKeys. Length must match `inputList`. 

256 outputKeys : `iterable` 

257 Iterable of values to be compared with inputKeys. 

258 padWith : `Unknown` 

259 Any value to be inserted where inputKey not in outputKeys. 

260 

261 Returns 

262 ------- 

263 outputList : `list` 

264 Copy of inputList reordered per outputKeys and padded with `padWith` 

265 so that the length matches length of outputKeys. 

266 """ 

267 outputList = [] 

268 for d in outputKeys: 

269 if d in inputKeys: 

270 outputList.append(inputList[inputKeys.index(d)]) 

271 else: 

272 outputList.append(padWith) 

273 return outputList