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

22from lsst.pipe.base import (Struct, PipelineTask, PipelineTaskConfig, PipelineTaskConnections) 

23import lsst.pipe.base.connectionTypes as cT 

24 

25from lsst.pex.config import ConfigurableField 

26from lsst.meas.deblender import SourceDeblendTask 

27from lsst.meas.extensions.scarlet import ScarletDeblendTask 

28 

29import lsst.afw.image as afwImage 

30import lsst.afw.table as afwTable 

31 

32__all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask", 

33 "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask") 

34 

35 

36deblendBaseTemplates = {"inputCoaddName": "deep", "outputCoaddName": "deep"} 

37 

38 

39class DeblendCoaddSourceSingleConnections(PipelineTaskConnections, 

40 dimensions=("tract", "patch", "band", "skymap"), 

41 defaultTemplates=deblendBaseTemplates): 

42 inputSchema = cT.InitInput( 

43 doc="Input schema to use in the deblend catalog", 

44 name="{inputCoaddName}Coadd_mergeDet_schema", 

45 storageClass="SourceCatalog" 

46 ) 

47 peakSchema = cT.InitInput( 

48 doc="Schema of the footprint peak catalogs", 

49 name="{inputCoaddName}Coadd_peak_schema", 

50 storageClass="PeakCatalog" 

51 ) 

52 mergedDetections = cT.Input( 

53 doc="Detection catalog merged across bands", 

54 name="{inputCoaddName}Coadd_mergeDet", 

55 storageClass="SourceCatalog", 

56 dimensions=("tract", "patch", "skymap") 

57 ) 

58 coadd = cT.Input( 

59 doc="Exposure on which to run deblending", 

60 name="{inputCoaddName}Coadd_calexp", 

61 storageClass="ExposureF", 

62 dimensions=("tract", "patch", "band", "skymap") 

63 ) 

64 measureCatalog = cT.Output( 

65 doc="The output measurement catalog of deblended sources", 

66 name="{outputCoaddName}Coadd_deblendedFlux", 

67 storageClass="SourceCatalog", 

68 dimensions=("tract", "patch", "band", "skymap") 

69 ) 

70 outputSchema = cT.InitOutput( 

71 doc="Output of the schema used in deblending task", 

72 name="{outputCoaddName}Coadd_deblendedFlux_schema", 

73 storageClass="SourceCatalog" 

74 ) 

75 

76 def setDefaults(self): 

77 super().setDefaults() 

78 self.singleBandDeblend.propagateAllPeaks = True 

79 

80 

81class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig, 

82 pipelineConnections=DeblendCoaddSourceSingleConnections): 

83 singleBandDeblend = ConfigurableField( 

84 target=SourceDeblendTask, 

85 doc="Task to deblend an image in one band" 

86 ) 

87 

88 

89class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections, 

90 dimensions=("tract", "patch", "skymap"), 

91 defaultTemplates=deblendBaseTemplates): 

92 inputSchema = cT.InitInput( 

93 doc="Input schema to use in the deblend catalog", 

94 name="{inputCoaddName}Coadd_mergeDet_schema", 

95 storageClass="SourceCatalog" 

96 ) 

97 peakSchema = cT.InitInput( 

98 doc="Schema of the footprint peak catalogs", 

99 name="{inputCoaddName}Coadd_peak_schema", 

100 storageClass="PeakCatalog" 

101 ) 

102 mergedDetections = cT.Input( 

103 doc="Detection catalog merged across bands", 

104 name="{inputCoaddName}Coadd_mergeDet", 

105 storageClass="SourceCatalog", 

106 dimensions=("tract", "patch", "skymap") 

107 ) 

108 coadds = cT.Input( 

109 doc="Exposure on which to run deblending", 

110 name="{inputCoaddName}Coadd_calexp", 

111 storageClass="ExposureF", 

112 multiple=True, 

113 dimensions=("tract", "patch", "band", "skymap") 

114 ) 

115 outputSchema = cT.InitOutput( 

116 doc="Output of the schema used in deblending task", 

117 name="{outputCoaddName}Coadd_deblendedModel_schema", 

118 storageClass="SourceCatalog" 

119 ) 

120 fluxCatalogs = cT.Output( 

121 doc="Flux catalogs produced by multiband deblending, not written " 

122 "if conserve flux is turned off", 

123 name="{outputCoaddName}Coadd_deblendedFlux", 

124 storageClass="SourceCatalog", 

125 dimensions=("tract", "patch", "band", "skymap") 

126 ) 

127 templateCatalogs = cT.Output( 

128 doc="Template catalogs produced by multiband deblending", 

129 name="{outputCoaddName}Coadd_deblendedModel", 

130 storageClass="SourceCatalog", 

131 dimensions=("tract", "patch", "band", "skymap") 

132 ) 

133 

134 def __init__(self, *, config=None): 

135 super().__init__(config=config) 

136 if not config.multibandDeblend.conserveFlux: 

137 self.outputs -= set(("fluxCatalogs",)) 

138 

139 

140class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig, 

141 pipelineConnections=DeblendCoaddSourcesMultiConnections): 

142 multibandDeblend = ConfigurableField( 

143 target=ScarletDeblendTask, 

144 doc="Task to deblend an images in multiple bands" 

145 ) 

146 

147 

148class DeblendCoaddSourcesBaseTask(PipelineTask): 

149 def __init__(self, initInputs, **kwargs): 

150 super().__init__(initInputs=initInputs, **kwargs) 

151 schema = initInputs["inputSchema"].schema 

152 self.peakSchema = initInputs["peakSchema"].schema 

153 self.schemaMapper = afwTable.SchemaMapper(schema) 

154 self.schemaMapper.addMinimalSchema(schema) 

155 self.schema = self.schemaMapper.getOutputSchema() 

156 

157 def runQuantum(self, butlerQC, inputRefs, outputRefs): 

158 inputs = butlerQC.get(inputRefs) 

159 packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True) 

160 inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits) 

161 outputs = self.run(**inputs) 

162 butlerQC.put(outputs, outputRefs) 

163 

164 def _makeSourceCatalog(self, mergedDetections, idFactory): 

165 table = afwTable.SourceTable.make(self.schema, idFactory) 

166 sources = afwTable.SourceCatalog(table) 

167 sources.extend(mergedDetections, self.schemaMapper) 

168 return sources 

169 

170 

171class DeblendCoaddSourcesSingleTask(DeblendCoaddSourcesBaseTask): 

172 ConfigClass = DeblendCoaddSourcesSingleConfig 

173 _DefaultName = "deblendCoaddSourcesSingle" 

174 

175 def __init__(self, initInputs, **kwargs): 

176 super().__init__(initInputs=initInputs, **kwargs) 

177 self.makeSubtask("singleBandDeblend", schema=self.schema, peakSchema=self.peakSchema) 

178 self.outputSchema = afwTable.SourceCatalog(self.schema) 

179 

180 def run(self, coadd, mergedDetections, idFactory): 

181 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

182 self.singleBandDeblend.run(coadd, sources) 

183 if not sources.isContiguous(): 

184 sources = sources.copy(deep=True) 

185 return Struct(measureCatalog=sources) 

186 

187 

188class DeblendCoaddSourcesMultiTask(DeblendCoaddSourcesBaseTask): 

189 ConfigClass = DeblendCoaddSourcesMultiConfig 

190 _DefaultName = "deblendCoaddSourcesMulti" 

191 

192 def __init__(self, initInputs, **kwargs): 

193 super().__init__(initInputs=initInputs, **kwargs) 

194 self.makeSubtask("multibandDeblend", schema=self.schema, peakSchema=self.peakSchema) 

195 self.outputSchema = afwTable.SourceCatalog(self.schema) 

196 

197 def runQuantum(self, butlerQC, inputRefs, outputRefs): 

198 inputs = butlerQC.get(inputRefs) 

199 packedId, maxBits = butlerQC.quantum.dataId.pack("tract_patch", returnMaxBits=True) 

200 inputs["idFactory"] = afwTable.IdFactory.makeSource(packedId, 64 - maxBits) 

201 inputs["filters"] = [dRef.dataId["band"] for dRef in inputRefs.coadds] 

202 outputs = self.run(**inputs) 

203 butlerQC.put(outputs, outputRefs) 

204 

205 def run(self, coadds, filters, mergedDetections, idFactory): 

206 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

207 multiExposure = afwImage.MultibandExposure.fromExposures(filters, coadds) 

208 fluxCatalogs, templateCatalogs = self.multibandDeblend.run(multiExposure, sources) 

209 retStruct = Struct(templateCatalogs) 

210 if self.config.multibandDeblend.conserveFlux: 

211 retStruct.fluxCatalogs = fluxCatalogs 

212 return retStruct