def buildMetadataImage(self, layerInfoList, width):
        """
        Creates the metadata caption for figures in the style used by WMSViz.
        """
        self.metadataItems = self._buildMetadataItems(layerInfoList)
        self.width = width
        
        width=self.width;height=1600;dpi=100;transparent=False
        figsize=(width / float(dpi), height / float(dpi))
        fig = Figure(figsize=figsize, dpi=dpi, facecolor='w', frameon=(not transparent))
        axes = fig.add_axes([0.04, 0.04, 0.92, 0.92],  frameon=True,xticks=[], yticks=[])
        renderer = Renderer(fig.dpi)


        title, titleHeight = self._drawTitleToAxes(axes, renderer)
        
        txt, textHeight = self._drawMetadataTextToAxes(axes, renderer, self.metadataItems)

        # fit the axis round the text

        pos = axes.get_position()
        newpos = Bbox( [[pos.x0,  pos.y1 - (titleHeight + textHeight) / height], [pos.x1, pos.y1]] )
        axes.set_position(newpos )

        # position the text below the title

        newAxisHeight = (newpos.y1 - newpos.y0) * height
        txt.set_position( (0.02, 0.98 - (titleHeight/newAxisHeight) ))

        for loc, spine in axes.spines.iteritems():
            spine.set_edgecolor(borderColor)
        
        # Draw heading box
        
        headingBoxHeight = titleHeight - 1
        
        axes.add_patch(Rectangle((0, 1.0 - (headingBoxHeight/newAxisHeight)), 1, (headingBoxHeight/newAxisHeight),
                       facecolor=borderColor,
                      fill = True,
                      linewidth=0))

        # reduce the figure height
        
        originalHeight = fig.get_figheight()
        pos = axes.get_position()
        topBound = 20 / float(dpi)
        
        textHeight = (pos.y1 - pos.y0) * originalHeight
        
        newHeight = topBound * 2 + textHeight
        
        # work out the new proportions for the figure
        
        border = topBound / float(newHeight)
        newpos = Bbox( [[pos.x0,  border], [pos.x1, 1 - border]] )
        axes.set_position(newpos )
        
        fig.set_figheight(newHeight)
        
        return image_util.figureToImage(fig)
    def buildMetadataImage(self, layerInfoList, width):
        """
        Creates the metadata caption for figures in styles that display a title only.
        """
        # Find first non-outline layer.
        nonOutlineLayers = [l for l in layerInfoList if l.id != outline_layer.OUTLINE_LAYER_ID]
        layerInfo = nonOutlineLayers[0] if len(nonOutlineLayers) > 0 else None

        # Get the title of the first set of keyword data, i.e., that for the layer rather than one
        # of its antecedent layers or datasets.
        titleText = ''
        if layerInfo and (len(layerInfo.keywordData) > 0):
            titleText = layerInfo.keywordData[0].get('title', '')

        height = 500
        dpi = 100
        transparent = False

        figsize = (width / float(dpi), height / float(dpi))
        fig = Figure(figsize=figsize, dpi=dpi, facecolor='w', frameon=(not transparent))
        renderer = Renderer(fig.dpi)

        text = fig.text(0.5, 0.98, titleText,
                        fontdict=titleFont,
                        horizontalalignment='center',
                        verticalalignment='top')

        # Trim the height of the text image.
        extent = text.get_window_extent(renderer)
        textHeight = (extent.y1 - extent.y0 + 8)
        fig.set_figheight(textHeight / float(dpi))
        
        return image_util.figureToImage(fig)
    def buildDetailsImage(self, layerInfoList, width):
        """
        Creates the metadata details for figures using templates.
        """
        # Find first non-outline layer.
        nonOutlineLayers = [l for l in layerInfoList if l.id != outline_layer.OUTLINE_LAYER_ID]
        layerInfo = nonOutlineLayers[0] if len(nonOutlineLayers) > 0 else None

        # Flatten the keyword dictionaries, giving priority to entries from descendants over
        # antecedents.
        keywordData = {}
        if layerInfo:
            for kw in reversed(layerInfo.keywordData):
                keywordData.update(kw)

        detailsText = caption_manager.getCaption(layerInfo, keywordData)

        height = 500
        dpi = 100
        transparent = False

        figsize = (width / float(dpi), height / float(dpi))
        fig = Figure(figsize=figsize, dpi=dpi, facecolor='w', frameon=(not transparent))
        renderer = Renderer(fig.dpi)

        text = fig.text(0.02, 0.98, detailsText,
                        fontdict=metadataFont,
                        horizontalalignment='left',
                        verticalalignment='top')

        # Trim the height of the text image.
        extent = text.get_window_extent(renderer)
        textHeight = (extent.y1 - extent.y0 + 8)
        fig.set_figheight(textHeight / float(dpi))
        
        return image_util.figureToImage(fig)
Beispiel #4
0
def addAxisToImage(figureOptions, commonLayerParams, layerInfoList,
                   imageCache):
    """Generates the main figure image with axes.
    @param figureOptions: overall options for the figure
    @param commonLayerParams: parameters that apply to all layers
    @param layerInfoList: list of LayerInfo defining layers to include in the figure
    @param imageCache: cache of images that have been generated for layers (used for animations
           where dimensions only vary in the layer over which animation occurs)
    """
    width = int(commonLayerParams.get('WIDTH'))
    height = int(commonLayerParams.get('HEIGHT'))
    log.debug("addAxisToImage %d x %d" % (width, height))
    dpi = 100
    figsize = (width / float(dpi), height / float(dpi))
    # Figure has transparent background so that it can be the top layer, making the grid visible.
    facecolor = 'none' if figureOptions.grid else 'w'
    edgecolor = 'none' if figureOptions.grid else 'w'
    aspect = 'equal'
    transparent = False

    bounds = commonLayerParams['BBOX'].split(',')
    log.debug("bounds = %s" % (bounds, ))
    lonLimits = (float(bounds[0]), float(bounds[2]))
    latLimits = (float(bounds[1]), float(bounds[3]))
    log.debug("lonLimits = %s, latLimits = %s" % (
        lonLimits,
        latLimits,
    ))

    # create an empty image with the axes drawn
    fig = Figure(
        figsize=figsize,
        dpi=dpi,
        facecolor=facecolor,
        edgecolor=edgecolor,
        frameon=(not transparent))

    # Add axes, allowing space for the axis legends and centering the map laterally within the figure.
    sideOffset = 95
    sideOffsetFraction = float(sideOffset) / float(width)
    bottomOffset = 50
    bottomOffsetFraction = float(bottomOffset) / float(height)
    bbox = [
        sideOffsetFraction, bottomOffsetFraction, (1 - 2 * sideOffsetFraction),
        (1 - 2 * bottomOffsetFraction)
    ]
    log.debug("bbox %s" % bbox)

    axes = fig.add_axes(bbox, frameon=True)
    axes.patch.set_facecolor(facecolor)

    axes.set_aspect(aspect)
    log.debug("axes.get_position(original=False) = %s" %
              (axes.get_position(original=False), ))

    axes.set_xlabel('Longitude')
    axes.set_ylabel('Latitude')

    axes.set_xlim(lonLimits)
    axes.set_ylim(latLimits)

    # Use tick values that are more suited to longitude and latitude if an appropriate set can be
    # found, otherwise use default ticks.
    xTicks = _getAxisTicksAtMultiplesOfBase(lonLimits, 15, 6, 9)
    if xTicks:
        axes.set_xticks(xTicks)
    yTicks = _getAxisTicksAtMultiplesOfBase(latLimits, 15, 4, 7)
    if yTicks:
        axes.set_yticks(yTicks)

    axes.xaxis.set_major_formatter(FuncFormatter(xMajorFormatter))
    axes.yaxis.set_major_formatter(FuncFormatter(yMajorFormatter))

    # Add grid.
    axes.grid(figureOptions.grid, linestyle='--')

    axesImage = image_util.figureToImage(fig)

    # Use the points to get the size of the new image.
    points = axes.get_position().get_points()

    bottom = int(round(height * points[0][1]))
    left = int(round(width * points[0][0]))
    right = int(round(width * points[1][0]))
    top = int(round(height * points[1][1]))

    box = (left, bottom, right, top)

    # Calculate the new width & height.
    commonLayerParams['WIDTH'] = str(right - left)
    commonLayerParams['HEIGHT'] = str(top - bottom)

    log.debug(
        "commonLayerParams['WIDTH'] = %s" % (commonLayerParams['WIDTH'], ))
    log.debug(
        "commonLayerParams['HEIGHT'] = %s" % (commonLayerParams['HEIGHT'], ))

    # Apply the new size to the layer parameters.
    figure_parameters.updateLayerParameters(
        layerInfoList, {
            'WIDTH': commonLayerParams['WIDTH'],
            'HEIGHT': commonLayerParams['HEIGHT']
        })

    # Request the new GetMap images.
    mapImage = buildImage(layerInfoList, imageCache)

    log.debug("axesImage.size = %s, mapImage.size = %s, box = %s" % (
        axesImage.size,
        mapImage.size,
        box,
    ))

    if figureOptions.grid:
        # Build the combined image on a white, opaque background.
        size = axesImage.size
        combinedImage = Image.new('RGBA', size, (255, 255, 255, 255))

        # Note that the alpha channel in the images is ignored by paste - the image must be explicitly
        # set as a mask.
        combinedImage.paste(mapImage, box, mapImage)
        combinedImage.paste(axesImage, (0, 0, size[0], size[1]), axesImage)
    else:
        # No grid so map image can be pasted into axes.
        combinedImage = axesImage
        combinedImage.paste(mapImage, box, mapImage)

    return combinedImage, box