Exemplo n.º 1
0
    def run(self, butler, dataRefList):
        """!Make a skymap from the bounds of the given set of calexps.

        @param[in]  butler        data butler used to save the SkyMap
        @param[in]  dataRefList   dataRefs of calexps used to determine the size and pointing of the SkyMap
        @return     a pipeBase Struct containing:
                    - skyMap: the constructed SkyMap
        """
        self.log.info("Extracting bounding boxes of %d images" % len(dataRefList))
        points = []
        for dataRef in dataRefList:
            if not dataRef.datasetExists("calexp"):
                self.log.warn("CalExp for %s does not exist: ignoring" % (dataRef.dataId,))
                continue
            md = dataRef.get("calexp_md", immediate=True)
            wcs = afwGeom.makeSkyWcs(md)
            # nb: don't need to worry about xy0 because Exposure saves Wcs with CRPIX shifted by (-x0, -y0).
            boxI = afwImage.bboxFromMetadata(md)
            boxD = afwGeom.Box2D(boxI)
            points.extend(wcs.pixelToSky(corner).getVector() for corner in boxD.getCorners())
        if len(points) == 0:
            raise RuntimeError("No data found from which to compute convex hull")
        self.log.info("Computing spherical convex hull")
        polygon = lsst.sphgeom.ConvexPolygon.convexHull(points)
        if polygon is None:
            raise RuntimeError(
                "Failed to compute convex hull of the vertices of all calexp bounding boxes; "
                "they may not be hemispherical."
            )
        circle = polygon.getBoundingCircle()

        datasetName = self.config.coaddName + "Coadd_skyMap"

        skyMapConfig = DiscreteSkyMap.ConfigClass()
        if self.config.doAppend and butler.datasetExists(datasetName):
            oldSkyMap = butler.get(datasetName, immediate=True)
            if not isinstance(oldSkyMap.config, DiscreteSkyMap.ConfigClass):
                raise TypeError("Cannot append to existing non-discrete skymap")
            compareLog = []
            if not self.config.skyMap.compare(oldSkyMap.config, output=compareLog.append):
                raise ValueError("Cannot append to existing skymap - configurations differ:", *compareLog)
            skyMapConfig.raList.extend(oldSkyMap.config.raList)
            skyMapConfig.decList.extend(oldSkyMap.config.decList)
            skyMapConfig.radiusList.extend(oldSkyMap.config.radiusList)
        skyMapConfig.update(**self.config.skyMap.toDict())
        circleCenter = lsst.sphgeom.LonLat(circle.getCenter())
        skyMapConfig.raList.append(circleCenter[0].asDegrees())
        skyMapConfig.decList.append(circleCenter[1].asDegrees())
        circleRadiusDeg = circle.getOpeningAngle().asDegrees()
        skyMapConfig.radiusList.append(circleRadiusDeg + self.config.borderSize)
        skyMap = DiscreteSkyMap(skyMapConfig)

        for tractInfo in skyMap:
            wcs = tractInfo.getWcs()
            posBox = afwGeom.Box2D(tractInfo.getBBox())
            pixelPosList = (
                posBox.getMin(),
                afwGeom.Point2D(posBox.getMaxX(), posBox.getMinY()),
                posBox.getMax(),
                afwGeom.Point2D(posBox.getMinX(), posBox.getMaxY()),
            )
            skyPosList = [wcs.pixelToSky(pos).getPosition(afwGeom.degrees) for pos in pixelPosList]
            posStrList = ["(%0.3f, %0.3f)" % tuple(skyPos) for skyPos in skyPosList]
            self.log.info("tract %s has corners %s (RA, Dec deg) and %s x %s patches" %
                          (tractInfo.getId(), ", ".join(posStrList),
                           tractInfo.getNumPatches()[0], tractInfo.getNumPatches()[1]))
        if self.config.doWrite:
            butler.put(skyMap, datasetName)
        return pipeBase.Struct(
            skyMap=skyMap
        )
Exemplo n.º 2
0
    def run(self, wcs_bbox_tuple_list, oldSkyMap=None):
        """Make a SkyMap from the bounds of the given set of calexp metadata.

        Parameters
        ----------
        wcs_bbox_tuple_list : iterable
           A list of tuples with each element expected to be a (Wcs, Box2I) pair
        oldSkyMap : `lsst.skymap.DiscreteSkyMap`, option
           The SkyMap to extend if appending
        Returns
        -------
        struct : `lsst.pipe.base.Struct
           The returned struct has one attribute, ``skyMap``, which holds the returned SkyMap
        """
        self.log.info("Extracting bounding boxes of %d images",
                      len(wcs_bbox_tuple_list))
        points = []
        for wcs, boxI in wcs_bbox_tuple_list:
            boxD = geom.Box2D(boxI)
            points.extend(
                wcs.pixelToSky(corner).getVector()
                for corner in boxD.getCorners())
        if len(points) == 0:
            raise RuntimeError(
                "No data found from which to compute convex hull")
        self.log.info("Computing spherical convex hull")
        polygon = lsst.sphgeom.ConvexPolygon.convexHull(points)
        if polygon is None:
            raise RuntimeError(
                "Failed to compute convex hull of the vertices of all calexp bounding boxes; "
                "they may not be hemispherical.")
        circle = polygon.getBoundingCircle()

        skyMapConfig = DiscreteSkyMap.ConfigClass()
        if oldSkyMap:
            skyMapConfig.raList.extend(oldSkyMap.config.raList)
            skyMapConfig.decList.extend(oldSkyMap.config.decList)
            skyMapConfig.radiusList.extend(oldSkyMap.config.radiusList)
        configIntersection = {
            k: getattr(self.config.skyMap, k)
            for k in self.config.skyMap.toDict() if k in skyMapConfig
        }
        skyMapConfig.update(**configIntersection)
        circleCenter = lsst.sphgeom.LonLat(circle.getCenter())
        skyMapConfig.raList.append(circleCenter[0].asDegrees())
        skyMapConfig.decList.append(circleCenter[1].asDegrees())
        circleRadiusDeg = circle.getOpeningAngle().asDegrees()
        skyMapConfig.radiusList.append(circleRadiusDeg +
                                       self.config.borderSize)
        skyMap = DiscreteSkyMap(skyMapConfig)

        for tractInfo in skyMap:
            wcs = tractInfo.getWcs()
            posBox = geom.Box2D(tractInfo.getBBox())
            pixelPosList = (
                posBox.getMin(),
                geom.Point2D(posBox.getMaxX(), posBox.getMinY()),
                posBox.getMax(),
                geom.Point2D(posBox.getMinX(), posBox.getMaxY()),
            )
            skyPosList = [
                wcs.pixelToSky(pos).getPosition(geom.degrees)
                for pos in pixelPosList
            ]
            posStrList = [
                "(%0.3f, %0.3f)" % tuple(skyPos) for skyPos in skyPosList
            ]
            self.log.info(
                "tract %s has corners %s (RA, Dec deg) and %s x %s patches",
                tractInfo.getId(), ", ".join(posStrList),
                tractInfo.getNumPatches()[0],
                tractInfo.getNumPatches()[1])
        return pipeBase.Struct(skyMap=skyMap)