28 __all__ = [
"BaseSelectImagesTask",
"BaseExposureInfo",
"WcsSelectImagesTask",
"DatabaseSelectImagesConfig"]
31 """Base configuration for subclasses of BaseSelectImagesTask that use a database"""
32 host = pexConfig.Field(
33 doc =
"Database server host name",
36 port = pexConfig.Field(
37 doc =
"Database server port",
40 database = pexConfig.Field(
41 doc =
"Name of database",
44 maxExposures = pexConfig.Field(
45 doc =
"maximum exposures to select; intended for debugging; ignored if None",
51 """Data about a selected exposure
54 """Create exposure information that can be used to generate data references
56 The object has the following fields:
57 - dataId: data ID of exposure (a dict)
58 - coordList: a list of corner coordinates of the exposure (list of afwCoord.IcrsCoord)
59 plus any others items that are desired
61 super(BaseExposureInfo, self).
__init__(dataId=dataId, coordList=coordList)
65 """Base task for selecting images suitable for coaddition
67 ConfigClass = pexConfig.Config
68 _DefaultName =
"selectImages"
71 def run(self, coordList):
72 """Select images suitable for coaddition in a particular region
74 @param[in] coordList: list of coordinates defining region of interest; if None then select all images
75 subclasses may add additional keyword arguments, as required
77 @return a pipeBase Struct containing:
78 - exposureInfoList: a list of exposure information objects (subclasses of BaseExposureInfo),
79 which have at least the following fields:
80 - dataId: data ID dictionary
81 - coordList: coordinates of the corner of the exposure (list of afwCoord.IcrsCoord)
83 raise NotImplementedError()
86 """Extract keyword arguments for run (other than coordList) from a data ID
88 @return keyword arguments for run (other than coordList), as a dict
90 raise NotImplementedError()
92 def runDataRef(self, dataRef, coordList, makeDataRefList=True, selectDataList=[]):
93 """Run based on a data reference
95 This delegates to run() and _runArgDictFromDataId() to do the actual
96 selection. In the event that the selectDataList is non-empty, this will
97 be used to further restrict the selection, providing the user with
98 additional control over the selection.
100 @param[in] dataRef: data reference; must contain any extra keys needed by the subclass
101 @param[in] coordList: list of coordinates defining region of interest; if None, search the whole sky
102 @param[in] makeDataRefList: if True, return dataRefList
103 @param[in] selectDataList: List of SelectStruct with dataRefs to consider for selection
104 @return a pipeBase Struct containing:
105 - exposureInfoList: a list of objects derived from ExposureInfo
106 - dataRefList: a list of data references (None if makeDataRefList False)
109 exposureInfoList = self.
run(coordList, **runArgDict).exposureInfoList
111 if len(selectDataList) > 0
and len(exposureInfoList) > 0:
114 inKeys, inValues =
_extractKeyValue([s.dataRef
for s
in selectDataList], keys=ccdKeys)
115 inValues = set(inValues)
116 newExposureInfoList = []
117 for info, ccdVal
in zip(exposureInfoList, ccdValues):
118 if ccdVal
in inValues:
119 newExposureInfoList.append(info)
121 self.log.info(
"De-selecting exposure %s: not in selectDataList" % info.dataId)
122 exposureInfoList = newExposureInfoList
125 butler = dataRef.butlerSubset.butler
126 dataRefList = [butler.dataRef(datasetType =
"calexp",
127 dataId = expInfo.dataId,
128 )
for expInfo
in exposureInfoList]
132 return pipeBase.Struct(
133 dataRefList = dataRefList,
134 exposureInfoList = exposureInfoList,
139 """Extract the keys and values from a list of dataIds
141 The input dataList is a list of objects that have 'dataId' members.
142 This allows it to be used for both a list of data references and a
145 assert len(dataList) > 0
147 keys = sorted(dataList[0].dataId.keys())
150 for data
in dataList:
151 thisKeys = set(data.dataId.keys())
152 if thisKeys != keySet:
153 raise RuntimeError(
"DataId keys inconsistent: %s vs %s" % (keySet, thisKeys))
154 values.append(tuple(data.dataId[k]
for k
in keys))
159 """A container for data to be passed to the WcsSelectImagesTask"""
161 super(SelectStruct, self).
__init__(dataRef=dataRef, wcs=wcs, dims=dims)
165 """Select images using their Wcs"""
166 def runDataRef(self, dataRef, coordList, makeDataRefList=True, selectDataList=[]):
167 """Select images in the selectDataList that overlap the patch
169 We use the "convexHull" function in the geom package to define
170 polygons on the celestial sphere, and test the polygon of the
171 patch for overlap with the polygon of the image.
173 We use "convexHull" instead of generating a SphericalConvexPolygon
174 directly because the standard for the inputs to SphericalConvexPolygon
175 are pretty high and we don't want to be responsible for reaching them.
176 If "convexHull" is found to be too slow, we can revise this.
178 @param dataRef: Data reference for coadd/tempExp (with tract, patch)
179 @param coordList: List of Coord specifying boundary of patch
180 @param makeDataRefList: Construct a list of data references?
181 @param selectDataList: List of SelectStruct, to consider for selection
186 exposureInfoList = []
188 patchVertices = [coord.getVector()
for coord
in coordList]
191 for data
in selectDataList:
192 dataRef = data.dataRef
198 imageCorners = [imageWcs.pixelToSky(pix)
for pix
in imageBox.getCorners()]
199 except (pexExceptions.DomainError, pexExceptions.RuntimeError)
as e:
201 self.log.logdebug(
"WCS error in testing calexp %s (%s): deselecting" % (dataRef.dataId, e))
204 imagePoly =
convexHull([coord.getVector()
for coord
in imageCorners])
205 if patchPoly.intersects(imagePoly):
206 self.log.info(
"Selecting calexp %s" % dataRef.dataId)
207 dataRefList.append(dataRef)
210 return pipeBase.Struct(
211 dataRefList = dataRefList
if makeDataRefList
else None,
212 exposureInfoList = exposureInfoList,
def _runArgDictFromDataId
A floating-point coordinate rectangle geometry.