5 from __future__
import division, absolute_import, print_function
10 import lsst.pex.exceptions
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")
62 log = lsst.log.Log.getLogger(
"jointcal.dataIds")
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 visit = ref.dataId[
"visit"]
79 if visit
not in visitRefs:
80 visitRefs[visit] = list()
81 visitRefs[visit].append(ref)
83 md = ref.get(
"calexp_md", immediate=
True)
84 wcs = lsst.afw.image.makeWcs(md)
85 box = lsst.afw.geom.Box2D(lsst.afw.geom.Point2D(0, 0),
86 lsst.afw.geom.Point2D(md.get(
"NAXIS1"), md.get(
"NAXIS2")))
89 tract = skymap.findTract(wcs.pixelToSky(box.getCenter()))
91 if visit
not in visitTract:
92 visitTract[visit] = set()
93 visitTract[visit].add(tract.getId())
95 tract = dataId.pop(
"tract")
97 for ref
in namespace.butler.subset(
"src", dataId=dataId):
103 for visit, tractSet
in sorted(visitTract.items()):
104 for ref
in visitRefs[visit]:
105 for tract
in sorted(tractSet):
108 tractCounter = collections.Counter()
109 for tractSet
in visitTract.values():
110 tractCounter.update(tractSet)
111 log.infof(
"Number of visits per tract: {}", dict(tractCounter))
115 """Return whether the image (specified by Wcs and bounding box) overlaps the tract 116 @param tract: TractInfo specifying a tract 117 @param imageWcs: Wcs for image 118 @param imageBox: Bounding box for image 121 tractWcs = tract.getWcs()
122 tractCorners = [tractWcs.pixelToSky(lsst.afw.geom.Point2D(coord)).getVector()
for 123 coord
in tract.getBBox().getCorners()]
124 tractPoly = convexHull(tractCorners)
127 imageCorners = [imageWcs.pixelToSky(lsst.afw.geom.Point2D(pix))
for pix
in imageBox.getCorners()]
128 except lsst.pex.exceptions.LsstCppException
as e:
130 if (
not isinstance(e.message, lsst.pex.exceptions.DomainErrorException)
and 131 not isinstance(e.message, lsst.pex.exceptions.RuntimeErrorException)):
135 imagePoly = convexHull([coord.getVector()
for coord
in imageCorners])
136 if imagePoly
is None:
138 return tractPoly.intersects(imagePoly)
def _addDataRef(self, namespace, dataId, tract)
def castDataIds(self, butler)
def makeDataRefList(self, namespace)
def overlapsTract(tract, imageWcs, imageBox)