1 from __future__ 
import absolute_import, division, print_function
     3 from builtins 
import zip
     4 from builtins 
import map
    23     coaddName = 
Field(dtype=str, default=
"deep", doc=
"Name for coadd")
    25         target=WcsSelectImagesTask, doc=
"Select images to process")
    27         target=MakeCoaddTempExpTask, doc=
"Warp images to sky")
    29         dtype=bool, default=
False, doc=
"Build background reference?")
    31         target=NullSelectImagesTask, doc=
"Build background reference")
    33         target=SafeClipAssembleCoaddTask, doc=
"Assemble warps into coadd")
    34     doDetection = 
Field(dtype=bool, default=
True,
    35                         doc=
"Run detection on the coaddition product")
    37         target=DetectCoaddSourcesTask, doc=
"Detect sources on coadd")
    47                 "makeCoaddTempExp.coaddName and coaddName don't match")
    50                 "assembleCoadd.coaddName and coaddName don't match")
    52             message = (
"assembleCoadd.matchingKernelSize (%s) and makeCoaddTempExp.matchingKernelSize (%s)"    55             raise RuntimeError(message)
    60     def __init__(self, TaskClass, parsedCmd, doReturnResults=False):
    61         CoaddTaskRunner.__init__(self, TaskClass, parsedCmd, doReturnResults)
    65         return self.TaskClass(config=self.config, log=self.log, reuse=self.
reuse)
    69         """!Get bare butler into Task    71         @param parsedCmd results of parsing command input    73         kwargs[
"butler"] = parsedCmd.butler
    74         kwargs[
"selectIdList"] = [
    75             ref.dataId 
for ref 
in parsedCmd.selectId.refList]
    76         return [(parsedCmd.id.refList, kwargs), ]
    80     """Unpickle something by calling a factory"""    81     return factory(*args, **kwargs)
    85     ConfigClass = CoaddDriverConfig
    86     _DefaultName = 
"coaddDriver"    87     RunnerClass = CoaddDriverTaskRunner
    90         BatchPoolTask.__init__(self, **kwargs)
    93         self.
makeSubtask(
"makeCoaddTempExp", reuse=(
"makeCoaddTempExp" in self.
reuse))
   100         return unpickle, (self.__class__, [], dict(config=self.
config, name=self.
_name,
   105     def _makeArgumentParser(cls, **kwargs):
   106         """!Build argument parser   108         Selection references are not cheap (reads Wcs), so are generated   109         only if we're not doing a batch submission.   112         parser.add_id_argument(
"--id", 
"deepCoadd", help=
"data ID, e.g. --id tract=12345 patch=1,2",
   113                                ContainerClass=TractDataIdContainer)
   114         parser.add_id_argument(
   115             "--selectId", 
"calexp", help=
"data ID, e.g. --selectId visit=6789 ccd=0..9")
   116         parser.addReuseOption([
"makeCoaddTempExp", 
"assembleCoadd", 
"detectCoaddSources"])
   122         Return walltime request for batch job   124         @param time: Requested time per iteration   125         @param parsedCmd: Results of argument parsing   126         @param numCores: Number of cores   127         @return float walltime request length   129         numTargets = len(parsedCmd.selectId.refList)
   130         return time*numTargets/
float(numCores)
   133     def runDataRef(self, tractPatchRefList, butler, selectIdList=[]):
   134         """!Determine which tracts are non-empty before processing   136         @param tractPatchRefList: List of tracts and patches to include in the coaddition   137         @param butler: butler reference object   138         @param selectIdList: List of data Ids (i.e. visit, ccd) to consider when making the coadd   139         @return list of references to sel.runTract function evaluation for each tractPatchRefList member   141         pool = 
Pool(
"tracts")
   142         pool.storeSet(butler=butler, skymap=butler.get(
   143             self.
config.coaddName + 
"Coadd_skyMap"))
   145         for patchRefList 
in tractPatchRefList:
   146             tractSet = 
set([patchRef.dataId[
"tract"]
   147                             for patchRef 
in patchRefList])
   148             assert len(tractSet) == 1
   149             tractIdList.append(tractSet.pop())
   151         selectDataList = [data 
for data 
in pool.mapNoBalance(self.
readSelection, selectIdList) 
if   153         nonEmptyList = pool.mapNoBalance(
   155         tractPatchRefList = [patchRefList 
for patchRefList, nonEmpty 
in   156                              zip(tractPatchRefList, nonEmptyList) 
if nonEmpty]
   157         self.
log.
info(
"Non-empty tracts (%d): %s" % (len(tractPatchRefList),
   158                                                      [patchRefList[0].dataId[
"tract"] 
for patchRefList 
in   162         for data 
in selectDataList:
   163             data.dataRef = 
getDataRef(butler, data.dataId, 
"calexp")
   166         return [self.
run(patchRefList, butler, selectDataList) 
for patchRefList 
in tractPatchRefList]
   169     def run(self, patchRefList, butler, selectDataList=[]):
   170         """!Run stacking on a tract   172         This method only runs on the master node.   174         @param patchRefList: List of patch data references for tract   175         @param butler: Data butler   176         @param selectDataList: List of SelectStruct for inputs   178         pool = 
Pool(
"stacker")
   180         pool.storeSet(butler=butler, warpType=self.
config.coaddName + 
"Coadd_directWarp",
   181                       coaddType=self.
config.coaddName + 
"Coadd")
   182         patchIdList = [patchRef.dataId 
for patchRef 
in patchRefList]
   184         selectedData = pool.map(self.
warp, patchIdList, selectDataList)
   185         if self.
config.doBackgroundReference:
   186             self.backgroundReference.
runDataRef(patchRefList, selectDataList)
   188         def refNamer(patchRef):
   189             return tuple(map(int, patchRef.dataId[
"patch"].split(
",")))
   191         lookup = dict(zip(map(refNamer, patchRefList), selectedData))
   192         coaddData = [
Struct(patchId=patchRef.dataId, selectDataList=lookup[refNamer(patchRef)]) 
for   193                      patchRef 
in patchRefList]
   194         pool.map(self.
coadd, coaddData)
   197         """!Read Wcs of selected inputs   199         This method only runs on slave nodes.   200         This method is similar to SelectDataIdContainer.makeDataRefList,   201         creating a Struct like a SelectStruct, except with a dataId instead   202         of a dataRef (to ease MPI).   204         @param cache: Pool cache   205         @param selectId: Data identifier for selected input   206         @return a SelectStruct with a dataId instead of dataRef   209             ref = 
getDataRef(cache.butler, selectId, 
"calexp")
   210             self.
log.
info(
"Reading Wcs from %s" % (selectId,))
   211             md = ref.get(
"calexp_md", immediate=
True)
   215             self.
log.
warn(
"Unable to construct Wcs from %s" % (selectId,))
   220         """!Check whether a tract has any overlapping inputs   222         This method only runs on slave nodes.   224         @param cache: Pool cache   225         @param tractId: Data identifier for tract   226         @param selectDataList: List of selection data   227         @return whether tract has any overlapping inputs   229         def makePolygon(wcs, bbox):
   230             """Return a polygon for the image, given Wcs and bounding box"""   232             boxSkyCorners = wcs.pixelToSky(boxPixelCorners)
   235         skymap = cache.skymap
   236         tract = skymap[tractId]
   237         tractWcs = tract.getWcs()
   238         tractPoly = makePolygon(tractWcs, tract.getBBox())
   240         for selectData 
in selectIdList:
   241             if not hasattr(selectData, 
"poly"):
   242                 selectData.poly = makePolygon(selectData.wcs, selectData.bbox)
   243             if tractPoly.intersects(selectData.poly):
   247     def warp(self, cache, patchId, selectDataList):
   248         """!Warp all images for a patch   250         Only slave nodes execute this method.   252         Because only one argument may be passed, it is expected to   253         contain multiple elements, which are:   255         @param patchRef: data reference for patch   256         @param selectDataList: List of SelectStruct for inputs   257         @return selectDataList with non-overlapping elements removed   259         patchRef = 
getDataRef(cache.butler, patchId, cache.coaddType)
   261         with self.
logOperation(
"warping %s" % (patchRef.dataId,), catch=
True):
   262             self.makeCoaddTempExp.
runDataRef(patchRef, selectDataList)
   263         return selectDataList
   266         """!Construct coadd for a patch and measure   268         Only slave nodes execute this method.   270         Because only one argument may be passed, it is expected to   271         contain multiple elements, which are:   273         @param patchRef: data reference for patch   274         @param selectDataList: List of SelectStruct for inputs   276         patchRef = 
getDataRef(cache.butler, data.patchId, cache.coaddType)
   277         selectDataList = data.selectDataList
   284             "detectCoaddSources" in self.
reuse and   285             patchRef.datasetExists(self.detectCoaddSources.config.coaddName+
"Coadd_det", write=
True)
   287         if "assembleCoadd" in self.
reuse:
   288             if patchRef.datasetExists(cache.coaddType, write=
True):
   289                 self.
log.
info(
"%s: Skipping assembleCoadd for %s; outputs already exist." %
   290                               (NODE, patchRef.dataId))
   291                 coadd = patchRef.get(cache.coaddType, immediate=
True)
   292             elif not self.
config.assembleCoadd.doWrite 
and self.
config.doDetection 
and canSkipDetection:
   294                     "%s: Skipping assembleCoadd and detectCoaddSources for %s; outputs already exist." %
   295                     (NODE, patchRef.dataId)
   299             with self.
logOperation(
"coadding %s" % (patchRef.dataId,), catch=
True):
   300                 coaddResults = self.assembleCoadd.
runDataRef(patchRef, selectDataList)
   301                 if coaddResults 
is not None:
   302                     coadd = coaddResults.coaddExposure
   303                     canSkipDetection = 
False     311         if self.
config.doDetection:
   313                 self.
log.
info(
"%s: Skipping detectCoaddSources for %s; outputs already exist." %
   314                               (NODE, patchRef.dataId))
   318                 idFactory = self.detectCoaddSources.makeIdFactory(patchRef)
   319                 expId = 
int(patchRef.get(self.
config.coaddName + 
"CoaddId"))
   322                 detResults = self.detectCoaddSources.
run(coadd, idFactory, expId=expId)
   323                 self.detectCoaddSources.write(detResults, patchRef)
   325             patchRef.put(coadd, self.assembleCoadd.config.coaddName+
"Coadd")
   328         """!Select exposures to operate upon, via the SelectImagesTask   330         This is very similar to CoaddBaseTask.selectExposures, except we return   331         a list of SelectStruct (same as the input), so we can plug the results into   332         future uses of SelectImagesTask.   334         @param patchRef data reference to a particular patch   335         @param selectDataList list of references to specific data products (i.e. visit, ccd)   336         @return filtered list of SelectStruct   339             return tuple(dataRef.dataId[k] 
for k 
in sorted(dataRef.dataId))
   340         inputs = dict((
key(select.dataRef), select)
   341                       for select 
in selectDataList)
   342         skyMap = patchRef.get(self.
config.coaddName + 
"Coadd_skyMap")
   343         tract = skyMap[patchRef.dataId[
"tract"]]
   344         patch = tract[(tuple(
int(i)
   345                              for i 
in patchRef.dataId[
"patch"].split(
",")))]
   346         bbox = patch.getOuterBBox()
   349         coordList = [wcs.pixelToSky(pos) 
for pos 
in cornerPosList]
   351             patchRef, coordList, selectDataList=selectDataList).dataRefList
   352         return [inputs[
key(dataRef)] 
for dataRef 
in dataRefList]
 
def batchWallTime(cls, time, parsedCmd, numCores)
Return walltime request for batch job. 
def unpickle(factory, args, kwargs)
def makeSubtask(self, name, keyArgs)
A floating-point coordinate rectangle geometry. 
def selectExposures(self, patchRef, selectDataList)
Select exposures to operate upon, via the SelectImagesTask. 
daf::base::PropertySet * set
def makeTask(self, parsedCmd=None, args=None)
def getDataRef(butler, dataId, datasetType="raw")
def __init__(self, reuse=tuple(), kwargs)
static ConvexPolygon convexHull(std::vector< UnitVector3d > const &points)
convexHull returns the convex hull of the given set of points if it exists and throws an exception ot...
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def coadd(self, cache, data)
Construct coadd for a patch and measure. 
def runDataRef(self, tractPatchRefList, butler, selectIdList=[])
Determine which tracts are non-empty before processing. 
def warp(self, cache, patchId, selectDataList)
Warp all images for a patch. 
def logOperation(self, operation, catch=False, trace=True)
Provide a context manager for logging an operation. 
def getTargetList(parsedCmd, kwargs)
Get bare butler into Task. 
std::shared_ptr< SkyWcs > makeSkyWcs(TransformPoint2ToPoint2 const &pixelsToFieldAngle, lsst::geom::Angle const &orientation, bool flipX, lsst::geom::SpherePoint const &boresight, std::string const &projection="TAN")
Construct a FITS SkyWcs from camera geometry. 
def readSelection(self, cache, selectId)
Read Wcs of selected inputs. 
def __init__(self, TaskClass, parsedCmd, doReturnResults=False)
def checkTract(self, cache, tractId, selectIdList)
Check whether a tract has any overlapping inputs. 
def writeMetadata(self, dataRef)
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header) 
def run(self, patchRefList, butler, selectDataList=[])
Run stacking on a tract.