How to render SPARQL results using Google Visualization API

From Data-gov Wiki

Jump to: navigation, search
Infobox (How-To) edit with form
  • name: How to render SPARQL results using Google Visualization API

  • description: A tutorial for Web developers to render SPARQL query results using Google Visualization.
  • creator(s): Jin Guang Zheng,Li Ding
  • created: Oct 7, 2009
  • modified: 2010-4-8



Contents

Overview

This article's intent is to help anyone who is interested in employing Google Visualization to visualize a given SPARQL query's results.

Note:

Using Google Visualization API

What can Google Visualization do?

The Google Visualization API enables you to expose your data, stored on any data-store that is connected to the web, as a Visualization compliant datasource. Thus, you can create reports and dashboards as well as analyze and display your data through the wealth of available visualization applications. The Google Visualization API also provides a platform that can be used to create, share and reuse visualizations written by the developer community at large.

For more information on Google Visualization: http://code.google.com/apis/visualization/

Interactive Demos provided by Google: http://code.google.com/apis/ajax/playground/?type=visualization#data_source_request

In order to understand how to employ Google Visualization for our work, it would be handy to walk through their "Hello, world" trivial example on their site. In the above case, we are visualizing data for a pie chart. In the following case, using our own data set and accessing it via SPARQL queries which are then parsed into JSON, we will use a Geographical Map, or in the Google Visualization language, a 'geomap'.

Input formats for Google Visualization

There are two kinds of data format that Google visualization will accept: 1. a Google Visualization's "data table" format:

var data = new google.visualization.DataTable();
data.addColumn('string', 'Task');
data.addColumn('number', 'Hours per Day');
data.addRows([
  ['Work', 11],
  ['Eat', 2],
  ['Commute', 2],
  ['Watch TV', 2],
  ['Sleep', {v:7, f:'7.000'}]
]);

In above case, a data table is constructed and stored in variable data. For this data table, two columns are added, and 5 rows are added, each row contains two columns as specified.

2. JSON format

var dt = new google.visualization.DataTable(
     {
       cols: [{id: 'task', label: 'Task', type: 'string'},
                {id: 'hours', label: 'Hours per Day', type: 'number'}],
       rows: [{c:[{v: 'Work'}, {v: 11}]},
              {c:[{v: 'Eat'}, {v: 2}]},
              {c:[{v: 'Commute'}, {v: 2}]},
              {c:[{v: 'Watch TV'}, {v:2}]},
              {c:[{v: 'Sleep'}, {v:7, f:'7.000'}]}
             ]
     },
   0.6
)

In above case, a data table in constructed by taking JSON format as input parameter. In this JSON format, 'cols' is equal to addColumns in case 1, and rows equal to addRows in case 1.

Presenting our data using Google visualization

First, you need to load the visualization:

google.load('visualization', '1', {packages: ['geomap']});

Then you need to create a <div> for the visualization:

<div id="visualization" style="height: 400px; width: 400px;"></div>

Finally, display your visualization:

var visualization = new google.visualization.GeoMap(document.getElementById('visualization'));
visualization.draw( data);

Note: more specification on different type of visualization can be found in Google Visualization API: http://code.google.com/apis/visualization/

Pipe RDF data to Google Visualization

The above section has shown how to manually generate a data tabel using JSON or "data table" format; and now we show how to construct data table using SPARQL query on RDF data in the following steps


Identify RDF data

First of all, the RDF dataset should be identified for query. In our demo, we either select an online file or a web based sparql endpoint.

Construct SPARQL query

Constructing a query is fairly easy: write the sparql query and make sure it can be accessed through a url. Construct the query by concatenating the sparql service endpoint url and the sparql query url, and pass the query url to the visualization's query function.

Convert SPARQL query result

To leverage Google Visualization, we need to convert the XML-encoded SPARQL query results to JSON format consumable by Google Visualization. For example:

http://data-gov.tw.rpi.edu/ws/sparqlproxy.php?query-uri=http%3A%2F%2Fdata-gov.tw.rpi.edu%2Fsparql%2Fquakemap.sparql&output=gvds&service-uri=http%3A%2F%2Fdata-gov.tw.rpi.edu%2Fjoseki%2Fsparql

var query = new google.visualization.Query($url)

In this example, we are using http://data-gov.tw.rpi.edu/joseki/sparql as the service url and http://data-gov.tw.rpi.edu/sparql/quakemap.sparql as the query url. These are passed into the endpoint, which is located at http://data-gov.tw.rpi.edu/ws/sparqlproxy.php. The rest of the parameters are additional information taken by this particular sparql query endpoint. Note that the parameters should be escaped.

The last line in the above example is how you construct the query.

Get Response

Once the query is constructed, you can send the query to get the result by

query.send(handleQueryResponse);

Where "handleQueryResponse" is a function defined how would you like to handle the result.

Then in the function "handleQueryResponse", you can get the data table by call this function(Note: a 'response' parameter is needed for defining this function):

var data = response.getDataTable();

In here, response is parameter for function "handleQueryResponse".

function handleQueryResponse(response) {
...
}

Complete Code Example

Here is complete code of GeoMap Visualization using SPARQL query we discussed above: (Note: In order to use Google Map, you need to get a Google Map Key.)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
  <head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/> 
    <title> 
    Google Visualization
    </title> 
    <script type="text/javascript" src="http://www.google.com/jsapi"></script> 
    <script type="text/javascript"> 
      google.load('visualization', '1', {packages: ['geomap']});
    </script> 
    <script type="text/javascript"> 
    var visualization;
 
    function drawVisualization() {
      // To see the data that this visualization uses, browse to
      // http://spreadsheets.google.com/ccc?key=pCQbetd-CptGXxxQIG7VFIQ  
      var query = new google.visualization.Query('http://data-gov.tw.rpi.edu/ws/sparqlproxy.php?query-uri=http%3A%2F%2Fdata-gov.tw.rpi.edu%2Fsparql%2Fquakemap.sparql&output=gvds&callback=&tqx=&service-uri=http%3A%2F%2Fonto.rpi.edu%2Fjoseki%2Fsparql');
      
     
      // Send the query with a callback function.
      
      query.send(handleQueryResponse);
       
    }
    
    function handleQueryResponse(response) {
 
      if (response.isError()) {
        alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
        return;
      }
        var options=null;
      options = {};options['dataMode'] = 'markers';
  var data = response.getDataTable();
 
      visualization = new google.visualization.GeoMap(document.getElementById('visualization'));
      visualization.draw( data ,options);
    }
 
    google.setOnLoadCallback(drawVisualization);
    </script> 
  </head> 
  <body style="font-family: Arial;border: 0 none;"> 
    <div id="visualization" style="height: 400px; width: 400px;"></div>  
  </body> 
</html>


Here is an timeline visualization example wrote by Rui using JSON format as input:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
  <title>Google Visualization API Sample</title> 
  <script type="text/javascript" src="http://www.google.com/jsapi"></script> 
  <script type="text/javascript"> 
    google.load('visualization', '1', {packages: ['annotatedtimeline']});
    function drawVisualization() {
      var JSONObject = {
         cols:[{id:'date',label:'date',type:'date'},{id:'ozone',label:'Ozone_content_value:',type:'number'}],rows:[{c:[{v:new Date('2009/03/11')},{v:52}]},{c:[{v:new Date('2009/03/12')},{v:52}]},{c:[{v:new Date('2009/04/11')},{v:45}]},{c:[{v:new Date('2009/04/18')},{v:51}]},{c:[{v:new Date('2009/04/04')},{v:51}]},{c:[{v:new Date('2009/05/12')},{v:56}]},{c:[{v:new Date('2009/04/05')},{v:57}]},{c:[{v:new Date('2009/04/06')},{v:56}]},{c:[{v:new Date('2009/04/20')},{v:51}]},{c:[{v:new Date('2009/03/19')},{v:53}]},{c:[{v:new Date('2009/05/16')},{v:57}]},{c:[{v:new Date('2009/03/15')},{v:53}]},{c:[{v:new Date('2009/03/24')},{v:52}]},{c:[{v:new Date('2009/03/07')},{v:55}]},{c:[{v:new Date('2009/03/05')},{v:56}]},{c:[{v:new Date('2009/03/03')},{v:47}]},{c:[{v:new Date('2009/04/19')},{v:53}]},{c:[{v:new Date('2009/04/01')},{v:62}]},{c:[{v:new Date('2009/03/13')},{v:53}]},{c:[{v:new Date('2009/03/27')},{v:60}]},{c:[{v:new Date('2009/03/20')},{v:48}]},{c:[{v:new Date('2009/05/07')},{v:50}]},{c:[{v:new Date('2009/04/27')},{v:60}]},{c:[{v:new Date('2009/03/22')},{v:55}]},{c:[{v:new Date('2009/05/17')},{v:56}]},{c:[{v:new Date('2009/04/02')},{v:51}]},{c:[{v:new Date('2009/03/10')},{v:56}]},{c:[{v:new Date('2009/03/30')},{v:63}]},{c:[{v:new Date('2009/03/31')},{v:54}]},{c:[{v:new Date('2009/04/12')},{v:52}]},{c:[{v:new Date('2009/03/16')},{v:52}]},{c:[{v:new Date('2009/05/06')},{v:54}]},{c:[{v:new Date('2009/04/14')},{v:49}]},{c:[{v:new Date('2009/05/09')},{v:58}]},{c:[{v:new Date('2009/04/08')},{v:61}]},{c:[{v:new Date('2009/03/04')},{v:56}]},{c:[{v:new Date('2009/05/02')},{v:33}]},{c:[{v:new Date('2009/03/21')},{v:57}]},{c:[{v:new Date('2009/04/21')},{v:54}]},{c:[{v:new Date('2009/04/10')},{v:48}]},{c:[{v:new Date('2009/03/26')},{v:45}]},{c:[{v:new Date('2009/04/22')},{v:57}]},{c:[{v:new Date('2009/05/14')},{v:56}]},{c:[{v:new Date('2009/03/28')},{v:56}]},{c:[{v:new Date('2009/04/09')},{v:60}]},{c:[{v:new Date('2009/03/18')},{v:50}]},{c:[{v:new Date('2009/05/19')},{v:56}]},{c:[{v:new Date('2009/05/08')},{v:56}]},{c:[{v:new Date('2009/03/06')},{v:57}]},{c:[{v:new Date('2009/04/13')},{v:51}]},{c:[{v:new Date('2009/04/15')},{v:53}]},{c:[{v:new Date('2009/03/17')},{v:49}]},{c:[{v:new Date('2009/05/15')},{v:54}]},{c:[{v:new Date('2009/03/23')},{v:55}]},{c:[{v:new Date('2009/03/01')},{v:52}]},{c:[{v:new Date('2009/05/11')},{v:56}]},{c:[{v:new Date('2009/05/05')},{v:51}]},{c:[{v:new Date('2009/04/17')},{v:41}]},{c:[{v:new Date('2009/05/04')},{v:63}]},{c:[{v:new Date('2009/03/09')},{v:56}]},{c:[{v:new Date('2009/04/07')},{v:53}]},{c:[{v:new Date('2009/04/30')},{v:48}]},{c:[{v:new Date('2009/03/14')},{v:52}]},{c:[{v:new Date('2009/05/10')},{v:42}]},{c:[{v:new Date('2009/04/16')},{v:37}]},{c:[{v:new Date('2009/03/02')},{v:47}]},{c:[{v:new Date('2009/05/03')},{v:56}]},{c:[{v:new Date('2009/04/23')},{v:60}]},{c:[{v:new Date('2009/05/01')},{v:39}]},{c:[{v:new Date('2009/03/25')},{v:51}]}]};
    
      var data = new google.visualization.DataTable(JSONObject, 0.5);
    
      
      var annotatedtimeline = new google.visualization.AnnotatedTimeLine(
          document.getElementById('visualization'));
      annotatedtimeline.draw(data, {'displayAnnotations': true});
    }
    
    google.setOnLoadCallback(drawVisualization);
  </script> 
</head> 
<body style="font-family: Arial;border: 0 none;"> 
<span style="font-weight: bold;">Annotated Time line for Ozone content at site ROM406</span> 
 
<div id="visualization" style="width: 800px; height: 400px;"></div> 
 
 
</body> 
</html> 

Here is a multiple chart visualization example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
  <head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/> 
    <title> 
US Government Agencies' Dataset Contribution   
	</title> 
    
    <script type="text/javascript" src="http://www.google.com/jsapi"></script> 
    <script type="text/javascript"> 
		google.load('visualization', '1', {packages: ['table','barchart','columnchart','linechart','piechart']});
    </script> 
 
 
    <script type="text/javascript"> 
    var visualization;
 
    function drawVisualization() {
      var query = new google.visualization.Query(
          'http://data-gov.tw.rpi.edu/ws/sparqlproxy.php?query-uri=http%3A%2F%2Fdata-gov.tw.rpi.edu%2Fsparql%2Fselect_count_agency_from.sparql&output=gvds');
      
     
      // Send the query with a callback function.
      query.send(handleQueryResponse);
    }
    
    function handleQueryResponse(response) {
      if (response.isError()) {
        alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
        return;
      }
    
      var data = response.getDataTable();
      visualization = new google.visualization.Table(document.getElementById('visualization_Table'));
      visualization.draw(data, {height:500, 'allowHtml': true});
      visualization = new google.visualization.BarChart(document.getElementById('visualization_BarChart'));
      visualization.draw(data, {height:500});
      visualization = new google.visualization.ColumnChart(document.getElementById('visualization_ColumnChart'));
      visualization.draw(data, {height:500});
      visualization = new google.visualization.LineChart(document.getElementById('visualization_LineChart'));
      visualization.draw(data, {height:500});
      visualization = new google.visualization.PieChart(document.getElementById('visualization_PieChart'));
      visualization.draw(data, {height:500, pieMinimalAngle: 1,is3D: true});
      
	}
    google.setOnLoadCallback(drawVisualization);
    </script> 
 
<style type="text/css"> 
div.example {border: #603 dotted; padding: 0.6em; margin: 1em 2em}
 
/* First example */
div.items p:not(:target) {display: none}
div.items p:target {display: block}
p.menu {margin: 0; padding: 0.4em; background: silver; color: black}
p.menu a {color: black; border: thin outset silver; padding: 0.1em 0.3em}
div.items p {height: 6em; overflow: auto; text-align: center; margin: 0}
#item1 {color: red}
#item2 {color: green}
#item3 {color: blue}
 
/* Tabbed example */
div.tabs {
  min-height: 7em;		/* No height: can grow if :target doesn't work */
  position: relative;		/* Establish a containing block */
  line-height: 1;		/* Easier to calculate with */
  z-index: 0}			/* So that we can put other things behind */
div.tabs > div {
  display: inline}		/* We want the buttons all on one line */
div.tabs > div > a {
  color: black;			/* Looks more like a button than a link */
  background: #CCC;		/* Active tabs are light gray */
  padding: 0.2em;		/* Some breathing space */
  border: 0.1em outset #BBB;	/* Make it look like a button */
  border-bottom: 0.1em solid #CCC} /* Visually connect tab and tab body */
div.tabs > div:not(:target) > a {
  border-bottom: none;		/* Make the bottom border disappear */
  background: #999}		/* Inactive tabs are dark gray */
div.tabs > div:target > a,	/* Apply to the targeted item or... */
:target #default2 > a {		/* ... to the default item */
  border-bottom: 0.1em solid #CCC; /* Visually connect tab and tab body */
  background: #CCC}		/* Active tab is light gray */
div.tabs > div > div {
  background: #CCC;		/* Light gray */
  z-index: -2;			/* Behind, because the borders overlap */
  left: 0; top: 1.3em;		/* The top needs some calculation... */
  bottom: 0; right: 0;		/* Other sides flush with containing block */
  overflow: auto;		/* Scroll bar if needed */
  padding: 0.3em;		/* Looks better */
  border: 0.1em outset #BBB}	/* 3D look */
div.tabs > div:not(:target) > div { /* Protect CSS1 & CSS2 browsers */
  position: absolute }		/* All these DIVs overlap */
div.tabs > div:target > div, :target #default2 > div {
  position: absolute;		/* All these DIVs overlap */
  z-index: -1}			/* Raise it above the others */
</style> 
<STYLE TYPE="text/css"> 
<!--
 img { border: 0; }
 
.logoimg{
  height:64px;
  width:64px;
  float:left;
  position:relative;
  margin-right:15px;
  top:-10px;
}
.menuimg{
  height:32px;
  width:32px;
  position:relative;
  top:0px;
  border:0px;
}
.normal {
  font-family:Helvetica,Arial,sans-serif;
  font-size:24px;
  margin:0px 0px 3px 2px;
  padding: 1px;
  display:block;
}
h3 {
  font-family:Arial,Helvetica,sans-serif;
  font-size:16px;
  margin:0px 0px 3px 2px;
  padding: 1px;
  display:block;
}
h2 {
  font-family:Helvetica,Arial,sans-serif;
  font-size:18px;
  margin:0px 0px 3px 2px;
  padding: 1px;
  display:block;
}
h1 {
  font-family:Arial,Helvetica,sans-serif;
  font-size:32px;
  margin:0px 0px 3px 2px;
  padding: 1px;
  display:block;
  color:#333;
}
 
 
--> 
</STYLE> 
 
  
  </head> 
  <body style="font-family: Arial;border: 0 none;"> 
<table width="100%"> 
<tr> 
<td width="70%" valign="bottom"> 
 
<a href='http://data-gov.tw.rpi.edu' alt='Data-gov Wiki'> 
<img src='http://data-gov.tw.rpi.edu/images/logo-data-gov.png' class="logoimg"/></a> 
 
<center> 
<h2>US Government Agencies' Dataset Contribution</h2> 
</center> 
 
</td> 
<td align="right"> 
 
<a class"=info" href="http://data-gov.tw.rpi.edu/demo/static/agency_dataset.php"> 
<img src="http://data-gov.tw.rpi.edu/images/blue_home.png" alt="Go to demo page" class="menuimg"/></a> 
 
   
 
<a class"=info" href="http://data-gov.tw.rpi.edu/wiki/Demo:_Agencies%27_Dataset_Contribution_on_Data.gov"> 
<img src='http://data-gov.tw.rpi.edu/images/blue_info.png' class="menuimg" alt='go to this demo wiki page'/></a> 
 
<!--
   
<a class"=info" href="#description">
<img src='http://data-gov.tw.rpi.edu/images/blue_folder.png' class="menuimg" alt='go to demo description'/></a>
--> 
 
   
<a class"=info" href="mailto:tw-webmaster@tw.rpi.edu"> 
<img src='http://data-gov.tw.rpi.edu/images/blue_mail.png' class="menuimg" alt='Contact us'/> 
</a> 
 
</td> 
</tr> 
</table> 
  
  
  <div class=tabs style="height:550px"> 
  <div id=tab_Table>   <a href="#tab_Table">Table</a> 
<div id="visualization_Table" style="height:520px"></div> 
  </div> 
  <div id=tab_BarChart>   <a href="#tab_BarChart">BarChart</a> 
<div id="visualization_BarChart" style="height:520px"></div> 
  </div> 
  <div id=tab_ColumnChart>   <a href="#tab_ColumnChart">ColumnChart</a> 
<div id="visualization_ColumnChart" style="height:520px"></div> 
  </div> 
  <div id=tab_LineChart>   <a href="#tab_LineChart">LineChart</a> 
<div id="visualization_LineChart" style="height:520px"></div> 
  </div> 
  <div id=tab_PieChart>   <a href="#tab_PieChart">PieChart</a> 
<div id="visualization_PieChart" style="height:520px"></div> 
  </div> 
  </div> 
<hr/> 
<div>This demo was created by <a href='http://www.cs.rpi.edu/~dingl'>Li Ding</a> and Sarah Magidson. It queries the data.gov catalog to get all the agencies that have submitted data to data.gov and then sums them up. The result is a pie chart of agencies according to how many datasets they have submitted to data.gov. This demo is based on the following datasets from <a href='http://data.gov/'>data.gov</a>: <ul><li><a href='http://data-gov.tw.rpi.edu/wiki/Dataset_92'>Dataset 92</a> - Data.gov Catalog</li></ul></div>   
  </body> 
</html> 


A note on query formatting

Of the above three examples, the graphs generated in the first and third rely on what is essentially an external link to the data source, whereas the second example's data source is written within the Javascript. It is important to take note of one important distinction: In the first, we are explicitly passing in the service-uri parameter (in this case, it is the escaped url http://onto.rpi.edu/joseki/sparql). In the third example, we are omitting this parameter. In SPARQL, this omission implies using the local service instead of a specified external source. For more on that, read RDF Dataset Specification for SPARQL queries

More Examples

More examples/code can be found at the interactive demo: http://code.google.com/apis/ajax/playground/?type=visualization#data_source_request

Or at the Google visualization api: http://code.google.com/apis/visualization/documentation/examples.html

TW SPARQL Code Camp: http://tw.rpi.edu/wiki/tw:TW_SPARQL_code_camp

More charts example: http://data-gov.tw.rpi.edu/demo/static/agency_dataset.php

Tools and Resources Needed

1. RDF document: in order to present your data through Google Visulization, a source of RDF document is needed.

2. SPARQL query endpoint: a Sparql query endpoint is needed to process your queries and get the results.

3. Google Visualization: of course, to visualize your query result on Google visualization we need Google visualization. The link below has documentation on how to visualize your data using different packages provide by Google:

More Demos

total :(33)


Acknowledgment

Thanks go out to Jeni Tennison for her blog post on how to accomplish this conversion.

Facts about How to render SPARQL results using Google Visualization APIRDF feed
Dcterms:created7 October 2009  +
Dcterms:creatorJin Guang Zheng  +, and Li Ding  +
Dcterms:descriptionA tutorial for Web developers to render SPARQL query results using Google Visualization.
Dcterms:modified2010-4-8
Foaf:nameHow to render SPARQL results using Google Visualization API
Skos:altLabelHow to render SPARQL results using Google Visualization API  +, how to render sparql results using google visualization api  +, and HOW TO RENDER SPARQL RESULTS USING GOOGLE VISUALIZATION API  +
Personal tools
internal pages