5 from __future__
import division, absolute_import, print_function
13 from lsst.geom
import convexHull
15 from lsst.coadd.utils
import CoaddDataIdContainer
19 """A version of lsst.pipe.base.DataIdContainer that combines raw data IDs (defined as whatever we use 20 for 'src') with a tract. 24 """Validate data IDs and cast them to the correct type (modify idList in place). 25 @param butler: data butler 28 idKeyTypeDict = butler.getKeys(datasetType=
"src", level=self.level)
30 raise KeyError(
"Cannot get keys for datasetType %s at level %s: %s" % (
"src", self.level, e))
32 idKeyTypeDict = idKeyTypeDict.copy()
33 idKeyTypeDict[
"tract"] = int
35 for dataDict
in self.idList:
36 for key, strVal
in dataDict.items():
38 keyType = idKeyTypeDict[key]
40 validKeys = sorted(idKeyTypeDict.keys())
41 raise KeyError(
"Unrecognized ID key %r; valid keys are: %s" % (key, validKeys))
44 castVal = keyType(strVal)
46 raise TypeError(
"Cannot cast value %r to %s for ID key %r" % (strVal, keyType, key,))
47 dataDict[key] = castVal
49 def _addDataRef(self, namespace, dataId, tract):
50 """Construct a dataRef based on dataId, but with an added tract key""" 51 forcedDataId = dataId.copy()
52 forcedDataId[
'tract'] = tract
53 dataRef = namespace.butler.dataRef(datasetType=self.datasetType, dataId=forcedDataId)
54 self.refList.append(dataRef)
57 """Make self.refList from self.idList 59 if self.datasetType
is None:
60 raise RuntimeError(
"Must call setDatasetType first")
65 for dataId
in self.idList:
66 if "tract" not in dataId:
68 log.infof(
"Reading WCS to determine tracts for components of dataId={}", dict(dataId))
70 skymap = self.getSkymap(namespace)
72 for ref
in namespace.butler.subset(
"calexp", dataId=dataId):
73 if not ref.datasetExists(
"calexp"):
74 log.warnf(
"calexp with dataId: {} not found.", dict(dataId))
78 if "visit" in ref.dataId.keys():
79 visit = ref.dataId[
"visit"]
82 visit = namespace.butler.queryMetadata(
"calexp", (
"visit"), ref.dataId)[0]
83 if visit
not in visitRefs:
84 visitRefs[visit] =
list()
85 visitRefs[visit].append(ref)
87 wcs = ref.get(
"calexp_wcs", immediate=
True)
91 tract = skymap.findTract(wcs.pixelToSky(box.getCenter()))
93 if visit
not in visitTract:
94 visitTract[visit] =
set()
95 visitTract[visit].add(tract.getId())
97 tract = dataId.pop(
"tract")
99 for ref
in namespace.butler.subset(
"src", dataId=dataId):
100 if ref.datasetExists():
106 for visit, tractSet
in sorted(visitTract.items()):
107 for ref
in visitRefs[visit]:
108 for tract
in sorted(tractSet):
111 tractCounter = collections.Counter()
112 for tractSet
in visitTract.values():
113 tractCounter.update(tractSet)
114 log.infof(
"Number of visits per tract: {}", dict(tractCounter))
118 """Return whether the image (specified by Wcs and bounding box) overlaps the tract 119 @param tract: TractInfo specifying a tract 120 @param imageWcs: Wcs for image 121 @param imageBox: Bounding box for image 124 tractWcs = tract.getWcs()
126 coord
in tract.getBBox().getCorners()]
127 tractPoly = convexHull(tractCorners)
131 except lsst.pex.exceptions.LsstCppException
as e:
133 if (
not isinstance(e.message, lsst.pex.exceptions.DomainErrorException)
and 134 not isinstance(e.message, lsst.pex.exceptions.RuntimeErrorException)):
138 imagePoly = convexHull([coord.getVector()
for coord
in imageCorners])
139 if imagePoly
is None:
141 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)