+

Generating Structured and Labelled SVG

Paul Murrell

University of Auckland
Department of Statistics

Simon Potter

University of Auckland
Department of Statistics
This document is licensed under a Creative Commons Attribution 3.0 New Zealand License .

Abstract

This article discusses the importance of providing structure and labelling within SVG code, particularly when the SVG code is generated indirectly by a high-level system and when the SVG code describes a complex image such as a statistical plot. We argue that this is a desirable goal, but that many high-level systems that generate SVG do not provide sufficient structure and labelling. An example of a system, based on R, that does provide structure and labelling, is described to demonstrate that the goal is acheivable and we highlight the crucial features of this system that we see as important factors in achieving this goal.


Introduction
The importance of structure and labelling
Generating SVG code
Generating structured and labelled SVG
Generating SVG from grid
Generating structure and labels from lattice
Discovering structure and labelling
An example
Summary
Discussion
A. Software used in this report
B. Other Software for Generating SVG
plot2svg
Gnumeric
gRaphael
Highcharts
Bibliography

Introduction

SVG is a language for describing images. It is both a vector graphics language, meaning images are described as a series of shapes rather than a raster matrix, and it is a markup language, meaning that components of the image are described using elements consisting of tags and attributes. For example, Figure 1, “Code for a simple image” shows SVG code for a simple image that consists of two rectangles (<rect> elements) and two circles (<circle> elements; see Figure 2, “A simple image”).

Figure 1. A simple image, described using SVG, that consists of two rectangles and two circles.

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" 
     width="250" height="150">
  <g transform="translate(25, 25)">
    <rect x="0" y="0" width="100" height="100"
          stroke="black" fill="white"/>
    <rect x="100" y="0" width="100" height="100"
          stroke="black" fill="white"/>
    <circle cx="50" cy="50" r="30"/>
    <circle cx="150" cy="50" r="30"/>
  </g>
</svg>

Figure 2. A simple image, described using SVG, that consists of two rectangles and two circles.


Two important features of the code in Figure 1, “Code for a simple image” are the structure of the code and the labelling of the code. An example of the structure in this code is demonstrated by the way that elements are nested within each other (the <rect> and <circle> elements are nested within a <g> element) and an example of the labelling in this code is the way that every component of the image is a named element (either a <rect> or a <circle>) and every piece of information about each component, such as location or colour, is a named attribute (e.g., fill="white") .

This structure and labelling within an SVG image is important because it makes it possible to identify each component of the image, either by where the component is within the structure of the document or by the type of element used to represent the component or the attributes associated with the component.

This report will briefly demonstrate why this structure and labelling is useful in SVG images and then discuss how difficult it is to generate good structure and labelling for complex SVG images, such as statistical plots. We will demonstrate that good structure and labelling is possible using the R language for statistical computing and graphics and attempt to summarise the important features that are necessary to provide structure and labelling for complex images.

The importance of structure and labelling

One advantage of using markup like SVG for images is that style information can be specified separately from the description of the image content. For example, the code in Figure 3, “Code for a simple image with CSS” modifies the simple image in Figure 2, “A simple image” by adding CSS styling code within a <style> element. Additional class attributes have also been added to the two <rect> elements. This CSS code changes the fill colour to grey for both circles and changes the fill colour to black for the rectangle on the left of the image (see Figure 4, “A simple image with CSS”).

The CSS code works by associating properties, such as fill: black, with specific elements within the image and it identifies specific elements within the image via selectors. For example, the selector circle specifies all <circle> elements within the image. The selector rect.left specifies any <rect> elements that have the attribute class="left". In other words, the CSS code relies on labelling within the SVG to be able to associate styling information with specific components of the image.

Figure 3. A simple image, described using SVG, that consists of two rectangles and two circles, with styling controlled via CSS.

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" 
     width="250" height="150">
  <style type="text/css">
    circle    { fill: #DDDDDD }
    rect.left { fill: black }
  </style>
  <g transform="translate(25, 25)">
    <rect x="0" y="0" width="100" height="100"
          stroke="black" fill="white"
          class="left"/>
    <rect x="100" y="0" width="100" height="100"
          stroke="black" fill="white"
          class="right"/>
    <circle cx="50" cy="50" r="30"/>
    <circle cx="150" cy="50" r="30"/>
  </g>
</svg>

Figure 4. A simple image, described using SVG, that consists of two rectangles and two circles, with styling controlled via CSS.


Another advantage of using markup is that interactive behaviour can be attached to components of the image. For example, the code in Figure 5, “Code for a simple image with javascript” extends the original image by adding javascript code within a <script> element. Additional id and on-click attributes have also been added to the second <rect> element. Now if we click on the rectangle on the right of the image its fill is changed to black (see Figure 6, “A simple image with javascript”).

The javascript code works by identifying a specific component of the image, using the getElementById() function, and then changing that element's fill colour. In this case, the javascript code targets the unique element with the attribute id="rect-2". Again, the javascript code relies on labelling within the SVG code to be able to identify which element to change.

Figure 5. A simple image, described using SVG, that consists of two rectangles and two circles, with interaction added via javascript.

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" 
     width="250" height="150">
  <style type="text/css">
    circle    { fill:   #DDDDDD }
    rect.left { fill:   black }
  </style>
  <script type="application/ecmascript">
    changeBG = function() {
      r = document.getElementById("rect-2");
      r.setAttribute("fill", "black");
    }
  </script>
  <g transform="translate(25, 25)">
    <rect x="0" y="0" width="100" height="100"
          stroke="black" fill="white"
          class="left"/>
    <rect x="100" y="0" width="100" height="100"
          stroke="black" fill="white"
          class="right"
          id="rect-2" onclick="changeBG()"/>
    <circle cx="50" cy="50" r="30"/>
    <circle cx="150" cy="50" r="30"/>
  </g>
</svg>

Figure 6. A simple image, described using SVG, that consists of two rectangles and two circles, with interaction added via javascript; when the right rectangle is clicked, it turns black.


A third advantage of using markup is that the image can be programmatically processed to add, remove, or modify components of the image. For example, the code in Figure 7, “Code for transforming a simple image” uses XSLT to transform the original SVG image so that we extract just the circle on the left of the image and the rectangle on the right of the image (see Figure 8, “A transformed image”).

This XSLT code works by copying specific components of the SVG image and it identifies specific components using XPath expressions. For example, the XPath expression svg:svg/svg:g/svg:circle[1] identifies the first <circle> element that is a child of a <g> element, which in turn is a child of the top-level <svg> element. The XPath expression //svg:rect[@class='right'] identifies any rectangle element that has the attribute class="right". Yet again, the XSLT code relies on the structure and labelling of the SVG code to identify which components of the image to process.

Figure 7. Code to process the simple image to extract just the left circle and the right rectangle.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:svg="http://www.w3.org/2000/svg" 
                version='1.0'>
  <xsl:template match="/">
    <svg xmlns="http://www.w3.org/2000/svg" 
         width="250" height="150">
      <g transform="translate(25, 25)">
        <xsl:copy-of select="//svg:rect[@class='right']"/>
        <xsl:copy-of select="svg:svg/svg:g/svg:circle[1]"/>
      </g>
    </svg>
  </xsl:template>
</xsl:stylesheet>

Figure 8. A transformation of the simple image so that only the left circle and the right rectangle remain.


All three of these cases - the application of CSS styling, the attachment of javascript functions, and the processing via XSLT - are very dependent on being able to identify specific components of the image. To some extent, we get landmarks or signposts within a document - element names, attributes, and nesting of elements - simply because we are using a markup language. For example, the SVG language definition requires that the outermost element must be an <svg> element and it dictates that <rect> elements have attributes x and y whereas <circle> elements have attributes cx and cy. However, there is a still a lot of freedom and variation within the markup language definition so that a very wide range of images is possible. The problem that then arises is how to ensure that it is still possible to identify every separate component of the image, even when images become large and complex.

Generating SVG code

One way to provide structure and labelling for an SVG image is to manually generate the SVG code (as in Figure 1, “Code for a simple image”). However, this method rapidly becomes impractical. For example, the statistical plot in Figure 9, “A complex image” requires over 450 lines of SVG code and the positioning of the text, lines, and data symbols within the image is not something that would be simple to do by hand.

Figure 9. A complex SVG image consisting of a ggplot2 plot


In order to generate a complex SVG image it becomes necessary to use a higher-level system that automates the generation of SVG code. The example used in Figure 9, “A complex image” was generated with R using the code shown in Figure 10, “R code for a complex image” (code to load the data not shown). This is clearly a lot easier than writing the SVG by hand, but what does the SVG that R generates look like? Is the SVG code generated by R nicely structured and labelled?

Figure 10. R code to generate a statistical plot

+
ggplot(elec, aes(x=volume, y=price, colour=source)) +
       geom_point() +
       facet_wrap(~ year, nrow=1)

Figure 11, “SVG code generated by R” shows some fragments from the SVG code for Figure 9, “A complex image”. This is enough to show the sort of problem that automatically generated SVG can suffer from. There is no obvious way to associate these SVG elements with specific components of the SVG image in Figure 9, “A complex image”. So the price of not having to generate SVG code manually is that the automatically generated SVG code does not have useful structure or labelling.

Figure 11. SVG code generated by R


<rect x="0" y="0" width="576" height="288" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/> <rect x="0" y="0" width="576" height="288" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/> <path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 288 L 576 288 L 576 0 L 0 0 Z M 0 288 "/> <g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> <use xlink:href="#glyph0-0" x="86.457031" y="69.999023"/> <use xlink:href="#glyph0-1" x="91.791016" y="69.999023"/> <use xlink:href="#glyph0-1" x="97.125" y="69.999023"/> <use xlink:href="#glyph0-2" x="102.458984" y="69.999023"/> </g>

This example is a particularly clear demonstration of unstructured SVG generation. Appendix B, Other Software for Generating SVG presents some other examples of SVG generation from several other software systems: two javascript libraries, gRaphael and Highcharts; the plot2svg extension package for Matlab; and the gnumeric spreadsheet software. These are not all as bad as this example, but they all fall short in some way of the ideal of fully structured and labelled SVG.

Generating structured and labelled SVG

The SVG code produced by R in Figure 11, “SVG code generated by R” is actually only one way to generate SVG from R. That example used the Cairo-based graphics device in R, which is available through the svg() function from the grDevices package. An alternative way to generate SVG from R is via the gridSVG package. This section demonstrates that this alternative approach can be used to generate SVG that is both structured and labelled.

Generating SVG from grid

The starting point for generating SVG from R using the gridSVG package, is to produce an image using the grid package. For example, the code in Figure 12, “grid code for a simple image” draws an image similar to the very simple SVG image in Figure 2, “A simple image” (see Figure 13, “A simple grid image”). Important points about this code are that the rectangles and circles are drawn within a grid viewport, which defines a sub-region on the page, there is a single function call to produce the two rectangles and a single function call to produce the two circles, and the rectangles and the circles (and the viewport) are explicitly named.

Figure 12. grid code to generate a simple image

+
pushViewport(viewport(width=.8, height=.8,
                      name="margin"))
grid.rect(x=0:1/2, width=1/2, just="left",
          name="rect")
grid.circle(x=c(1, 3)/4, r=1/4,
            gp=gpar(fill="black"),
            name="circ")
popViewport()

Figure 13. A simple SVG image produced using grid


A structured and labelled SVG version of the image can then be generated using the gridToSVG() function from the gridSVG package. The code in Figure 14, “gridSVG code” shows the simple call required and Figure 15, “SVG code from gridSVG” shows the SVG code that is produced. One important feature of this SVG code is the fact that the <rect> and <circle> elements are nested within a <g> element that represents the grid viewport in the original image. The <rect> elements are further nested within another <g> element, reflecting the fact that they were both generated by a single call to the function grid.rect(), and the <circle> elements are similarly nested. Finally, all elements have id attributes based on the names that were specified in the grid code.

Figure 14. gridSVG code to generate SVG code from a grid image

+
gridToSVG("grid-fig.svg")

Figure 15. SVG code generated from R using the gridSVG package


<g id="margin.1"> <g id="rect.1"> <rect id="rect.1.1" x="14.4" y="7.2" width="57.6" height="57.6"/> <rect id="rect.1.2" x="72" y="7.2" width="57.6" height="57.6"/> </g> <g id="circ.1"> <circle id="circ.1.1" cx="43.2" cy="36" r="14.4" fill="rgb(0,0,0)" fill-opacity="1"/> <circle id="circ.1.2" cx="100.8" cy="36" r="14.4" fill="rgb(0,0,0)" fill-opacity="1"/> </g> </g>

In summary, using grid, it is possible to generate an image with structure and labelling and then gridSVG produces SVG code that retains that structure and labelling.

Generating structure and labels from lattice

One simple thing that we have demonstrated so far is that structure and labelling can be manually specified with grid, much like it can be manually specified with SVG, but what we are more interested in is the ability to generate a complex image, such as a statistical plot, that has useful structure and labelling. This is where the lattice package comes in.

The lattice package uses grid to render sophisticated and complex statistical plots. For example, the code in Figure 16, “R code for a complex image” is all that is required to generate the plot in Figure 17, “A complex grid image”.

Figure 16. R code to generate a statistical plot

+
xyplot(price ~ volume | year, elec, group=source)

Figure 17. A complex SVG image consisting of a lattice plot


This image actually contains a great deal of structure and labelling. The grid.ls() function can be used to show the names of all grid objects within an image and Figure 18, “Labelling in a lattice plot” shows part of the list for the plot in Figure 17, “A complex grid image”. This shows that every component of the plot, right down to the tick marks on the left side of the panel in row 1, column 1 (plot_01.ticks.left.panel.1.1), has a detailed label.

Figure 18. A listing of the grid objects in a statistical plot produced by lattice

+
grid.ls()
 [1] "plot_01.background"                     
 [2] "plot_01.xlab"                           
 [3] "plot_01.ylab"                           
 [4] "plot_01.ticks.top.panel.1.1"            
 [5] "plot_01.ticks.left.panel.1.1"           
 [6] "plot_01.ticklabels.left.panel.1.1"      
 [7] "plot_01.ticks.bottom.panel.1.1"         
 [8] "plot_01.ticklabels.bottom.panel.1.1"    
 [9] "plot_01.xyplot.points.group.1.panel.1.1"
[10] "plot_01.xyplot.points.group.2.panel.1.1"
[11] "plot_01.xyplot.points.group.3.panel.1.1"
[12] "plot_01.xyplot.points.group.4.panel.1.1"

If this image is exported to SVG (with code similar to Figure 14, “gridSVG code”), the structure and labelling is preserved. Figure 19, “SVG code from lattice” shows a fragment of the SVG from Figure 17, “A complex grid image”. This fragment shows the SVG code representing the tick marks on the left side of the panel in row 1, column 1. There is structure demonstrated by the nesting of elements (in particular, the top-most <g> element represents the grid viewport that the ticks are drawn within) and there is labelling demonstrated by the id attributes of the <g> and <polyline> elements.

Figure 19. SVG code generated from a lattice plot using the gridSVG package


<g id="plot_01.toplevel.vp::plot_01.strip.1.1.off.vp.1"> <g id="plot_01.ticks.top.panel.1.1.1"> <polyline id="plot_01.ticks.top.panel.1.1.1.1" points="59.98,245.81 59.98,251.48"/> <polyline id="plot_01.ticks.top.panel.1.1.1.2" points="97.59,245.81 97.59,251.48"/> <polyline id="plot_01.ticks.top.panel.1.1.1.3" points="135.21,245.81 135.21,251.48"/> </g> </g>

Discovering structure and labelling

We have demonstrated that it is possible to produce a complex statistical plot with a small amount of code, but still generate highly structured and labelled SVG. This makes it possible to apply styling, add interactivity, or post-process the SVG image, but a major stumbling block remains: how does a person, particularly someone other than the creator of the original plot, discover the structure and labelling of the SVG code?

Simply viewing a displayed image of the SVG (like Figure 17, “A complex grid image”) gives no clues to the SVG structure or labelling. We can see the structure and labelling in the raw SVG code, but relating individual SVG elements to the appropriate component of the displayed image may not always be straightforward, especially in complex images where the SVG code runs to hundreds of lines (there are over 550 lines of SVG code for Figure 17, “A complex grid image”).

Web browsers like Firefox provide powerful tools for manually "inspecting" SVG images, so that it is possible to select a displayed component with the mouse and see the corresponding SVG code. The grid and gridDebug packages in R provide similar functionality, for example, the grid.ls() function mentioned previously. These tools are helpful for interactively exploring the structure and labelling in a single image, but they do not support programmatically modifying an SVG image when, for example, we perform a large batch processing of many SVG images, or we wish to modify many features within a single SVG image (e.g., add tooltips to regions within a map). In that case, it is necessary to understand the algorithm used to produce the structure and labelling so that we can accurately predict the location and id values for elements within the SVG code.

This leads to a need for proper documentation of the algorithm that is used for structuring and labelling the SVG images. Even better, we could use an API that provides functions to assist with generating the location and labels for components of an image.

In the case of generating SVG from R, there is an added complication because the lattice package first generates a structure and labelling for an image and then the gridSVG package translates that structure and labelling to SVG. It is therefore necessary to document both the lattice naming scheme and the gridSVG translation process. In terms of an API, lattice provides two functions, trellis.vpname() and trellis.grobname(), that assist with the generation of labels for specific components of a plot. For example, the following code shows the programmatic way to generate the grob name for the ticks on the left side of the plot in Figure 17, “A complex grid image”.

+
ticks <- trellis.grobname("ticks.left", "panel", column=1, row=1)
ticks
[1] "plot_01.ticks.left.panel.1.1"

The gridSVG package provides functions for use in R and javascript that support look-up of the SVG id value that are generated from the original grid names. For example, the following code generates the SVG id for the ticks on the left side of the plot in Figure 17, “A complex grid image”.

+
mappings <- readMappingsJS("lattice-plot.svg.mappings.js")
gridSVGMappings(mappings)
getSVGMappings(ticks, "grob")
[1] "plot_01.ticks.left.panel.1.1.1"

An example

This section briefly describes an example that demonstrates the usefulness of being able to work with structured and labelled SVG.

The code below draws a simple grid image consisting of a spiral, drawn as multiple line segments with ever-decreasing line widths (see Figure 20, “A zoomable grid spiral”). This image is designed so that more detail is revealed if the image is enlarged. Enlarging the image is made possible by including the javascript code from the file SVGPan-spiral.js, which is a small modification of the SVGPan javascript library. With this javascript included in the SVG file, the mouse wheel can be used to zoom into and out of the image.

Figure 20. A spiral drawn using grid. The mouse wheel can be used to zoom into the image.


The important point about this example is that an SVG image that was created by one author using R has been combined with a javascript library that was created by another independent author. This was possible because the SVG image from R contains a viewport called "viewport", which is translated to an SVG <g> element with an id="viewport.1" and the javascript library determines what part of the image to zoom based on a specific id. In other words, by having control of the labelling of the SVG that is generated by R, we were able to link to the javascript library very easily.

This basic idea lies behind a real world application that provides zoomable choropleth maps of New Zealand (see Languages in Aotearoa New Zealand published by the Royal Society of New Zealand).

Summary

SVG is a markup language that enables images to be described using structure and labelling so that every individual component of the image is uniquely identifiable.

If images are generated with structure and labelling they become useful resources from which further images may be produced, for example by independently specifying the styling of the image with CSS, by adding interactivity to the image with javascript, or by processing the image to extract, modify, and recombine the image with XSLT.

Software systems that generate complex SVG images from a high-level description often do not provide structure or labelling in the SVG code that they produce, but it is possible to generate complex SVG images with structure and labelling from R using the grid, lattice, and gridSVG packages. The important features of the solution that these R packages provide are:

  1. A low-level system that enables an image to be described with structure and labelling.

  2. A high-level system that produces complex images in a structured way and employs a naming scheme that automatically generates labels for every component of an image.

  3. Documentation of the structure and naming scheme.

  4. Tools for interactively exploring the structure and labelling in an image.

  5. An API for generating labels and locations for individual components of an image.

Discussion

We have shown that it is desirable to have structure and labelling in an SVG image and that it is possible to generate such an image from a high-level system that produces complex statistical plots. This section discusses the implications for other software.

The first point is that this is something that other software could do better. For example, javascript libraries, such as gRaphael and Highcharts, could provide more structure and labelling for the images that they generate.

The second point is that the benefits of structure and labelling are not exclusive to SVG. It would also be useful if software that generates HTML for web pages, such as DocBook converters and software that transforms simpler document markup to HTML (e.g., asciidoc and markdown), generated structure and labelling so that the resulting web page could be worked with and further developed by other authors.

An important subtlety is that the structure and labelling generated by a high-level system should not just be designed for the high-level system's own use; the ultimate goal is to produce a document that does not limit what other people can do with the document.

A. Software used in this report

Most of the code in this report is R code that uses packages that are available from CRAN (see version information below). The exception is version 1.1-0 of the gridSVG package, which was only available from github at the time of writing. This should appear on CRAN in the near future.

+
sessionInfo()
R Under development (unstable) (2013-03-31 r62459)
Platform: x86_64-unknown-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_NZ.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_NZ.UTF-8        LC_COLLATE=en_NZ.UTF-8    
 [5] LC_MONETARY=en_NZ.UTF-8    LC_MESSAGES=en_NZ.UTF-8   
 [7] LC_PAPER=C                 LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_NZ.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
[1] lattice_0.20-14 gridSVG_1.1-0   RJSONIO_1.0-1   XML_3.95-0.2   
[5] ggplot2_0.9.3   XDynDocs_0.3-1  Sxslt_0.91-1   

loaded via a namespace (and not attached):
 [1] codetools_0.2-8    colorspace_1.2-1   dichromat_2.0-0    digest_0.6.3      
 [5] gtable_0.1.1-1     labeling_0.1       MASS_7.3-26        munsell_0.4       
 [9] plyr_1.8           proto_0.3-10       RColorBrewer_1.0-5 reshape2_1.2.2    
[13] scales_0.2.3       stringr_0.6.2     

The software packages used in Appendix B, Other Software for Generating SVG were: Gnumeric Spreadsheet 1.10.17, plot2svg dated 10 Apr 2005 (Updated 17 Sep 2012), Highcharts 2.0, gRaphael 0.5.1.

B. Other Software for Generating SVG

This appendix briefly considers the SVG generated by several high-level systems for drawing statistical plots and comments on the presence or absence of structure and labelling in the SVG code.

plot2svg

The plot2svg package for Matlab allows a Matlab plot to be exported in an SVG format (also adding access to advanced SVG features such as filters). Basic usage involves a single command, as shown in Figure B.1, “Matlab code for a complex image” (see Figure B.2, “An image generated by plot2svg” for the output).

Figure B.1. Matlab code to generate a statistical plot

>> scatter(x,y)
>> plot2svg

Figure B.2. A statistical plot generated by plot2svg


Figure B.3, “SVG code generated by plot2svg” shows a fragment of the SVG code generated by plot2svg. The SVG code does include id attributes on some elements, but they are very uninformative, serving only an internal use for plot2svg. The structure or nesting of elements does provide a grouping of the data symbols (<circle> elements) together within a <g> element, but again the labelling renders this structure uninformative. Overall, there is little assistance within the SVG code for working with the image any further.

Figure B.3. SVG code generated by plot2svg


<g id="ID000000"> <clipPath id="ID000001"> <rect x="68.250" y="29.531" width="406.875" height="320.906"/> </clipPath> </g> <g id="ID000002" clip-path="url(#ID000001)"> <g id="ID000003" clip-path="url(#ID000001)"> <g> <circle cx="451.721" cy="265.415" r="3.000" fill="none" stroke="#0000ff" stroke-width="0.5pt"/> </g> <g> <circle cx="449.794" cy="262.857" r="3.000" fill="none" stroke="#0000ff" stroke-width="0.5pt"/> </g> </g> </g>

Gnumeric

The Gnumeric spreadsheet software can produce statistical charts and it is possible to export these charts in an SVG format (see Figure B.4, “An image generated by Gnumeric”).

Figure B.4. A statistical plot generated by Gnumeric


Figure B.5, “SVG code generated by Gnumeric” shows a fragment of the SVG code generated by Gnumeric. This shows relatively efficient SVG code because various shapes have been defined at the start of the document and then the <use> elements just repeatedly reuse those shapes. However, there is neither nesting of elements to provide structure nor labelling of elements to assist with selection of specific components of the plot.

Figure B.5. SVG code generated by Gnumeric


<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> <use xlink:href="#glyph0-2" x="11.679688" y="114.441406"/> <use xlink:href="#glyph0-0" x="16.769531" y="114.441406"/> </g> <use xlink:href="#surface16639" transform="matrix(1,0,0,1,28.13876,107.337157)"/> <use xlink:href="#surface16639" transform="matrix(1,0,0,1,27.270721,91.839662)"/> <use xlink:href="#surface16639" transform="matrix(1,0,0,1,36.471936,81.367268)"/>

gRaphael

The gRaphael javascript library allows statistical charts to be produced with relatively little javascript code. Figure B.6, “gRaphael javascript code” shows the javascript code required to produce the plot in Figure B.7, “An image generated by gRaphael”.

Figure B.6. gRaphael javascript code for producing a statistical plot

<script><![CDATA[ var paper = Raphael(10, 10, 640, 480); paper.dotchart(0, 0, 620, 460, [76, 70, 67, 71, 69], [0, 1, 2, 3, 4], [100, 120, 140, 160, 500], { max: 10, axisylabels: ['Mexico', 'Argentina', 'Cuba', 'Canada', 'United States of America'], heat: true, axis: '0 0 1 1'}); ]]></script>

Figure B.7. A statistical plot generated by gRaphael


Figure B.8, “SVG code generated by gRaphael” shows a fragment of the SVG code that gRaphael generates. Again, there is neither structure nor labelling to identify significant components within the plot.

Figure B.8. SVG code generated by gRaphael

<text style="text-anchor: middle; font: 11px 'Fontin Sans',Fontin-Sans,sans-serif;" x="157" y="325" text-anchor="middle" font="11px 'Fontin Sans', Fontin-Sans, sans-serif" stroke="none" fill="#000000"/> <text style="text-anchor: middle; font: 11px 'Fontin Sans',Fontin-Sans,sans-serif;" x="197.8" y="325" text-anchor="middle" font="11px 'Fontin Sans', Fontin-Sans, sans-serif" stroke="none" fill="#000000"/> <text style="text-anchor: middle; font: 11px 'Fontin Sans',Fontin-Sans,sans-serif;" x="238.60000000000002" y="325" text-anchor="middle" font="11px 'Fontin Sans', Fontin-Sans, sans-serif" stroke="none" fill="#000000"/> <path style="" fill="none" stroke="#000000" d="M157,313.5L463,313.5M157.5,313L157.5,318M177.9,313L177.9,318M198.3,313L198.3,318M218.70000000000002,313L218.70000000000002,318M239.10000000000002,313L239.10000000000002,318M259.5,313L259.5,318M279.9,313L279.9,318M300.29999999999995,313L300.29999999999995,318M320.69999999999993,313L320.69999999999993,318M341.0999999999999,313L341.0999999999999,318M361.4999999999999,313L361.4999999999999,318M381.89999999999986,313L381.89999999999986,318M402.29999999999984,313L402.29999999999984,318M422.6999999999998,313L422.6999999999998,318M443.0999999999998,313L443.0999999999998,318M463.4999999999998,313L463.4999999999998,318"/> <circle cx="463" cy="303" r="4.47213595499958" fill="#90bf2f" stroke="none" style="fill-opacity: 1;" fill-opacity="1"/> <circle cx="259" cy="266.5" r="4.898979485566357" fill="#9fbf2f" stroke="none" style="fill-opacity: 1;" fill-opacity="1"/> <circle cx="157" cy="230" r="5.291502622129181" fill="#acbf2f" stroke="none" style="fill-opacity: 1;" fill-opacity="1"/>

Highcharts

Highcharts is another javascript library for producing statistical plots (free for personal use). Figure B.9, “Highcharts javascript code” shows the javascript required to produce the plot in Figure B.10, “An image generated by highcharts”.

Figure B.9. Highcharts javascript code for producing a statistical plot

<script><![CDATA[ $(document).ready(function() { var chart1 = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'bar' }, title: { text: 'Fruit Consumption' }, xAxis: { categories: ['Apples', 'Bananas', 'Oranges'] }, yAxis: { title: { text: 'Fruit eaten' } }, series: [{ name: 'Jane', data: [1, 0, 4] }, { name: 'John', data: [5, 7, 3] }] }); }); ]]></script>

Figure B.10. A statistical plot generated by highcharts


Figure B.11, “SVG code generated by highcharts” shows a fragment of the SVG code generated by Highcharts, which shows that there is some structure and labelling within the SVG code that Highcharts generates. There is a clear correspondence between the conceptual components used in the original javascript code, with axis labelling information collected together within <g> elements that have a useful class attribute. This does allow for some further processing of an SVG image that is generated by Highcharts. For example, it is possible to style the plot using CSS to affect all axis labelling. However, the labelling is insufficient to be able to reliably distinguish the axis labelling for the x-axis from the labelling for the y-axis. Similar structure and labelling makes it possible to style all of the rectangles in the plot, but there is insufficient labelling to reliably address specific rectangles or to reliably distinguish one series of rectangles from another. Although Highcharts produces by far the most structure and labelling in its SVG code, out of the high-level systems considered in this section, there is still plenty of room for Highcharts to provide more assistance for further processing of Highcharts plots.

Figure B.11. SVG code generated by highcharts


<g class="highcharts-axis-labels"> <text text-anchor="end" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;width:457px;color:#666;line-height:14px;fill:#666;" y="92.43333333333334" x="53"> <tspan x="53">Apples</tspan> </text> <text text-anchor="end" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;width:457px;color:#666;line-height:14px;fill:#666;" y="185.10000000000002" x="53"> <tspan x="53">Bananas</tspan> </text> <text text-anchor="end" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;width:457px;color:#666;line-height:14px;fill:#666;" y="277.7666666666667" x="53"> <tspan x="53">Oranges</tspan> </text> </g> <g class="highcharts-axis-labels"> <text text-anchor="middle" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;color:#666;line-height:14px;fill:#666;" y="332" x="61"> <tspan x="61">0</tspan> </text> <text text-anchor="middle" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;color:#666;line-height:14px;fill:#666;" y="332" x="124.6"> <tspan x="124.6">0.5</tspan> </text> <text text-anchor="middle" style="font-family:'lucida grande', 'lucida sans unicode', verdana, arial, helvetica, sans-serif;font-size:11px;color:#666;line-height:14px;fill:#666;" y="332" x="188.2"> <tspan x="188.2">1</tspan> </text> </g>

Bibliography

[R] R Development Core Team. “ R : A Language and Environment for Statistical Computing ”. 2011. ISBN 3-900051-07-0.

[griddebug] Paul Murrell and Velvet Ly.. “ gridDebug : Debugging Grid Graphics ”. 2012. R package version 0.5-0.

[gridsvg] Paul Murrell and Simon Potter. “ gridSVG : Export grid graphics as SVG ”. 2012. R package version 1.1-0.

[ggplot2] Hadley Wickham. “ ggplot2 : elegant graphics for data analysis ”. 2009.

[XML] Duncan Temple Lang. “ XML : Tools for parsing and generating XML within R and S-Plus. ”. 2012. R package version 3.9-4.

[lattice] Deepayan Sarkar. “ Lattice : Multivariate Data Visualization with R ”. 2008. ISBN 978-0-387-75968-5.

[XPath] James Clark and Steve DeRose. “ XML Path Language (XPath) 1.0 ”. 1999. http://www.w3.org/TR/1999/REC-xpath-19991116.

[XLST] James Clark. “ XSL Transformations (XSLT) 1.0 ”. 1999. http://www.w3.org/TR/1999/REC-xslt-19991116.

[SVG] Erik Dahlstrom, Patrick Dengler, Anthony Grasso, Chris Lilley, Cameron McCormack, Doug Schepers, Jonathon Watt, Jon Ferraiolo, Jun Fujisawa, and Dean Jackson. “ Scalable Vector Graphics (SVG) 1.1 ”. 2011. http://www.w3.org/TR/2011/REC-SVG11-20110816/.

[gridSVGnaming] Simon Potter and Paul Murrell. “ Generating Unique Names in gridSVG ”. 2013.

[latticeNaming] Paul Murrell. “ A Naming Scheme for Lattice Grobs ”. 2011. http://lattice.r-forge.r-project.org/Vignettes/src/naming-scheme/namingScheme.pdf.

[svgpan] Andrea Leofreddi. “ svgpan : A JavaScript library to zoom, drag and pan SVG images ”. 2013. http://code.google.com/p/svgpan/.

[plot2svg] Juerg Schwizer. “ Scalable Vector Graphics (SVG) Export of Figures ”. 2012. http://www.mathworks.com/matlabcentral/fileexchange/7401-scalable-vector-graphics-svg-export-of-figures.

[gnumeric] GNOME Office team. “ Gnumeric : The GNOME Office Spreadsheet ”. 2013. http://projects.gnome.org/gnumeric/.

[graphael] Dmitry Baranovskiy. “ gRaphael - JavaScript Library ”. 2013. http://g.raphaeljs.com/.

[highcharts] Highsoft Solutions AS. “ Highcharts : Interactive JavasScript charts for your web projects ”. 2013. http://www.highcharts.com/.


dynDoc("labels.xml", "HTML", force = TRUE, xslParams = c(html.stylesheet = "http://stattech.wordpress.fos.auckland.ac.nz/wp-content/themes/twentyeleven/style.css customStyle.css", 
    base.dir = "HTML", generate.toc = "article toc"))
Wed Apr 10 10:22:12 2013