24 import lsst.pex.config
 
   30                                            CompareWarpAssembleCoaddTask)
 
   31 from .mockObject 
import MockObjectTask
 
   32 from .mockObservation 
import MockObservationTask
 
   33 from .mockSelect 
import MockSelectImagesTask
 
   37     makeSkyMap = lsst.pex.config.ConfigurableField(
 
   38         doc=
"SkyMap builder subtask",
 
   41     mockObject = lsst.pex.config.ConfigurableField(
 
   42         doc=
"Subtask that generates and draws the objects/sources in the mock images",
 
   45     mockObservation = lsst.pex.config.ConfigurableField(
 
   46         doc=
"Subtask that generates the Wcs, Psf, PhotoCalib, etc. of mock images",
 
   47         target=MockObservationTask
 
   49     coaddName = lsst.pex.config.Field(
 
   50         doc=
"Coadd name used as a prefix for other datasets",
 
   55     nObservations = lsst.pex.config.Field(
 
   56         doc=
"Number of mock observations to generate.",
 
   61     edgeBuffer = lsst.pex.config.Field(
 
   62         doc=(
"Number of pixels by which to grow object bounding boxes when determining whether they land " 
   63              " completely on a generated image"),
 
   71         Set the nested [discrete] skymap config parameters such that the full tract 
   72         has nPatches x nPatches patches of the given size and pixel scale. 
   74         self.
makeSkyMap.skyMap[
'discrete'].patchInnerDimensions = [patchSize, patchSize]
 
   75         self.
makeSkyMap.skyMap[
'discrete'].pixelScale = pixelScale.asArcseconds()
 
   78         radius = (0.5 * nPatches - 0.49) * patchSize * pixelScale.asDegrees()
 
   79         self.
makeSkyMap.skyMap[
'discrete'].radiusList = [radius]
 
   83         self.
makeSkyMap.skyMap[
'discrete'].raList = [90.0]
 
   84         self.
makeSkyMap.skyMap[
'discrete'].decList = [0.0]
 
   85         self.
makeSkyMap.skyMap[
'discrete'].patchBorder = 10
 
   86         self.
makeSkyMap.skyMap[
'discrete'].projection = 
"TAN" 
   87         self.
makeSkyMap.skyMap[
'discrete'].tractOverlap = 0.0
 
   92     """MockCoaddTask is a driver task for creating mock coadds.  As opposed to more realistic 
   93     simulations, MockCoadd generates and uses extremely simple "toy" data that can be used to more 
   94     rigorously test the behavior of high-level task code because the expected results are 
   95     more easily predicted.  In particular, calexps are generated directly from the truth catalog, 
   96     and contain only zero-noise stars that are created using the same Psf, PhotoCalib, and Wcs that will 
   97     be attached to the mock calexp. 
   99     In addition to creating the mock calexps and truth catalogs, MockCoadd also contains driver 
  100     code to run the MakeSkyMap, MakeCoaddTempExp, and AssembleCoadd tasks on the mock calexps, 
  101     and code to directly create a mock coadd image using CoaddPsf, which can be compared to the 
  102     output of the regular coadd tasks to check that the coadd code and CoaddPsf are consistent. 
  104     Note that aside from MakeSkyMapTask, the coadd tasks are *not* subtasks of MockCoaddTasks, 
  105     and their configs are not part of MockCoaddConfig; these are created locally within 
  106     MockCoaddTask methods when needed, as not all coadd task config options are appropriate 
  107     for the mock data generated by MockCoadd. 
  110     ConfigClass = MockCoaddConfig
 
  112     _DefaultName = 
"MockCoadd" 
  115         """Construct a MockCoaddTask and the subtasks used for generating skymaps, objects, 
  116         and observations (i.e. calexp parameters). 
  118         lsst.pipe.base.CmdLineTask.__init__(self, **kwds)
 
  123         self.
objectIdKey = self.
schema.addField(
"objectId", type=
"L", doc=
"foreign key to truth catalog")
 
  125                                                   doc=
"foreign key to observation catalog")
 
  127             "centroidInBBox", type=
"Flag",
 
  128             doc=
"set if this source's center position is inside the generated image's bbox" 
  131             "partialOverlap", type=
"Flag",
 
  132             doc=
"set if this source was not completely inside the generated image" 
  136         """Build the skymap for the mock dataset.""" 
  137         return self.makeSkyMap.runDataRef(butler.dataRef(self.
config.coaddName + 
"Coadd_skyMap")).skyMap
 
  140         """Create and save (if butler is not None) a truth catalog containing all the mock objects. 
  142         Must be run after buildSkyMap. 
  144         Most of the work is delegated to the mockObject subtask. 
  147             skyMap = butler.get(self.
config.coaddName + 
"Coadd_skyMap")
 
  148         catalog = self.mockObject.
run(tractInfo=skyMap[tract])
 
  149         if butler 
is not None:
 
  150             butler.put(catalog, 
"truth", tract=tract)
 
  154         """Create and save (if butler is not None) an ExposureCatalog of simulated observations, 
  155         containing the Psfs, Wcss, PhotoCalibs, etc. of the calexps to be simulated. 
  157         Must be run after buildSkyMap. 
  159         Most of the work is delegated to the mockObservation subtask. 
  162             skyMap = butler.get(self.
config.coaddName + 
"Coadd_skyMap")
 
  164             camera = butler.get(
"camera")
 
  165         catalog = self.mockObservation.
run(butler=butler,
 
  166                                            n=self.
config.nObservations, camera=camera,
 
  167                                            tractInfo=skyMap[tract])
 
  169         if butler 
is not None:
 
  170             butler.put(catalog, 
"observations", tract=tract)
 
  174         """Use the truth catalog and observation catalog to create and save (if butler is not None) 
  175         mock calexps and an ExposureCatalog ('simsrc') that contains information about which objects 
  176         appear partially or fully in each exposure. 
  178         Must be run after buildTruthCatalog and buildObservationCatalog. 
  180         if obsCatalog 
is None:
 
  181             obsCatalog = butler.get(
"observations", tract=tract)
 
  182         if truthCatalog 
is None:
 
  183             truthCatalog = butler.get(
"truth", tract=tract)
 
  184         ccdKey = obsCatalog.getSchema().find(
"ccd").key
 
  185         visitKey = obsCatalog.getSchema().find(
"visit").key
 
  187         for obsRecord 
in obsCatalog:
 
  188             ccd = obsRecord.getI(ccdKey)
 
  189             visit = obsRecord.getI(visitKey)
 
  190             self.
log.
info(
"Generating image for visit={visit}, ccd={ccd}".
format(ccd=ccd, visit=visit))
 
  191             exposure = lsst.afw.image.ExposureF(obsRecord.getBBox())
 
  194             exposure.maskedImage.image.array += 1e-8
 
  195             exposure.setPhotoCalib(obsRecord.getPhotoCalib())
 
  196             exposure.setWcs(obsRecord.getWcs())
 
  197             exposure.setPsf(obsRecord.getPsf())
 
  198             exposure.getInfo().setApCorrMap(obsRecord.getApCorrMap())
 
  199             exposure.getInfo().setTransmissionCurve(obsRecord.getTransmissionCurve())
 
  200             for truthRecord 
in truthCatalog:
 
  201                 status = self.mockObject.drawSource(truthRecord, exposure, buffer=self.
config.edgeBuffer)
 
  203                     simSrcRecord = simSrcCatalog.addNew()
 
  204                     simSrcRecord.setCoord(truthRecord.getCoord())
 
  205                     simSrcRecord.setL(self.
objectIdKey, truthRecord.getId())
 
  207                     simSrcRecord.setFlag(self.
centroidInBBoxKey, obsRecord.contains(truthRecord.getCoord()))
 
  209                     self.
log.
info(
"  added object {id}".
format(id=truthRecord.getId()))
 
  210             exposure.getMaskedImage().getVariance().
set(1.0)
 
  211             if butler 
is not None:
 
  212                 butler.put(exposure, 
"calexp", ccd=ccd, visit=visit)
 
  213         if butler 
is not None:
 
  214             butler.put(simSrcCatalog, 
"simsrc", tract=tract)
 
  218         """Convenience function that calls buildSkyMap, buildObservationCatalog, buildTruthCatalog, 
  219         and buildInputImages. 
  227         """Helper function to create a Coadd task with configuration appropriate for the simulations. 
  229         MockCoaddTask does not include MakeCoaddTempExpTask or AssembleCoaddTask as subtasks, because 
  230         we want explicit control over their configs, rather than leaving this up to the user. 
  231         However, we have to install our own SelectImages task for both of these, so it made sense 
  232         to have a single method that would create one of these two tasks, set the config values we 
  233         want, and install the custom SelectImagesTask. 
  236         config.coaddName = self.
config.coaddName
 
  237         config.select.retarget(MockSelectImagesTask)
 
  238         if cls == MakeCoaddTempExpTask:
 
  239             config.bgSubtracted = 
True 
  240             config.makeDirect = 
True 
  241             config.makePsfMatched = 
True 
  242             config.modelPsf.defaultFwhm = 9
 
  243             config.modelPsf.addWing = 
False 
  244             config.warpAndPsfMatch.psfMatch.kernel[
'AL'].scaleByFwhm = 
False 
  245             config.warpAndPsfMatch.psfMatch.kernel[
'AL'].kernelSize = 25
 
  246             config.warpAndPsfMatch.psfMatch.kernel[
'AL'].sizeCellX = 64
 
  247             config.warpAndPsfMatch.psfMatch.kernel[
'AL'].sizeCellY = 64
 
  249         elif cls 
in [AssembleCoaddTask, SafeClipAssembleCoaddTask, CompareWarpAssembleCoaddTask]:
 
  250             if assemblePsfMatched:
 
  251                 config.warpType = 
'psfMatched' 
  252             if cls != AssembleCoaddTask:
 
  253                 config.doWrite = 
False 
  254             if cls == CompareWarpAssembleCoaddTask:
 
  255                 config.assembleStaticSkyModel.select.retarget(MockSelectImagesTask)
 
  256             config.doAttachTransmissionCurve = 
True 
  257         return cls(config=config)
 
  260         """Generator that iterates over the patches in a tract, yielding dataRefs. 
  262         nPatchX, nPatchY = tractInfo.getNumPatches()
 
  263         for iPatchX 
in range(nPatchX):
 
  264             for iPatchY 
in range(nPatchY):
 
  265                 patchRef = butler.dataRef(self.
config.coaddName + 
"Coadd",
 
  266                                           tract=tractInfo.getId(), patch=
"%d,%d" % (iPatchX, iPatchY),
 
  271         """Run the coadd tasks (MakeCoaddTempExp and AssembleCoadd) on the mock data. 
  273         Must be run after buildInputImages. 
  274         Makes both direct and PSF-matched coadds 
  277             skyMap = butler.get(self.
config.coaddName + 
"Coadd_skyMap")
 
  278         tractInfo = skyMap[tract]
 
  279         makeCoaddTempExpTask = self.
makeCoaddTask(MakeCoaddTempExpTask)
 
  280         directCoaddTaskList = []
 
  281         for coaddTask 
in [SafeClipAssembleCoaddTask, CompareWarpAssembleCoaddTask, AssembleCoaddTask]:
 
  283         assemblePsfMatchedCoaddTask = self.
makeCoaddTask(AssembleCoaddTask, assemblePsfMatched=
True)
 
  285             makeCoaddTempExpTask.runDataRef(patchRef)
 
  287             for directCoaddTask 
in directCoaddTaskList:
 
  288                 directCoaddTask.runDataRef(patchRef)
 
  289             assemblePsfMatchedCoaddTask.runDataRef(patchRef)
 
  292         """Directly create a simulation of the coadd, using the CoaddPsf (and ModelPsf) 
  293         of the direct (and psfMatched) coadd exposure and the truth catalog. 
  295         Must be run after buildCoadd. 
  297         if truthCatalog 
is None:
 
  298             truthCatalog = butler.get(
"truth", tract=tract)
 
  300             skyMap = butler.get(self.
config.coaddName + 
"Coadd_skyMap")
 
  301         tractInfo = skyMap[tract]
 
  303             for dataProduct 
in [
"Coadd", 
"CoaddPsfMatched"]:
 
  304                 exposure = patchRef.get(self.
config.coaddName + dataProduct)
 
  305                 exposure.getMaskedImage().getImage().
set(0.0)
 
  307                     exposure.getInfo().getCoaddInputs().ccds, exposure.getWcs()
 
  309                 exposure.setPsf(coaddPsf)
 
  310                 for truthRecord 
in truthCatalog:
 
  311                     self.mockObject.drawSource(truthRecord, exposure, buffer=0)
 
  312                 patchRef.put(exposure, self.
config.coaddName + dataProduct + 
"_mock")
 
  316     """Convenience function to create and run MockCoaddTask with default settings. 
  318     from .simpleMapper 
import makeDataRepo
 
  321     task.buildAllInputs(butler)
 
  322     task.buildCoadd(butler)
 
  323     task.buildMockCoadd(butler)