5 from __future__
import division, absolute_import, print_function
13 from lsst.geom
import convexHull
15 from lsst.coadd.utils
import CoaddDataIdContainer
17 __all__ = [
"PerTractCcdDataIdContainer",
"overlapsTract"]
21 """A version of lsst.pipe.base.DataIdContainer that combines raw data IDs (defined as whatever we use 22 for 'src') with a tract. 26 """Validate data IDs and cast them to the correct type (modify idList in place). 34 idKeyTypeDict = butler.getKeys(datasetType=
"src", level=self.level)
36 raise KeyError(
"Cannot get keys for datasetType %s at level %s: %s" % (
"src", self.level, e))
38 idKeyTypeDict = idKeyTypeDict.copy()
39 idKeyTypeDict[
"tract"] = int
41 for dataDict
in self.idList:
42 for key, strVal
in dataDict.items():
44 keyType = idKeyTypeDict[key]
46 validKeys = sorted(idKeyTypeDict.keys())
47 raise KeyError(
"Unrecognized ID key %r; valid keys are: %s" % (key, validKeys))
50 castVal = keyType(strVal)
52 raise TypeError(
"Cannot cast value %r to %s for ID key %r" % (strVal, keyType, key,))
53 dataDict[key] = castVal
55 def _addDataRef(self, namespace, dataId, tract):
56 """Construct a dataRef based on dataId, but with an added tract key""" 57 forcedDataId = dataId.copy()
58 forcedDataId[
'tract'] = tract
59 dataRef = namespace.butler.dataRef(datasetType=self.datasetType, dataId=forcedDataId)
60 self.refList.append(dataRef)
63 """Make self.refList from self.idList 65 if self.datasetType
is None:
66 raise RuntimeError(
"Must call setDatasetType first")
71 for dataId
in self.idList:
72 if "tract" not in dataId:
74 log.infof(
"Reading WCS to determine tracts for components of dataId={}", dict(dataId))
76 skymap = self.getSkymap(namespace)
78 for ref
in namespace.butler.subset(
"calexp", dataId=dataId):
79 if not ref.datasetExists(
"calexp"):
80 log.warnf(
"calexp with dataId: {} not found.", dict(dataId))
84 if "visit" in ref.dataId.keys():
85 visit = ref.dataId[
"visit"]
88 visit = namespace.butler.queryMetadata(
"calexp", (
"visit"), ref.dataId)[0]
89 if visit
not in visitRefs:
90 visitRefs[visit] =
list()
91 visitRefs[visit].append(ref)
93 wcs = ref.get(
"calexp_wcs", immediate=
True)
97 tract = skymap.findTract(wcs.pixelToSky(box.getCenter()))
99 if visit
not in visitTract:
100 visitTract[visit] =
set()
101 visitTract[visit].add(tract.getId())
103 tract = dataId.pop(
"tract")
105 for ref
in namespace.butler.subset(
"src", dataId=dataId):
106 if ref.datasetExists():
112 for visit, tractSet
in sorted(visitTract.items()):
113 for ref
in visitRefs[visit]:
114 for tract
in sorted(tractSet):
117 tractCounter = collections.Counter()
118 for tractSet
in visitTract.values():
119 tractCounter.update(tractSet)
120 log.infof(
"Number of visits per tract: {}", dict(tractCounter))
124 """Return whether the image (specified by Wcs and bounding box) overlaps the tract 129 TractInfo specifying a tract 133 Bounding box for image 138 True if the image overlaps the tract, False otherwise. 140 tractWcs = tract.getWcs()
142 coord
in tract.getBBox().getCorners()]
143 tractPoly = convexHull(tractCorners)
147 except lsst.pex.exceptions.LsstCppException
as e:
149 if (
not isinstance(e.message, lsst.pex.exceptions.DomainErrorException)
and 150 not isinstance(e.message, lsst.pex.exceptions.RuntimeErrorException)):
154 imagePoly = convexHull([coord.getVector()
for coord
in imageCorners])
155 if imagePoly
is None:
157 return tractPoly.intersects(imagePoly)
def _addDataRef(self, namespace, dataId, tract)
def castDataIds(self, butler)
def makeDataRefList(self, namespace)
static Log getLogger(std::string const &loggername)
def overlapsTract(tract, imageWcs, imageBox)