34 """Config for MakeDiscreteSkyMapTask
36 coaddName = pexConfig.Field(
37 doc=
"coadd name, e.g. deep, goodSeeing, chiSquared",
41 skyMap = pexConfig.ConfigField(
42 dtype=BaseSkyMap.ConfigClass,
43 doc=
"SkyMap configuration parameters, excluding position and radius"
45 borderSize = pexConfig.Field(
46 doc=
"additional border added to the bounding box of the calexps, in degrees",
50 doAppend = pexConfig.Field(
51 doc=
"append another tract to an existing DiscreteSkyMap on disk, if present?",
55 doWrite = pexConfig.Field(
56 doc=
"persist the skyMap?",
62 self.
skyMapskyMap.tractOverlap = 0.0
66 """Run a task with all dataRefs at once, rather than one dataRef at a time.
68 Call the run method of the task using two positional arguments:
70 - dataRefList: list of all dataRefs,
74 return [(parsedCmd.butler, parsedCmd.id.refList)]
78 @param args Arguments for Task.run()
81 - None if self.doReturnResults false
82 - A pipe_base Struct containing these fields if self.doReturnResults true:
83 - dataRef: the provided data reference
84 - metadata: task metadata after execution of run
85 - result: result returned by task run, or None if the task fails
87 butler, dataRefList = args
88 task = self.TaskClass(config=self.config, log=self.log)
92 result = task.runDataRef(butler, dataRefList)
95 result = task.runDataRef(butler, dataRefList)
96 except Exception
as e:
97 task.log.fatal(
"Failed: %s", e)
99 if not isinstance(e, pipeBase.TaskError):
100 traceback.print_exc(file=sys.stderr)
101 for dataRef
in dataRefList:
102 task.writeMetadata(dataRef)
104 if self.doReturnResults:
105 return pipeBase.Struct(
106 dataRefList=dataRefList,
107 metadata=task.metadata,
109 exitStatus=exitStatus,
112 return pipeBase.Struct(
113 exitStatus=exitStatus,
118 """!Make a DiscreteSkyMap in a repository, using the bounding box of a set of calexps.
120 The command-line and run signatures and config are sufficiently different from MakeSkyMapTask
121 that we don't inherit from it, but it is a replacement, so we use the same config/metadata names.
123 ConfigClass = MakeDiscreteSkyMapConfig
124 _DefaultName =
"makeDiscreteSkyMap"
125 RunnerClass = MakeDiscreteSkyMapRunner
131 """Make a skymap from the bounds of the given set of calexps using the butler.
135 butler : `lsst.daf.persistence.Butler`
136 Gen2 data butler used to save the SkyMap
137 dataRefList : iterable
138 A list of Gen2 data refs of calexps used to determin the size and pointing of the SkyMap
141 struct : `lsst.pipe.base.Struct`
142 The returned struct has one attribute, ``skyMap``, which holds the returned SkyMap
144 wcs_bbox_tuple_list = []
146 datasetName = self.config.coaddName +
"Coadd_skyMap"
147 for dataRef
in dataRefList:
148 if not dataRef.datasetExists(
"calexp"):
149 self.log.
warning(
"CalExp for %s does not exist: ignoring", dataRef.dataId)
151 wcs_bbox_tuple_list.append((dataRef.get(
"calexp_wcs", immediate=
True),
152 dataRef.get(
"calexp_bbox", immediate=
True)))
153 if self.config.doAppend
and butler.datasetExists(datasetName):
154 oldSkyMap = butler.get(datasetName, immediate=
True)
155 if not isinstance(oldSkyMap.config, DiscreteSkyMap.ConfigClass):
156 raise TypeError(
"Cannot append to existing non-discrete skymap")
158 if not self.config.skyMap.compare(oldSkyMap.config, output=compareLog.append):
159 raise ValueError(
"Cannot append to existing skymap - configurations differ:", *compareLog)
160 result = self.
runrun(wcs_bbox_tuple_list, oldSkyMap)
161 if self.config.doWrite:
162 butler.put(result.skyMap, datasetName)
166 def run(self, wcs_bbox_tuple_list, oldSkyMap=None):
167 """Make a SkyMap from the bounds of the given set of calexp metadata.
171 wcs_bbox_tuple_list : iterable
172 A list of tuples with each element expected to be a (Wcs, Box2I) pair
173 oldSkyMap : `lsst.skymap.DiscreteSkyMap`, option
174 The SkyMap to extend if appending
177 struct : `lsst.pipe.base.Struct
178 The returned struct has one attribute, ``skyMap``, which holds the returned SkyMap
180 self.log.
info(
"Extracting bounding boxes of %d images", len(wcs_bbox_tuple_list))
182 for wcs, boxI
in wcs_bbox_tuple_list:
184 points.extend(wcs.pixelToSky(corner).getVector()
for corner
in boxD.getCorners())
186 raise RuntimeError(
"No data found from which to compute convex hull")
187 self.log.
info(
"Computing spherical convex hull")
191 "Failed to compute convex hull of the vertices of all calexp bounding boxes; "
192 "they may not be hemispherical."
194 circle = polygon.getBoundingCircle()
196 skyMapConfig = DiscreteSkyMap.ConfigClass()
198 skyMapConfig.raList.extend(oldSkyMap.config.raList)
199 skyMapConfig.decList.extend(oldSkyMap.config.decList)
200 skyMapConfig.radiusList.extend(oldSkyMap.config.radiusList)
201 skyMapConfig.update(**self.config.skyMap.toDict())
203 skyMapConfig.raList.append(circleCenter[0].asDegrees())
204 skyMapConfig.decList.append(circleCenter[1].asDegrees())
205 circleRadiusDeg = circle.getOpeningAngle().asDegrees()
206 skyMapConfig.radiusList.append(circleRadiusDeg + self.config.borderSize)
209 for tractInfo
in skyMap:
210 wcs = tractInfo.getWcs()
218 skyPosList = [wcs.pixelToSky(pos).getPosition(geom.degrees)
for pos
in pixelPosList]
219 posStrList = [
"(%0.3f, %0.3f)" % tuple(skyPos)
for skyPos
in skyPosList]
220 self.log.
info(
"tract %s has corners %s (RA, Dec deg) and %s x %s patches",
221 tractInfo.getId(),
", ".join(posStrList),
222 tractInfo.getNumPatches()[0], tractInfo.getNumPatches()[1])
223 return pipeBase.Struct(
227 def _getConfigName(self):
228 """Return None to disable saving config
230 There's only one SkyMap per repository, so the config is redundant, and checking it means we can't
231 easily overwrite or append to an existing repository.
235 def _getMetadataName(self):
236 """Return None to disable saving metadata
238 The metadata is not interesting, and by not saving it we can eliminate a dataset type.
243 def _makeArgumentParser(cls):
244 parser = ArgumentParser(name=cls.
_DefaultName_DefaultName)
245 parser.add_id_argument(name=
"--id", datasetType=
"calexp", help=
"data ID, e.g. --id visit=123 ccd=1,2")
A floating-point coordinate rectangle geometry.
def getTargetList(parsedCmd)
Make a DiscreteSkyMap in a repository, using the bounding box of a set of calexps.
def run(self, wcs_bbox_tuple_list, oldSkyMap=None)
def runDataRef(self, butler, dataRefList)
def __init__(self, **kwargs)
static ConvexPolygon convexHull(std::vector< UnitVector3d > const &points)
convexHull returns the convex hull of the given set of points if it exists and throws an exception ot...
LonLat represents a spherical coordinate (longitude/latitude angle) pair.