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.image.bboxFromMetadata(md))
88 tract = skymap.findTract(wcs.pixelToSky(box.getCenter()))
90 if visit
not in visitTract:
91 visitTract[visit] = set()
92 visitTract[visit].add(tract.getId())
94 tract = dataId.pop(
"tract")
96 for ref
in namespace.butler.subset(
"src", dataId=dataId):
102 for visit, tractSet
in sorted(visitTract.items()):
103 for ref
in visitRefs[visit]:
104 for tract
in sorted(tractSet):
107 tractCounter = collections.Counter()
108 for tractSet
in visitTract.values():
109 tractCounter.update(tractSet)
110 log.infof(
"Number of visits per tract: {}", dict(tractCounter))
114 """Return whether the image (specified by Wcs and bounding box) overlaps the tract
115 @param tract: TractInfo specifying a tract
116 @param imageWcs: Wcs for image
117 @param imageBox: Bounding box for image
120 tractWcs = tract.getWcs()
121 tractCorners = [tractWcs.pixelToSky(lsst.afw.geom.Point2D(coord)).getVector()
for
122 coord
in tract.getBBox().getCorners()]
123 tractPoly = convexHull(tractCorners)
126 imageCorners = [imageWcs.pixelToSky(lsst.afw.geom.Point2D(pix))
for pix
in imageBox.getCorners()]
127 except lsst.pex.exceptions.LsstCppException
as e:
129 if (
not isinstance(e.message, lsst.pex.exceptions.DomainErrorException)
and
130 not isinstance(e.message, lsst.pex.exceptions.RuntimeErrorException)):
134 imagePoly = convexHull([coord.getVector()
for coord
in imageCorners])
135 if imagePoly
is None:
137 return tractPoly.intersects(imagePoly)