Abstract

The Allotrope Data Format (ADF) [ADF] consists of several APIs and taxonomies. This document constitutes the Developer's Guide for the ADF Data Description API (ADF-DD) [ADF-DD]. It provides examples on how to use the ADF-DD API to store meta data of the Data Package and the Data Cubes along with experimental or process data and contextual meta data. ADF-DD is based on semantic web standards and linked data concepts using the RDF Data Model.

Disclaimer

THESE MATERIALS ARE PROVIDED "AS IS" AND ALLOTROPE EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE WARRANTIES OF NON-INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current Allotrope publications and the latest revision of this technical report can be found in the Allotrope technical reports index at http://purl.allotrope.org/TR/.

This document is part of a set of specifications on the Allotrope Data Format [ADF]

This document was published by the Allotrope Foundation as a First Public Working Draft. This document is intended to become an Allotrope Recommendation. If you wish to make comments regarding this document, please send them to more.info@allotrope.org. All comments are welcome.

Publication as a First Public Working Draft does not imply endorsement by the Allotrope Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

Table of Contents


1. Introduction

The Allotrope Data Format (ADF) defines an interface for storing scientific observations from analytical chemistry. It is intended for long-term stability of archived analytical data and fast real-time access to it. The ADF Data Description API defines an interface for storing business and technical meta data. This Developer's Guide provides examples on how to use the ADF Data Description API to store meta data of Data Package and Data Cubes along with experimental or process data and contextual meta data.

The document is structured as follows: First, the core operations on the RDF graph that are offered by the ADF-DD API for querying and modifying data are explained along examples. Namely the query, insert, delete and update operations are explained. Then reference to a complete example application of the API is given.

1.1 Document Conventions

1.1.1 Namespaces

Within this specification, the following namespace prefix bindings are used:

Prefix Namespace
owl:http://www.w3.org/2002/07/owl#
rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs:http://www.w3.org/2000/01/rdf-schema#
xsd:http://www.w3.org/2001/XMLSchema#
skos:http://www.w3.org/2004/02/skos/core#
dct:http://purl.org/dc/terms/
foaf:http://xmlns.com/foaf/0.1/
adf-dp:http://purl.allotrope.org/ontologies/datapackage#
adf-dc:http://purl.allotrope.org/ontologies/datacube#
af-r:http://purl.allotrope.org/ontologies/result#
af-x:http://purl.allotrope.org/ontologies/property#

1.1.2 Number Formatting

Within this document, decimal numbers will use a dot "." as the decimal mark.

2. RDF Graph Operations

The Data Description API provides functions for the core operations on the RDF graph - i.e. the data stored in the ADF Triple Store.

The API of Apache Jena [APACHE-JENA] constitutes the ADF Data Description API. In the following sections, the API is introduced and illustrated by examples. For a complete description of the API, please consult the JavaDoc API documentation and the sources listed in the References section.

2.1 The RDF Graph

In Apache Jena, an RDF graph [rdf11-concepts] is called a model and is represented by the Model interface [APACHE-JENA], [JENA-INTRO]. The following sections illustrate how the Jena Model can be used for operations on the RDF graph. For more details on the Jena API, please refer to [APACHE-JENA] and [JENA-INTRO].

2.2 Querying an RDF Graph

The RDF graph can be queried by iterating over the Jena Model or by running SPARQL queries on the Model. The following sections illustrate both approaches.

2.2.1 Iterating over the RDF Graph

The Model interface of Apache Jena contains a listStatements() method that returns an interator (a StmtIterator, which is a subtype of Java's Iterator) that allows to iterate over all statements in the model. The Statement interface provides accessor methods to the subject, predicate and object of a statement.

The following example illustrates iterating over the model:

Example 1
Java:
// Iterate over all RDF Statements in the DataDescription
for (Statement stmt : dataDescription.listStatements()) {

	// get the subject
	Resource subject = stmt.getSubject();

	// get the predicate
	Property predicate = stmt.getPredicate();

	// get the object
	RDFNode object = stmt.getObject();
}

C#:
// Iterate over all RDF Statements in the DataDescription
StmtIterator iter = dataDescription.listStatements();
while (iter.MoveNext())
{
	Statement stmt = iter.Current;

	// get the subject
	Resource subject = stmt.getSubject();

	// get the predicate
	Property predicate = stmt.getPredicate();

	// get the object
	RDFNode @object = stmt.getObject();
}
				

2.2.2 Querying the RDF Graph via SPARQL

This section describes how to query an RDF graph via a SPARQL query.

2.2.2.1 Example Query

The following picture shows a total ion chromatogram and the spectra that belong to it. Assume that we want to query the data highlighted in the following figure:

Fig. 1 Query example

2.2.2.2 Representation of the Query in SPARQL

To keep it simple, the example uses human readable identifiers surrounded by guillemets (« ») instead of artificial identifiers.

Example 2
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX qudt: <http://qudt.org/schema/qudt#>
PREFIX af-r: <http://purl.allotrope.org/ontologies/result#>
PREFIX af-x: <http://purl.allotrope.org/ontologies/propert#>
SELECT ?scan ?scanTimeValue ?scanTimeUnit ?totalIonCurrent ?basePeakPosValue ?basePeakPosUnit ?basePeakHeightValue ?basePeakHeightUnit 
WHERE { 
	?spectrum a «af-r:MS1 spectrum» ;
	«af-x:total ion current» ?totalIonCurrent ;
	«af-x:base peak» ?basePeak .
	?basePeak a «af-r:peak» ; 
	«af-x:total retention time» [ 
		qudt:numericValue ?basePeakPosValue ; 
		qudt:unit ?basePeakPosUnit ; 
	] ; 
	«af-x:intensity» [ 
		qudt:numericValue ?basePeakHeightValue ; 
		qudt:unit ?basePeakHeightUnit ; 
	] ;
	?scan a «af-x:scan» ; 
	«af-x:scanned spectrum» ?spectrum ; 
	«af-x:start time» [
		qudt:numericValue ?scanTimeValue ; 
		qudt:unit ?scanTimeUnit ; 
	] .
}					

A short query with artificial identifiers could look like this:

Example 3
PREFIX qudt: <http://qudt.org/schema/qudt#>
PREFIX af-r: <http://purl.allotrope.org/ontologies/result#>
PREFIX af-x: <http://purl.allotrope.org/ontologies/propert#>
SELECT ?spectrum ?basePeakHeightValue ?basePeakHeightUnit 
WHERE { 
	?spectrum a af-r:AFR_0000472 ;
	af-x:AFX_0000361 [ 
		qudt:numericValue ?basePeakHeightValue ; 
		qudt:unit ?basePeakHeightUnit ; 
	] .
}					

2.2.2.3 Execution of the SPARQL Query

Given a SPARQL query as queryString and a Jena Model, we can execute the query on the model as follows, using the Jena ARQ API [JENA-ARQ]:

Example 4
JAVA:
Query query = QueryFactory.create(queryString);
try (QueryExecution qexec = QueryExecutionFactory.create(query, dataDescription)) {
	ResultSet resultSet = qexec.execSelect();
	while (resultSet.hasNext()) {
		QuerySolution solution = resultSet.nextSolution();
		// extract the queried information via solution.get("variable name")
		// and do something with the result
	}
}

C#:
Query query = QueryFactory.create(queryString);
QueryExecution qexec = QueryExecutionFactory.create(query, dataDescription);
try
{
	ResultSet results = qexec.execSelect();
	while (results.MoveNext())
	{
		QuerySolution solution = resultSet.Current;
		// extract the queried information via solution.getResource("variable name");
		// and do something with the result
	}
}
finally
{
	qexec.close();
}
					

In this example, we first create a Query out of the given query string. Then we execute it and finally iterate over the results.

Resuming the example from above, the execution of the query looks like this:

Example 5
JAVA:
// Iterate over the ResultSet
while (resultSet.hasNext()) {
	QuerySolution soln = resultSet.nextSolution();

	// Get the Scan Time, the Total Ion Current and the Base Peak of the spectrum
	String scanTime = soln.get("scanTimeValue") + " " + soln.get("scanTimeUnit");
	String tic = soln.get("tic");
	String basePeakMZ = soln.get("basePeakPosValue") + " " + soln.get("basePeakPosUnit");
	String basePeakint = soln.get("basePeakHeightValue") + " " + soln.get("basePeakHeightUnit");
}

C#:
// Iterate over the ResultSet
while (results.MoveNext())
{
	com.hp.hpl.jena.query.QuerySolution soln = results.Current;

	// Get the Scan Time, the Total Ion Current and the Base Peak of the spectrum
	String = soln.get("scanTimeValue") + " " + soln.get("scanTimeUnit");
	String tic = soln.get("tic");
	String basePeakMZ = soln.get("basePeakPosValue") + " " + soln.get("basePeakPosUnit");
	String basePeakint = soln.get("basePeakHeightValue") + " " + soln.get("basePeakHeightUnit");
}
					

Please refer to [JENA-ARQ] for more details and additional examples on SPARQL queries with the Jena ARQ API.

2.3 Modifying Statements in an RDF Graph

2.3.1 Inserting Statements into an RDF Graph

The Jena Model that represents the RDF graph consists of a set of statements. A statement is a triple that consists of subject, predicate and object. Statements can be constructed and inserted into the Jena Model via createResource() and addProperty() in fluent API style:

Example 6
JAVA and C#:
Resource myBalance = dataDescription.createResource(<myBalanceURI>) //
	.addLiteral(DCTerms.title, "My analytical balance that ...");
				

In this example, we added the triple

Example 7
<myBalanceURI> dc:title 'My analytical balance that ...'

to the model, using the Dublin Core 'title' predicate. The namespace declaration for Dublin Core (dc) can be found in the Namespaces section.

2.3.2 Updating a Statement in the RDF Graph

Given a data cube and its representation in an RDF graph, assume we have a typo in the label of the dimension representing the intensity. The following SPARQL 1.1 Update [sparql11-update], [SEARBORNE-SPARQL] query illustrates how this typo can be fixed:

Example 8
PREFIX adf-dc: <http://purl.allotrope.org/adf/dc/1.0#>
PREFIX qb: <http://purl.org/linked-data/cube#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

DELETE { ?dimension rdfs:label 'intensty' }
INSERT { ?dimension rdfs:label 'intensity' }
WHERE
  {
	?dimension rdfs:label 'intensty'.
	?dimension rdfs:type qb:DimensionProperty .
  }
				

Given the Jena Model of the RDF graph, we can execute this query using the Jena ARQ API [JENA-ARQ] to fix the typo:

Example 9
JAVA and C#:
UpdateAction.parseExecute(queryString, dataDescription);
				

2.3.3 Removing a Statement from the RDF Graph

With SPARQL 1.1 Update, it is possible to remove statements from an RDF graph by using the DELETE operation (cp. the example of the previous section). The following query removes all archive information packages (AIP), whose retention period of 50 years has expired on 2014-12-05.

Example 10
PREFIX core: <http://purl.allotrope.org/core/metadata#>

DELETE { ?aip  ?p ?v }
WHERE
  {
	?aip core:retentionTime ?date .
	FILTER ( ?date < "1964-12-05T00:00:00-02:00"^^xsd:dateTime )
	?aip ?p ?v?
  }
				

Given the Jena Model of the RDF graph, we can execute this query using the Jena ARQ API [JENA-ARQ]:

Example 11
JAVA and C#:
UpdateAction.parseExecute(queryString, dataDescription);
				

3. Complete Example

The ADF-DD First Steps Example Application illustrates the Java API of ADF-DD by one complete code example. It is contained in the file FirstSteps.java in the package org.allotrope.adf.dd.firststeps.

4. Change History

Version Release Date Remarks
0.4.0 2015-06-29 Initial Working Draft version
1.0.0 RC 2015-09-17
  • Renamed document from User Manual to Developer's Guide
  • Renamed section Example Code to Complete Example
  • Removed unnecessary sub section from section Complete Example
  • Added provenance information to the Complete Example
1.0.0 2015-09-29
  • Updated versions, dates and document status
  • Updated introduction
  • Removed code from section Complete Example
1.1.0 RC 2016-03-11
  • updated versions, dates and document status
  • added section on number formatting to document conventions
  • added information and examples for C#/.NET
1.1.0 RF 2016-03-31
  • updated versions, dates and document status
1.1.5 2016-05-13
  • updated versions and dates
1.2.0 Preview 2016-09-23
  • updated versions and dates
1.2.0 RC 2016-12-07
  • updated versions and dates
1.3.0 Preview 2017-03-31
  • updated versions and dates
  • updated section 2.3.3 (Example 9)
1.3.0 RF 2017-06-30
  • updated versions and dates

A. References

A.1 Normative references

[ADF]
Allotrope. Allotrope Data Format Overview. URL: http://purl.allotrope.org/TR/adf/
[ADF-DD]
Allotrope. ADF Data Description API. URL: http://purl.allotrope.org/TR/adf-dd/
[rdf11-concepts]
Richard Cyganiak; David Wood; Markus Lanthaler. W3C. RDF 1.1 Concepts and Abstract Syntax. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/rdf11-concepts/
[sparql11-update]
Paula Gearon; Alexandre Passant; Axel Polleres. W3C. SPARQL 1.1 Update. 21 March 2013. W3C Recommendation. URL: https://www.w3.org/TR/sparql11-update/

A.2 Informative references

[APACHE-JENA]
The Apache Software Foundation. Apache Jena - A free and open source Java framework for building Semantic Web and Linked Data applications.. URL: https://jena.apache.org/
[JENA-ARQ]
The Apache Software Foundation. Apache Jena - ARQ - Application API. URL: https://jena.apache.org/documentation/query/app_api.html
[JENA-INTRO]
The Apache Software Foundation. Apache Jena - An Introduction to RDF and the Jena RDF API. URL: https://jena.apache.org/tutorials/rdf_api.html
[SEARBORNE-SPARQL]
Andy Searborne. Andy Searborne - SPARQL 1.1. URL: http://de.slideshare.net/andyseaborne/sparql-11-update