Example #1
0
    def draw(self, dataTable, functionTable, performanceTable, rowIndex, colIndex, cellContents, labelAttributes, plotDefinitions):
        """Draw the plot legend content, which is more often text than graphics.

        @type dataTable: DataTable
        @param dataTable: Contains the data to describe, if any.
        @type functionTable: FunctionTable
        @param functionTable: Defines functions that may be used to transform data.
        @type performanceTable: PerformanceTable
        @param performanceTable: Measures and records performance (time and memory consumption) of the drawing process.
        @type rowIndex: int
        @param rowIndex: Row number of the C{cellContents} to fill.
        @type colIndex: int
        @param colIndex: Column number of the C{cellContents} to fill.
        @type cellContents: dict
        @param cellContents: Dictionary that maps pairs of integers to SVG graphics to draw.
        @type labelAttributes: CSS style dict
        @param labelAttributes: Style properties that are defined at the level of the legend and must percolate down to all drawables within the legend.
        @type plotDefinitions: PlotDefinitions
        @type plotDefinitions: The dictionary of key-value pairs that forms the <defs> section of the SVG document.
        @rtype: 2-tuple
        @return: The next C{rowIndex} and C{colIndex} in the sequence.
        """

        svg = SvgBinding.elementMaker

        svgId = self.get("svgId")
        if svgId is None:
            output = svg.g()
        else:
            output = svg.g(**{"id": svgId})

        inlineSvg = self.getchildren()
        fileName = self.get("fileName")
        if len(inlineSvg) == 1 and fileName is None:
            svgBinding = copy.deepcopy(inlineSvg[0])
        elif len(inlineSvg) == 0 and fileName is not None:
            svgBinding = SvgBinding.loadXml(fileName)
        else:
            raise defs.PmmlValidationError("PlotLegendSvg should specify an inline SVG or a fileName but not both or neither")

        sx1, sy1, sx2, sy2 = PlotSvgAnnotation.findSize(svgBinding)
        nominalHeight = sy2 - sy1
        nominalWidth = sx2 - sx1

        # TODO: set this correctly from the text height
        rowHeight = 30.0

        # output["transform"] = "translate(%r, %r) scale(%r, %r)" % (-sx1, -sy1, rowHeight/float(sx2 - sx1), rowHeight/float(sy2 - sy1))
        output["transform"] = "translate(%r, %r) scale(%r, %r)" % (-sx1 - 0.5*nominalWidth*rowHeight/nominalHeight, -sy1 - 0.75*rowHeight, rowHeight/nominalHeight, rowHeight/nominalHeight)
        output.append(svgBinding)
        
        cellContents[rowIndex, colIndex] = svg.g(output)
        cellContents[rowIndex, colIndex].text = "  "   # TODO: set the width correctly, too
        colIndex += 1

        return rowIndex, colIndex
Example #2
0
    def draw(self, state, plotCoordinates, plotDefinitions, performanceTable):
        """Draw the plot element.

        This stage consists of creating an SVG image of the
        pre-computed data.

        @type state: ad-hoc Python object
        @param state: State information that persists long enough to use quantities computed in C{prepare} in the C{draw} stage.  This is a work-around of lxml's refusal to let its Python instances maintain C{self} and it is unrelated to DataTableState.
        @type plotCoordinates: PlotCoordinates
        @param plotCoordinates: The coordinate system in which this plot element will be placed.
        @type plotDefinitions: PlotDefinitions
        @type plotDefinitions: The dictionary of key-value pairs that forms the <defs> section of the SVG document.
        @type performanceTable: PerformanceTable
        @param performanceTable: Measures and records performance (time and memory consumption) of the drawing process.
        @rtype: SvgBinding
        @return: An SVG fragment representing the fully drawn plot element.
        """

        svg = SvgBinding.elementMaker

        x1 = float(self["x1"])
        y1 = float(self["y1"])
        x2 = float(self["x2"])
        y2 = float(self["y2"])

        inlineSvg = self.getchildren()
        fileName = self.get("fileName")
        if len(inlineSvg) == 1 and fileName is None:
            svgBinding = inlineSvg[0]
        elif len(inlineSvg) == 0 and fileName is not None:
            svgBinding = SvgBinding.loadXml(fileName)
        else:
            raise defs.PmmlValidationError(
                "PlotSvgContent should specify an inline SVG or a fileName but not both or neither"
            )

        sx1, sy1, sx2, sy2 = PlotSvgAnnotation.findSize(svgBinding)
        subCoordinates = PlotCoordinatesWindow(plotCoordinates, sx1, sy1, sx2,
                                               sy2, x1, y1, x2 - x1, y2 - y1)

        tx0, ty0 = subCoordinates(0.0, 0.0)
        tx1, ty1 = subCoordinates(1.0, 1.0)
        transform = "translate(%r, %r) scale(%r, %r)" % (tx0, ty0, tx1 - tx0,
                                                         ty1 - ty0)

        attribs = {"transform": transform}
        svgId = self.get("svgId")
        if svgId is not None:
            attribs["id"] = svgId
        if "style" in svgBinding.attrib:
            attribs["style"] = svgBinding.attrib["style"]

        return svg.g(*(copy.deepcopy(svgBinding).getchildren()), **attribs)
Example #3
0
    def draw(self, state, plotCoordinates, plotDefinitions, performanceTable):
        """Draw the plot element.

        This stage consists of creating an SVG image of the
        pre-computed data.

        @type state: ad-hoc Python object
        @param state: State information that persists long enough to use quantities computed in C{prepare} in the C{draw} stage.  This is a work-around of lxml's refusal to let its Python instances maintain C{self} and it is unrelated to DataTableState.
        @type plotCoordinates: PlotCoordinates
        @param plotCoordinates: The coordinate system in which this plot element will be placed.
        @type plotDefinitions: PlotDefinitions
        @type plotDefinitions: The dictionary of key-value pairs that forms the <defs> section of the SVG document.
        @type performanceTable: PerformanceTable
        @param performanceTable: Measures and records performance (time and memory consumption) of the drawing process.
        @rtype: SvgBinding
        @return: An SVG fragment representing the fully drawn plot element.
        """

        svg = SvgBinding.elementMaker

        x1 = float(self["x1"])
        y1 = float(self["y1"])
        x2 = float(self["x2"])
        y2 = float(self["y2"])

        inlineSvg = self.getchildren()
        fileName = self.get("fileName")
        if len(inlineSvg) == 1 and fileName is None:
            svgBinding = inlineSvg[0]
        elif len(inlineSvg) == 0 and fileName is not None:
            svgBinding = SvgBinding.loadXml(fileName)
        else:
            raise defs.PmmlValidationError("PlotSvgContent should specify an inline SVG or a fileName but not both or neither")
        
        sx1, sy1, sx2, sy2 = PlotSvgAnnotation.findSize(svgBinding)
        subCoordinates = PlotCoordinatesWindow(plotCoordinates, sx1, sy1, sx2, sy2, x1, y1, x2 - x1, y2 - y1)

        tx0, ty0 = subCoordinates(0.0, 0.0)
        tx1, ty1 = subCoordinates(1.0, 1.0)
        transform = "translate(%r, %r) scale(%r, %r)" % (tx0, ty0, tx1 - tx0, ty1 - ty0)

        attribs = {"transform": transform}
        svgId = self.get("svgId")
        if svgId is not None:
            attribs["id"] = svgId
        if "style" in svgBinding.attrib:
            attribs["style"] = svgBinding.attrib["style"]

        return svg.g(*(copy.deepcopy(svgBinding).getchildren()), **attribs)
Example #4
0
    def makeMarker(svgIdMarker, marker, style, plotSvgMarker):
        """Construct a marker from a set of known shapes or an SVG
        pictogram.

        @type svgIdMarker: string
        @param svgIdMarker: SVG id for the new marker.
        @type marker: string
        @param marker: Name of the marker shape; must be one of PLOT-MARKER-TYPE.
        @type style: dict
        @param style: CSS style for the marker in dictionary form.
        @type plotSvgMarker: PmmlBinding or None
        @param plotSvgMarker: A PlotSvgMarker element, which either contains an inline SvgBinding or a fileName pointing to an external image.
        @rtype: SvgBinding
        @return: The marker image, appropriate for adding to a PlotDefinitions.
        """

        svg = SvgBinding.elementMaker

        style["stroke"] = style["marker-outline"]
        del style["marker-outline"]
        markerSize = float(style["marker-size"])
        del style["marker-size"]

        if marker == "circle":
            return svg.circle(id=svgIdMarker, cx="0", cy="0", r=repr(markerSize), style=PlotStyle.toString(style))

        elif marker == "square":
            p =  markerSize
            m = -markerSize
            return svg.path(id=svgIdMarker, d="M %r,%r L %r,%r L %r,%r L %r,%r z" % (m,m, p,m, p,p, m,p), style=PlotStyle.toString(style))

        elif marker == "diamond":
            p =  math.sqrt(2.0) * markerSize
            m = -math.sqrt(2.0) * markerSize
            return svg.path(id=svgIdMarker, d="M %r,0 L 0,%r L %r,0 L 0,%r z" % (m, m, p, p), style=PlotStyle.toString(style))

        elif marker == "plus":
            p =  markerSize
            m = -markerSize
            if style["stroke"] == "none":
                style["stroke"] = style["fill"]
            style["fill"] = "none"
            return svg.path(id=svgIdMarker, d="M %r,0 L %r,0 M 0,%r L 0,%r" % (m, p, m, p), style=PlotStyle.toString(style))

        elif marker == "times":
            p =  math.sqrt(2.0) * markerSize
            m = -math.sqrt(2.0) * markerSize
            if style["stroke"] == "none":
                style["stroke"] = style["fill"]
            style["fill"] = "none"
            return svg.path(id=svgIdMarker, d="M %r,%r L %r,%r M %r,%r L %r,%r" % (m,m, p,p, p,m, m,p), style=PlotStyle.toString(style))

        elif marker == "svg":
            if plotSvgMarker is None:
                raise defs.PmmlValidationError("When marker is \"svg\", a PlotSvgMarker must be provided")

            inlineSvg = plotSvgMarker.getchildren()
            fileName = plotSvgMarker.get("fileName")
            if len(inlineSvg) == 1 and fileName is None:
                svgBinding = inlineSvg[0]
            elif len(inlineSvg) == 0 and fileName is not None:
                svgBinding = SvgBinding.loadXml(fileName)
            else:
                raise defs.PmmlValidationError("PlotSvgMarker should specify an inline SVG or a fileName but not both or neither")

            sx1, sy1, sx2, sy2 = PlotSvgAnnotation.findSize(svgBinding)
            tx1, ty1 = -markerSize, -markerSize
            tx2, ty2 = markerSize, markerSize

            transform = "translate(%r, %r) scale(%r, %r)" % (tx1 - sx1, ty1 - sy1, (tx2 - tx1)/float(sx2 - sx1), (ty2 - ty1)/float(sy2 - sy1))
            return svg.g(copy.deepcopy(svgBinding), id=svgIdMarker, transform=transform)
Example #5
0
    def makeMarker(svgIdMarker, marker, style, plotSvgMarker):
        """Construct a marker from a set of known shapes or an SVG
        pictogram.

        @type svgIdMarker: string
        @param svgIdMarker: SVG id for the new marker.
        @type marker: string
        @param marker: Name of the marker shape; must be one of PLOT-MARKER-TYPE.
        @type style: dict
        @param style: CSS style for the marker in dictionary form.
        @type plotSvgMarker: PmmlBinding or None
        @param plotSvgMarker: A PlotSvgMarker element, which either contains an inline SvgBinding or a fileName pointing to an external image.
        @rtype: SvgBinding
        @return: The marker image, appropriate for adding to a PlotDefinitions.
        """

        svg = SvgBinding.elementMaker

        style["stroke"] = style["marker-outline"]
        del style["marker-outline"]
        markerSize = float(style["marker-size"])
        del style["marker-size"]

        if marker == "circle":
            return svg.circle(id=svgIdMarker, cx="0", cy="0", r=repr(markerSize), style=PlotStyle.toString(style))

        elif marker == "square":
            p =  markerSize
            m = -markerSize
            return svg.path(id=svgIdMarker, d="M %r,%r L %r,%r L %r,%r L %r,%r z" % (m,m, p,m, p,p, m,p), style=PlotStyle.toString(style))

        elif marker == "diamond":
            p =  math.sqrt(2.0) * markerSize
            m = -math.sqrt(2.0) * markerSize
            return svg.path(id=svgIdMarker, d="M %r,0 L 0,%r L %r,0 L 0,%r z" % (m, m, p, p), style=PlotStyle.toString(style))

        elif marker == "plus":
            p =  markerSize
            m = -markerSize
            if style["stroke"] == "none":
                style["stroke"] = style["fill"]
            style["fill"] = "none"
            return svg.path(id=svgIdMarker, d="M %r,0 L %r,0 M 0,%r L 0,%r" % (m, p, m, p), style=PlotStyle.toString(style))

        elif marker == "times":
            p =  math.sqrt(2.0) * markerSize
            m = -math.sqrt(2.0) * markerSize
            if style["stroke"] == "none":
                style["stroke"] = style["fill"]
            style["fill"] = "none"
            return svg.path(id=svgIdMarker, d="M %r,%r L %r,%r M %r,%r L %r,%r" % (m,m, p,p, p,m, m,p), style=PlotStyle.toString(style))

        elif marker == "svg":
            if plotSvgMarker is None:
                raise defs.PmmlValidationError("When marker is \"svg\", a PlotSvgMarker must be provided")

            inlineSvg = plotSvgMarker.getchildren()
            fileName = plotSvgMarker.get("fileName")
            if len(inlineSvg) == 1 and fileName is None:
                svgBinding = inlineSvg[0]
            elif len(inlineSvg) == 0 and fileName is not None:
                svgBinding = SvgBinding.loadXml(fileName)
            else:
                raise defs.PmmlValidationError("PlotSvgMarker should specify an inline SVG or a fileName but not both or neither")

            sx1, sy1, sx2, sy2 = PlotSvgAnnotation.findSize(svgBinding)
            tx1, ty1 = -markerSize, -markerSize
            tx2, ty2 = markerSize, markerSize

            transform = "translate(%r, %r) scale(%r, %r)" % (tx1 - sx1, ty1 - sy1, (tx2 - tx1)/float(sx2 - sx1), (ty2 - ty1)/float(sy2 - sy1))
            return svg.g(copy.deepcopy(svgBinding), id=svgIdMarker, transform=transform)