27 __all__ = [
"BaseSelectImagesTask",
"BaseExposureInfo",
"WcsSelectImagesTask",
"DatabaseSelectImagesConfig"]
30 """Base configuration for subclasses of BaseSelectImagesTask that use a database"""
31 host = pexConfig.Field(
32 doc =
"Database server host name",
35 port = pexConfig.Field(
36 doc =
"Database server port",
39 database = pexConfig.Field(
40 doc =
"Name of database",
43 maxExposures = pexConfig.Field(
44 doc =
"maximum exposures to select; intended for debugging; ignored if None",
50 """Data about a selected exposure
53 """Create exposure information that can be used to generate data references
55 The object has the following fields:
56 - dataId: data ID of exposure (a dict)
57 - coordList: a list of corner coordinates of the exposure (list of afwCoord.IcrsCoord)
58 plus any others items that are desired
60 super(BaseExposureInfo, self).
__init__(dataId=dataId, coordList=coordList)
64 """Base task for selecting images suitable for coaddition
66 ConfigClass = pexConfig.Config
67 _DefaultName =
"selectImages"
70 def run(self, coordList):
71 """Select images suitable for coaddition in a particular region
73 @param[in] coordList: list of coordinates defining region of interest; if None then select all images
74 subclasses may add additional keyword arguments, as required
76 @return a pipeBase Struct containing:
77 - exposureInfoList: a list of exposure information objects (subclasses of BaseExposureInfo),
78 which have at least the following fields:
79 - dataId: data ID dictionary
80 - coordList: coordinates of the corner of the exposure (list of afwCoord.IcrsCoord)
82 raise NotImplementedError()
85 """Extract keyword arguments for run (other than coordList) from a data ID
87 @return keyword arguments for run (other than coordList), as a dict
89 raise NotImplementedError()
91 def runDataRef(self, dataRef, coordList, makeDataRefList=True, selectDataList=[]):
92 """Run based on a data reference
94 This delegates to run() and _runArgDictFromDataId() to do the actual
95 selection. In the event that the selectDataList is non-empty, this will
96 be used to further restrict the selection, providing the user with
97 additional control over the selection.
99 @param[in] dataRef: data reference; must contain any extra keys needed by the subclass
100 @param[in] coordList: list of coordinates defining region of interest; if None, search the whole sky
101 @param[in] makeDataRefList: if True, return dataRefList
102 @param[in] selectDataList: List of SelectStruct with dataRefs to consider for selection
103 @return a pipeBase Struct containing:
104 - exposureInfoList: a list of objects derived from ExposureInfo
105 - dataRefList: a list of data references (None if makeDataRefList False)
108 exposureInfoList = self.
run(coordList, **runArgDict).exposureInfoList
110 if len(selectDataList) > 0
and len(exposureInfoList) > 0:
113 inKeys, inValues =
_extractKeyValue([s.dataRef
for s
in selectDataList], keys=ccdKeys)
114 inValues = set(inValues)
115 newExposureInfoList = []
116 for info, ccdVal
in zip(exposureInfoList, ccdValues):
117 if ccdVal
in inValues:
118 newExposureInfoList.append(info)
120 self.log.info(
"De-selecting exposure %s: not in selectDataList" % info.dataId)
121 exposureInfoList = newExposureInfoList
124 butler = dataRef.butlerSubset.butler
125 dataRefList = [butler.dataRef(datasetType =
"calexp",
126 dataId = expInfo.dataId,
127 )
for expInfo
in exposureInfoList]
131 return pipeBase.Struct(
132 dataRefList = dataRefList,
133 exposureInfoList = exposureInfoList,
138 """Extract the keys and values from a list of dataIds
140 The input dataList is a list of objects that have 'dataId' members.
141 This allows it to be used for both a list of data references and a
144 assert len(dataList) > 0
146 keys = sorted(dataList[0].dataId.keys())
149 for data
in dataList:
150 thisKeys = set(data.dataId.keys())
151 if thisKeys != keySet:
152 raise RuntimeError(
"DataId keys inconsistent: %s vs %s" % (keySet, thisKeys))
153 values.append(tuple(data.dataId[k]
for k
in keys))
158 """A container for data to be passed to the WcsSelectImagesTask"""
160 super(SelectStruct, self).
__init__(dataRef=dataRef, wcs=wcs, dims=dims)
164 """Select images using their Wcs"""
165 def runDataRef(self, dataRef, coordList, makeDataRefList=True, selectDataList=[]):
166 """Select images in the selectDataList that overlap the patch
168 We use the "convexHull" function in the geom package to define
169 polygons on the celestial sphere, and test the polygon of the
170 patch for overlap with the polygon of the image.
172 We use "convexHull" instead of generating a SphericalConvexPolygon
173 directly because the standard for the inputs to SphericalConvexPolygon
174 are pretty high and we don't want to be responsible for reaching them.
175 If "convexHull" is found to be too slow, we can revise this.
177 @param dataRef: Data reference for coadd/tempExp (with tract, patch)
178 @param coordList: List of Coord specifying boundary of patch
179 @param makeDataRefList: Construct a list of data references?
180 @param selectDataList: List of SelectStruct, to consider for selection
185 exposureInfoList = []
187 patchVertices = [coord.getVector()
for coord
in coordList]
190 for data
in selectDataList:
191 dataRef = data.dataRef
197 imageCorners = [imageWcs.pixelToSky(pix)
for pix
in imageBox.getCorners()]
198 except (pexExceptions.DomainError, pexExceptions.RuntimeError)
as e:
200 self.log.debug(
"WCS error in testing calexp %s (%s): deselecting", dataRef.dataId, e)
203 imagePoly =
convexHull([coord.getVector()
for coord
in imageCorners])
204 if imagePoly
is None:
205 self.log.debug(
"Unable to create polygon from image %s: deselecting", dataRef.dataId)
207 if patchPoly.intersects(imagePoly):
208 self.log.info(
"Selecting calexp %s" % dataRef.dataId)
209 dataRefList.append(dataRef)
212 return pipeBase.Struct(
213 dataRefList = dataRefList
if makeDataRefList
else None,
214 exposureInfoList = exposureInfoList,
def _runArgDictFromDataId
A floating-point coordinate rectangle geometry.