35 """Config for MakeDiscreteSkyMapTask
37 coaddName = pexConfig.Field(
38 doc=
"coadd name, e.g. deep, goodSeeing, chiSquared",
42 skyMap = pexConfig.ConfigField(
43 dtype=BaseSkyMap.ConfigClass,
44 doc=
"SkyMap configuration parameters, excluding position and radius"
46 borderSize = pexConfig.Field(
47 doc=
"additional border added to the bounding box of the calexps, in degrees",
51 doAppend = pexConfig.Field(
52 doc=
"append another tract to an existing DiscreteSkyMap on disk, if present?",
56 doWrite = pexConfig.Field(
57 doc=
"persist the skyMap?",
63 self.
skyMapskyMap.tractOverlap = 0.0
67 """Run a task with all dataRefs at once, rather than one dataRef at a time.
69 Call the run method of the task using two positional arguments:
71 - dataRefList: list of all dataRefs,
75 return [(parsedCmd.butler, parsedCmd.id.refList)]
79 @param args Arguments for Task.run()
82 - None if self.doReturnResults false
83 - A pipe_base Struct containing these fields if self.doReturnResults true:
84 - dataRef: the provided data reference
85 - metadata: task metadata after execution of run
86 - result: result returned by task run, or None if the task fails
88 butler, dataRefList = args
89 task = self.TaskClass(config=self.config, log=self.log)
93 result = task.runDataRef(butler, dataRefList)
96 result = task.runDataRef(butler, dataRefList)
97 except Exception
as e:
98 task.log.fatal(
"Failed: %s" % e)
100 if not isinstance(e, pipeBase.TaskError):
101 traceback.print_exc(file=sys.stderr)
102 for dataRef
in dataRefList:
103 task.writeMetadata(dataRef)
105 if self.doReturnResults:
106 return pipeBase.Struct(
107 dataRefList=dataRefList,
108 metadata=task.metadata,
110 exitStatus=exitStatus,
113 return pipeBase.Struct(
114 exitStatus=exitStatus,
119 """!Make a DiscreteSkyMap in a repository, using the bounding box of a set of calexps.
121 The command-line and run signatures and config are sufficiently different from MakeSkyMapTask
122 that we don't inherit from it, but it is a replacement, so we use the same config/metadata names.
124 ConfigClass = MakeDiscreteSkyMapConfig
125 _DefaultName =
"makeDiscreteSkyMap"
126 RunnerClass = MakeDiscreteSkyMapRunner
132 """Make a skymap from the bounds of the given set of calexps using the butler.
136 butler : `lsst.daf.persistence.Butler`
137 Gen2 data butler used to save the SkyMap
138 dataRefList : iterable
139 A list of Gen2 data refs of calexps used to determin the size and pointing of the SkyMap
142 struct : `lsst.pipe.base.Struct`
143 The returned struct has one attribute, ``skyMap``, which holds the returned SkyMap
145 wcs_md_tuple_list = []
147 datasetName = self.config.coaddName +
"Coadd_skyMap"
148 for dataRef
in dataRefList:
149 if not dataRef.datasetExists(
"calexp"):
150 self.log.
warn(
"CalExp for %s does not exist: ignoring" % (dataRef.dataId,))
152 wcs_md_tuple_list.append((dataRef.get(
"calexp_wcs", immediate=
True),
153 dataRef.get(
"calexp_md", immediate=
True)))
154 if self.config.doAppend
and butler.datasetExists(datasetName):
155 oldSkyMap = butler.get(datasetName, immediate=
True)
156 if not isinstance(oldSkyMap.config, DiscreteSkyMap.ConfigClass):
157 raise TypeError(
"Cannot append to existing non-discrete skymap")
159 if not self.config.skyMap.compare(oldSkyMap.config, output=compareLog.append):
160 raise ValueError(
"Cannot append to existing skymap - configurations differ:", *compareLog)
161 result = self.
runrun(wcs_md_tuple_list, oldSkyMap)
162 if self.config.doWrite:
163 butler.put(result.skyMap, datasetName)
167 def run(self, wcs_md_tuple_list, oldSkyMap=None):
168 """Make a SkyMap from the bounds of the given set of calexp metadata.
172 wcs_md_tuple_list : iterable
173 A list of tuples with each element expected to be a (Wcs, PropertySet) pair
174 oldSkyMap : `lsst.skymap.DiscreteSkyMap`, option
175 The SkyMap to extend if appending
178 struct : `lsst.pipe.base.Struct
179 The returned struct has one attribute, ``skyMap``, which holds the returned SkyMap
181 self.log.
info(
"Extracting bounding boxes of %d images" % len(wcs_md_tuple_list))
183 for wcs, md
in wcs_md_tuple_list:
187 points.extend(wcs.pixelToSky(corner).getVector()
for corner
in boxD.getCorners())
189 raise RuntimeError(
"No data found from which to compute convex hull")
190 self.log.
info(
"Computing spherical convex hull")
194 "Failed to compute convex hull of the vertices of all calexp bounding boxes; "
195 "they may not be hemispherical."
197 circle = polygon.getBoundingCircle()
199 skyMapConfig = DiscreteSkyMap.ConfigClass()
201 skyMapConfig.raList.extend(oldSkyMap.config.raList)
202 skyMapConfig.decList.extend(oldSkyMap.config.decList)
203 skyMapConfig.radiusList.extend(oldSkyMap.config.radiusList)
204 skyMapConfig.update(**self.config.skyMap.toDict())
206 skyMapConfig.raList.append(circleCenter[0].asDegrees())
207 skyMapConfig.decList.append(circleCenter[1].asDegrees())
208 circleRadiusDeg = circle.getOpeningAngle().asDegrees()
209 skyMapConfig.radiusList.append(circleRadiusDeg + self.config.borderSize)
212 for tractInfo
in skyMap:
213 wcs = tractInfo.getWcs()
221 skyPosList = [wcs.pixelToSky(pos).getPosition(geom.degrees)
for pos
in pixelPosList]
222 posStrList = [
"(%0.3f, %0.3f)" % tuple(skyPos)
for skyPos
in skyPosList]
223 self.log.
info(
"tract %s has corners %s (RA, Dec deg) and %s x %s patches" %
224 (tractInfo.getId(),
", ".join(posStrList),
225 tractInfo.getNumPatches()[0], tractInfo.getNumPatches()[1]))
226 return pipeBase.Struct(
230 def _getConfigName(self):
231 """Return None to disable saving config
233 There's only one SkyMap per repository, so the config is redundant, and checking it means we can't
234 easily overwrite or append to an existing repository.
238 def _getMetadataName(self):
239 """Return None to disable saving metadata
241 The metadata is not interesting, and by not saving it we can eliminate a dataset type.
246 def _makeArgumentParser(cls):
248 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 runDataRef(self, butler, dataRefList)
def run(self, wcs_md_tuple_list, oldSkyMap=None)
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.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
lsst::geom::Box2I bboxFromMetadata(daf::base::PropertySet &metadata)
Determine the image bounding box from its metadata (FITS header)