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