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_deblendedFlux_schema", 

118 storageClass="SourceCatalog" 

119 ) 

120 templateCatalogs = cT.Output( 

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

122 name="{outputCoaddName}Coadd_deblendedFlux", 

123 storageClass="SourceCatalog", 

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

125 multiple=True 

126 ) 

127 

128 

129class DeblendCoaddSourcesMultiConfig(PipelineTaskConfig, 

130 pipelineConnections=DeblendCoaddSourcesMultiConnections): 

131 multibandDeblend = ConfigurableField( 

132 target=ScarletDeblendTask, 

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

134 ) 

135 

136 

137class DeblendCoaddSourcesBaseTask(PipelineTask): 

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

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

140 schema = initInputs["inputSchema"].schema 

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

142 self.schemaMapper = afwTable.SchemaMapper(schema) 

143 self.schemaMapper.addMinimalSchema(schema) 

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

145 

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

147 inputs = butlerQC.get(inputRefs) 

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

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

150 outputs = self.run(**inputs) 

151 butlerQC.put(outputs, outputRefs) 

152 

153 def _makeSourceCatalog(self, mergedDetections, idFactory): 

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

155 sources = afwTable.SourceCatalog(table) 

156 sources.extend(mergedDetections, self.schemaMapper) 

157 return sources 

158 

159 

160class DeblendCoaddSourcesSingleTask(DeblendCoaddSourcesBaseTask): 

161 ConfigClass = DeblendCoaddSourcesSingleConfig 

162 _DefaultName = "deblendCoaddSourcesSingle" 

163 

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

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

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

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

168 

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

170 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

171 self.singleBandDeblend.run(coadd, sources) 

172 if not sources.isContiguous(): 

173 sources = sources.copy(deep=True) 

174 return Struct(measureCatalog=sources) 

175 

176 

177class DeblendCoaddSourcesMultiTask(DeblendCoaddSourcesBaseTask): 

178 ConfigClass = DeblendCoaddSourcesMultiConfig 

179 _DefaultName = "deblendCoaddSourcesMulti" 

180 

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

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

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

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

185 

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

187 inputs = butlerQC.get(inputRefs) 

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

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

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

191 outputs = self.run(**inputs) 

192 sortedTemplateCatalogs = [] 

193 for outRef in outputRefs.templateCatalogs: 

194 band = outRef.dataId['band'] 

195 sortedTemplateCatalogs.append(outputs.templateCatalogs[band]) 

196 outputs.templateCatalogs = sortedTemplateCatalogs 

197 butlerQC.put(outputs, outputRefs) 

198 

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

200 sources = self._makeSourceCatalog(mergedDetections, idFactory) 

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

202 templateCatalogs = self.multibandDeblend.run(multiExposure, sources) 

203 retStruct = Struct(templateCatalogs=templateCatalogs) 

204 return retStruct