31 from lsst.utils.timer 
import timeMethod
 
   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_bbox_tuple_list = []
 
  147         datasetName = self.config.coaddName + 
"Coadd_skyMap" 
  148         for dataRef 
in dataRefList:
 
  149             if not dataRef.datasetExists(
"calexp"):
 
  150                 self.log.
warning(
"CalExp for %s does not exist: ignoring", dataRef.dataId)
 
  152             wcs_bbox_tuple_list.append((dataRef.get(
"calexp_wcs", immediate=
True),
 
  153                                         dataRef.get(
"calexp_bbox", 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_bbox_tuple_list, oldSkyMap)
 
  162         if self.config.doWrite:
 
  163             butler.put(result.skyMap, datasetName)
 
  167     def run(self, wcs_bbox_tuple_list, oldSkyMap=None):
 
  168         """Make a SkyMap from the bounds of the given set of calexp metadata. 
  172         wcs_bbox_tuple_list : iterable 
  173            A list of tuples with each element expected to be a (Wcs, Box2I) 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_bbox_tuple_list))
 
  183         for wcs, boxI 
in wcs_bbox_tuple_list:
 
  185             points.extend(wcs.pixelToSky(corner).getVector() 
for corner 
in boxD.getCorners())
 
  187             raise RuntimeError(
"No data found from which to compute convex hull")
 
  188         self.log.
info(
"Computing spherical convex hull")
 
  192                 "Failed to compute convex hull of the vertices of all calexp bounding boxes; " 
  193                 "they may not be hemispherical." 
  195         circle = polygon.getBoundingCircle()
 
  197         skyMapConfig = DiscreteSkyMap.ConfigClass()
 
  199             skyMapConfig.raList.extend(oldSkyMap.config.raList)
 
  200             skyMapConfig.decList.extend(oldSkyMap.config.decList)
 
  201             skyMapConfig.radiusList.extend(oldSkyMap.config.radiusList)
 
  202         configIntersection = {k: getattr(self.config.skyMap, k)
 
  203                               for k 
in self.config.skyMap.toDict()
 
  204                               if k 
in skyMapConfig}
 
  205         skyMapConfig.update(**configIntersection)
 
  207         skyMapConfig.raList.append(circleCenter[0].asDegrees())
 
  208         skyMapConfig.decList.append(circleCenter[1].asDegrees())
 
  209         circleRadiusDeg = circle.getOpeningAngle().asDegrees()
 
  210         skyMapConfig.radiusList.append(circleRadiusDeg + self.config.borderSize)
 
  213         for tractInfo 
in skyMap:
 
  214             wcs = tractInfo.getWcs()
 
  222             skyPosList = [wcs.pixelToSky(pos).getPosition(geom.degrees) 
for pos 
in pixelPosList]
 
  223             posStrList = [
"(%0.3f, %0.3f)" % tuple(skyPos) 
for skyPos 
in skyPosList]
 
  224             self.log.
info(
"tract %s has corners %s (RA, Dec deg) and %s x %s patches",
 
  225                           tractInfo.getId(), 
", ".join(posStrList),
 
  226                           tractInfo.getNumPatches()[0], tractInfo.getNumPatches()[1])
 
  227         return pipeBase.Struct(
 
  231     def _getConfigName(self):
 
  232         """Return None to disable saving config 
  234         There's only one SkyMap per repository, so the config is redundant, and checking it means we can't 
  235         easily overwrite or append to an existing repository. 
  239     def _getMetadataName(self):
 
  240         """Return None to disable saving metadata 
  242         The metadata is not interesting, and by not saving it we can eliminate a dataset type. 
  247     def _makeArgumentParser(cls):
 
  248         parser = ArgumentParser(name=cls.
_DefaultName_DefaultName)
 
  249         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.