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

27 

28import lsst.afw.image as afwImage 

29import lsst.afw.table as afwTable 

30 

31__all__ = ("DeblendCoaddSourcesSingleConfig", "DeblendCoaddSourcesSingleTask", 

32 "DeblendCoaddSourcesMultiConfig", "DeblendCoaddSourcesMultiTask") 

33 

34 

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

36 

37 

38class DeblendCoaddSourceSingleConnections(PipelineTaskConnections, 

39 dimensions=("tract", "patch", "abstract_filter", "skymap"), 

40 defaultTemplates=deblendBaseTemplates): 

41 inputSchema = cT.InitInput( 

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

43 name="{inputCoaddName}Coadd_mergeDet_schema", 

44 storageClass="SourceCatalog" 

45 ) 

46 peakSchema = cT.InitInput( 

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

48 name="{inputCoaddName}Coadd_peak_schema", 

49 storageClass="PeakCatalog" 

50 ) 

51 mergedDetections = cT.Input( 

52 doc="Detection catalog merged across bands", 

53 name="{inputCoaddName}Coadd_mergeDet", 

54 storageClass="SourceCatalog", 

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

56 ) 

57 coadd = cT.Input( 

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

59 name="{inputCoaddName}Coadd_calexp", 

60 storageClass="ExposureF", 

61 dimensions=("tract", "patch", "abstract_filter", "skymap") 

62 ) 

63 measureCatalog = cT.Output( 

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

65 name="{outputCoaddName}Coadd_deblendedFlux", 

66 storageClass="SourceCatalog", 

67 dimensions=("tract", "patch", "abstract_filter", "skymap") 

68 ) 

69 outputSchema = cT.InitOutput( 

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

71 name="{outputCoaddName}Coadd_deblendedFlux_schema", 

72 storageClass="SourceCatalog" 

73 ) 

74 

75 def setDefaults(self): 

76 super().setDefaults() 

77 self.singleBandDeblend.propagateAllPeaks = True 

78 

79 

80class DeblendCoaddSourcesSingleConfig(PipelineTaskConfig, 

81 pipelineConnections=DeblendCoaddSourceSingleConnections): 

82 singleBandDeblend = ConfigurableField( 

83 target=SourceDeblendTask, 

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

85 ) 

86 

87 

88class DeblendCoaddSourcesMultiConnections(PipelineTaskConnections, 

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

90 defaultTemplates=deblendBaseTemplates): 

91 inputSchema = cT.InitInput( 

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

93 name="{inputCoaddName}Coadd_mergeDet_schema", 

94 storageClass="SourceCatalog" 

95 ) 

96 peakSchema = cT.InitInput( 

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

98 name="{inputCoaddName}Coadd_peak_schema", 

99 storageClass="PeakCatalog" 

100 ) 

101 mergedDetections = cT.Input( 

102 doc="Detection catalog merged across bands", 

103 name="{inputCoaddName}Coadd_mergeDet", 

104 storageClass="SourceCatalog", 

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

106 ) 

107 coadds = cT.Input( 

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

109 name="{inputCoaddName}Coadd_calexp", 

110 storageClass="ExposureF", 

111 multiple=True, 

112 dimensions=("tract", "patch", "abstract_filter", "skymap") 

113 ) 

114 outputSchema = cT.InitOutput( 

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

116 name="{outputCoaddName}Coadd_deblendedModel_schema", 

117 storageClass="SourceCatalog" 

118 ) 

119 fluxCatalogs = cT.Output( 

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

121 "if conserve flux is turned off", 

122 name="{outputCoaddName}Coadd_deblendedFlux", 

123 storageClass="SourceCatalog", 

124 dimensions=("tract", "patch", "abstract_filter", "skymap") 

125 ) 

126 templateCatalogs = cT.Output( 

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

128 name="{outputCoaddName}Coadd_deblendedModel", 

129 storageClass="SourceCatalog", 

130 dimensions=("tract", "patch", "abstract_filter", "skymap") 

131 ) 

132 

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

134 super().__init__(config=config) 

135 if not config.multibandDeblend.conserveFlux: 

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

137 

138 

139class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig, 

140 pipelineConnections=DeblendCoaddSourcesMultiConnections): 

141 multibandDeblend = ConfigurableField( 

142 target=MultibandDeblendTask, 

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

144 ) 

145 

146 

147class DeblendCoaddSourcesBaseTask(PipelineTask): 

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

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

150 schema = initInputs["inputSchema"].schema 

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

152 self.schemaMapper = afwTable.SchemaMapper(schema) 

153 self.schemaMapper.addMinimalSchema(schema) 

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

155 

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

157 inputs = butlerQC.get(inputRefs) 

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

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

160 outputs = self.run(**inputs) 

161 butlerQC.put(outputs, outputRefs) 

162 

163 def _makeSourceCatalog(self, mergedDetections, idFactory): 

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

165 sources = afwTable.SourceCatalog(table) 

166 sources.extend(mergedDetections, self.schemaMapper) 

167 return sources 

168 

169 

170class DeblendCoaddSourcesSingleTask(DeblendCoaddSourcesBaseTask): 

171 ConfigClass = DeblendCoaddSourcesSingleConfig 

172 _DefaultName = "deblendCoaddSourcesSingle" 

173 

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

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

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

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

178 

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

180 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

181 self.singleBandDeblend.run(coadd, sources) 

182 if not sources.isContiguous(): 

183 sources = sources.copy(deep=True) 

184 return Struct(measureCatalog=sources) 

185 

186 

187class DeblendCoaddSourcesMultiTask(DeblendCoaddSourcesBaseTask): 

188 ConfigClass = DeblendCoaddSourcesMultiConfig 

189 _DefaultName = "deblendCoaddSourcesMulti" 

190 

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

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

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

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

195 

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

197 inputs = butlerQC.get(inputRefs) 

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

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

200 inputs["filters"] = [dRef.dataId["abstract_filter"] for dRef in inputRefs.coadds] 

201 outputs = self.run(**inputs) 

202 butlerQC.put(outputs, outputRefs) 

203 

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

205 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

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

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

208 retStruct = Struct(templateCatalogs) 

209 if self.config.multibandDeblend.conserveFlux: 

210 retStruct.fluxCatalogs = fluxCatalogs 

211 return retStruct