23 from __future__
import absolute_import, division, print_function
24 from builtins
import range
27 import lsst.pex.config
33 CompareWarpAssembleCoaddTask)
34 from .mockObject
import MockObjectTask
35 from .mockObservation
import MockObservationTask
36 from .mockSelect
import MockSelectImagesTask
40 makeSkyMap = lsst.pex.config.ConfigurableField(
41 doc=
"SkyMap builder subtask",
44 mockObject = lsst.pex.config.ConfigurableField(
45 doc=
"Subtask that generates and draws the objects/sources in the mock images",
48 mockObservation = lsst.pex.config.ConfigurableField(
49 doc=
"Subtask that generates the Wcs, Psf, Calib, etc. of mock images",
50 target=MockObservationTask
52 coaddName = lsst.pex.config.Field(
53 doc=
"Coadd name used as a prefix for other datasets",
58 nObservations = lsst.pex.config.Field(
59 doc=
"Number of mock observations to generate.",
64 edgeBuffer = lsst.pex.config.Field(
65 doc=(
"Number of pixels by which to grow object bounding boxes when determining whether they land " 66 " completely on a generated image"),
72 def setupSkyMapPatches(self, nPatches=2, patchSize=400, pixelScale=0.2*lsst.afw.geom.arcseconds):
74 Set the nested [discrete] skymap config parameters such that the full tract 75 has nPatches x nPatches patches of the given size and pixel scale. 77 self.
makeSkyMap.skyMap[
'discrete'].patchInnerDimensions = [patchSize, patchSize]
78 self.
makeSkyMap.skyMap[
'discrete'].pixelScale = pixelScale.asArcseconds()
81 radius = (0.5 * nPatches - 0.49) * patchSize * pixelScale.asDegrees()
82 self.
makeSkyMap.skyMap[
'discrete'].radiusList = [radius]
86 self.
makeSkyMap.skyMap[
'discrete'].raList = [90.0]
87 self.
makeSkyMap.skyMap[
'discrete'].decList = [0.0]
88 self.
makeSkyMap.skyMap[
'discrete'].patchBorder = 10
89 self.
makeSkyMap.skyMap[
'discrete'].projection =
"TAN" 90 self.
makeSkyMap.skyMap[
'discrete'].tractOverlap = 0.0
95 """MockCoaddTask is a driver task for creating mock coadds. As opposed to more realistic 96 simulations, MockCoadd generates and uses extremely simple "toy" data that can be used to more 97 rigorously test the behavior of high-level task code because the expected results are 98 more easily predicted. In particular, calexps are generated directly from the truth catalog, 99 and contain only zero-noise stars that are created using the same Psf, Calib, and Wcs that will 100 be attached to the mock calexp. 102 In addition to creating the mock calexps and truth catalogs, MockCoadd also contains driver 103 code to run the MakeSkyMap, MakeCoaddTempExp, and AssembleCoadd tasks on the mock calexps, 104 and code to directly create a mock coadd image using CoaddPsf, which can be compared to the 105 output of the regular coadd tasks to check that the coadd code and CoaddPsf are consistent. 107 Note that aside from MakeSkyMapTask, the coadd tasks are *not* subtasks of MockCoaddTasks, 108 and their configs are not part of MockCoaddConfig; these are created locally within 109 MockCoaddTask methods when needed, as not all coadd task config options are appropriate 110 for the mock data generated by MockCoadd. 113 ConfigClass = MockCoaddConfig
115 _DefaultName =
"MockCoadd" 118 """Construct a MockCoaddTask and the subtasks used for generating skymaps, objects, 119 and observations (i.e. calexp parameters). 121 lsst.pipe.base.CmdLineTask.__init__(self, **kwds)
122 self.makeSubtask(
"makeSkyMap")
123 self.makeSubtask(
"mockObject")
124 self.makeSubtask(
"mockObservation")
125 self.
schema = lsst.afw.table.SimpleTable.makeMinimalSchema()
126 self.
objectIdKey = self.
schema.addField(
"objectId", type=
"L", doc=
"foreign key to truth catalog")
128 doc=
"foreign key to observation catalog")
130 "centroidInBBox", type=
"Flag",
131 doc=
"set if this source's center position is inside the generated image's bbox" 134 "partialOverlap", type=
"Flag",
135 doc=
"set if this source was not completely inside the generated image" 139 """Build the skymap for the mock dataset.""" 140 return self.makeSkyMap.
run(butler.dataRef(self.config.coaddName +
"Coadd_skyMap")).skyMap
143 """Create and save (if butler is not None) a truth catalog containing all the mock objects. 145 Must be run after buildSkyMap. 147 Most of the work is delegated to the mockObject subtask. 150 skyMap = butler.get(self.config.coaddName +
"Coadd_skyMap")
151 catalog = self.mockObject.
run(tractInfo=skyMap[tract])
152 if butler
is not None:
153 butler.put(catalog,
"truth", tract=tract)
157 """Create and save (if butler is not None) an ExposureCatalog of simulated observations, 158 containing the Psfs, Wcss, Calibs, etc. of the calexps to be simulated. 160 Must be run after buildSkyMap. 162 Most of the work is delegated to the mockObservation subtask. 165 skyMap = butler.get(self.config.coaddName +
"Coadd_skyMap")
167 camera = butler.get(
"camera")
168 catalog = self.mockObservation.
run(butler=butler,
169 n=self.config.nObservations, camera=camera,
170 tractInfo=skyMap[tract])
171 if butler
is not None:
172 butler.put(catalog,
"observations", tract=tract)
176 """Use the truth catalog and observation catalog to create and save (if butler is not None) 177 mock calexps and an ExposureCatalog ('simsrc') that contains information about which objects 178 appear partially or fully in each exposure. 180 Must be run after buildTruthCatalog and buildObservationCatalog. 182 if obsCatalog
is None:
183 obsCatalog = butler.get(
"observations", tract=tract)
184 if truthCatalog
is None:
185 truthCatalog = butler.get(
"truth", tract=tract)
186 ccdKey = obsCatalog.getSchema().find(
"ccd").key
187 visitKey = obsCatalog.getSchema().find(
"visit").key
188 simSrcCatalog = lsst.afw.table.SimpleCatalog(self.
schema)
189 for obsRecord
in obsCatalog:
190 ccd = obsRecord.getI(ccdKey)
191 visit = obsRecord.getI(visitKey)
192 self.log.info(
"Generating image for visit={visit}, ccd={ccd}".format(ccd=ccd, visit=visit))
193 exposure = lsst.afw.image.ExposureF(obsRecord.getBBox())
194 exposure.setCalib(obsRecord.getCalib())
195 exposure.setWcs(obsRecord.getWcs())
196 exposure.setPsf(obsRecord.getPsf())
197 exposure.getInfo().setApCorrMap(obsRecord.getApCorrMap())
198 for truthRecord
in truthCatalog:
199 status = self.mockObject.drawSource(truthRecord, exposure, buffer=self.config.edgeBuffer)
201 simSrcRecord = simSrcCatalog.addNew()
202 simSrcRecord.setCoord(truthRecord.getCoord())
203 simSrcRecord.setL(self.
objectIdKey, truthRecord.getId())
205 simSrcRecord.setFlag(self.
centroidInBBoxKey, obsRecord.contains(truthRecord.getCoord()))
207 self.log.info(
" added object {id}".format(id=truthRecord.getId()))
208 exposure.getMaskedImage().getVariance().set(1.0)
209 if butler
is not None:
210 butler.put(exposure,
"calexp", ccd=ccd, visit=visit)
211 if butler
is not None:
212 butler.put(simSrcCatalog,
"simsrc", tract=tract)
216 """Convenience function that calls buildSkyMap, buildObservationCatalog, buildTruthCatalog, 217 and buildInputImages. 222 simSrcCatalog = self.
buildInputImages(butler, obsCatalog=observations, truthCatalog=truth)
225 """Helper function to create a Coadd task with configuration appropriate for the simulations. 227 MockCoaddTask does not include MakeCoaddTempExpTask or AssembleCoaddTask as subtasks, because 228 we want explicit control over their configs, rather than leaving this up to the user. 229 However, we have to install our own SelectImages task for both of these, so it made sense 230 to have a single method that would create one of these two tasks, set the config values we 231 want, and install the custom SelectImagesTask. 234 config.coaddName = self.config.coaddName
235 config.select.retarget(MockSelectImagesTask)
236 if cls == MakeCoaddTempExpTask:
237 config.bgSubtracted =
True 238 config.makeDirect =
True 239 config.makePsfMatched =
True 240 config.modelPsf.defaultFwhm = 9
241 config.modelPsf.addWing =
False 242 config.warpAndPsfMatch.psfMatch.kernel[
'AL'].scaleByFwhm =
False 243 config.warpAndPsfMatch.psfMatch.kernel[
'AL'].kernelSize = 25
244 config.warpAndPsfMatch.psfMatch.kernel[
'AL'].sizeCellX = 64
245 config.warpAndPsfMatch.psfMatch.kernel[
'AL'].sizeCellY = 64
247 elif cls
in [AssembleCoaddTask, SafeClipAssembleCoaddTask, CompareWarpAssembleCoaddTask]:
248 if assemblePsfMatched:
249 config.warpType =
'psfMatched' 250 if cls != AssembleCoaddTask:
251 config.doWrite =
False 252 if cls == CompareWarpAssembleCoaddTask:
253 config.assembleStaticSkyModel.select.retarget(MockSelectImagesTask)
257 """Generator that iterates over the patches in a tract, yielding dataRefs. 259 nPatchX, nPatchY = tractInfo.getNumPatches()
260 for iPatchX
in range(nPatchX):
261 for iPatchY
in range(nPatchY):
262 patchRef = butler.dataRef(self.config.coaddName +
"Coadd",
263 tract=tractInfo.getId(), patch=
"%d,%d" % (iPatchX, iPatchY),
268 """Run the coadd tasks (MakeCoaddTempExp and AssembleCoadd) on the mock data. 270 Must be run after buildInputImages. 271 Makes both direct and PSF-matched coadds 274 skyMap = butler.get(self.config.coaddName +
"Coadd_skyMap")
275 tractInfo = skyMap[tract]
276 makeCoaddTempExpTask = self.
makeCoaddTask(MakeCoaddTempExpTask)
277 directCoaddTaskList = []
278 for coaddTask
in [SafeClipAssembleCoaddTask, CompareWarpAssembleCoaddTask, AssembleCoaddTask]:
280 assemblePsfMatchedCoaddTask = self.
makeCoaddTask(AssembleCoaddTask, assemblePsfMatched=
True)
282 makeCoaddTempExpTask.run(patchRef)
284 for directCoaddTask
in directCoaddTaskList:
285 directCoaddTask.run(patchRef)
286 assemblePsfMatchedCoaddTask.run(patchRef)
289 """Directly create a simulation of the coadd, using the CoaddPsf (and ModelPsf) 290 of the direct (and psfMatched) coadd exposure and the truth catalog. 292 Must be run after buildCoadd. 294 if truthCatalog
is None:
295 truthCatalog = butler.get(
"truth", tract=tract)
297 skyMap = butler.get(self.config.coaddName +
"Coadd_skyMap")
298 tractInfo = skyMap[tract]
299 tractWcs = tractInfo.getWcs()
302 for dataProduct
in [
"Coadd",
"CoaddPsfMatched"]:
303 exposure = patchRef.get(self.config.coaddName + dataProduct, immediate=
True)
304 exposure.getMaskedImage().getImage().set(0.0)
305 coaddPsf = lsst.meas.algorithms.CoaddPsf(
306 exposure.getInfo().getCoaddInputs().ccds, exposure.getWcs()
308 exposure.setPsf(coaddPsf)
309 for truthRecord
in truthCatalog:
310 self.mockObject.drawSource(truthRecord, exposure, buffer=0)
311 patchRef.put(exposure, self.config.coaddName + dataProduct +
"_mock")
314 """Convenience function to create and run MockCoaddTask with default settings. 316 from .simpleMapper
import makeDataRepo
319 task.buildAllInputs(butler)
320 task.buildCoadd(butler)
321 task.buildMockCoadd(butler)
def buildTruthCatalog(self, butler=None, skyMap=None, tract=0)
def buildObservationCatalog(self, butler=None, skyMap=None, tract=0, camera=None)
def makeCoaddTask(self, cls, assemblePsfMatched=False)
def buildAllInputs(self, butler)
def setupSkyMapPatches(self, nPatches=2, patchSize=400, pixelScale=0.2 *lsst.afw.geom.arcseconds)
def buildSkyMap(self, butler)
def buildInputImages(self, butler, obsCatalog=None, truthCatalog=None, tract=0)
def buildMockCoadd(self, butler, truthCatalog=None, skyMap=None, tract=0)
def iterPatchRefs(self, butler, tractInfo)
def buildCoadd(self, butler, skyMap=None, tract=0)