Skip to content

Latest commit

 

History

History
532 lines (417 loc) · 36.2 KB

semantic-annotation.md

File metadata and controls

532 lines (417 loc) · 36.2 KB

Semantic Annotation proposal

Author: Ben Leinfelder

Date: May, 2014: Initial draft of semantic annotation model and indexing March 2017: Updated to reflect current state of prototype system

Goal: Describe the current state of semantic annotation model using OBOE and OA (Open Annotation) concepts

Summary:

Years of semantic work on the semtools project has informed the current annotation model we are prosing for use in Metacat. The model will initially focus on annotating attribute information for characteristics (e.g., Temperature) and Standard (e.g., Celsius). The model will be indexed to support fast and simple queries using the existing SOLR index methods used for standard metadata descriptions. The annotation model uses the AnnotatorJS serialization to store the MeasurementType-to-attribute relationship.

Overview

The primary goal of this initial semantic annotation model is to support querying on MeasurementType (Entity and Characteristic) information. This requires the ontology define appropriate MeasurementType concepts to be applied to data table attributes.

AnnotatorJS model (JSON)

In an effort to reduce the amount of de novo development activities we undertake, we've adopted the AnnotatorJS library for adding and editing annotations on metadata records. The annotations are stored as JSON objects that loosely correspond to fields in the more formal OA model (described later). The maintainers of the AnnotatorJS library intend to use the OA model for v2.x of the library, but it currently does not "speak" OA natively. Below is an example annotation about a web-accessible resource using their JSON model followed by a mapping of those fields to the OA model described later.

Online documentation for AnnotatorJS model is available here. This example shows how one might tag the "T_AIR" column in the metadata to be an Air Temperature concept taken from the ECSO ontology.

{
  "user": "uid=kepler,o=unaffiliated,dc=ecoinformatics,dc=org", 
  "consumer": "f780f3e398cf45cbb4e84ed9ec91622a", 
  "id": "48hAIW6TQJyg4uW5Utq7iA", 
  "resource": "#xpointer(/eml/dataset/dataTable[1]/attributeList/attribute[3])", 
  "text": "", 
  "created": "2014-11-18T05:12:08.331690+00:00", 
  "pid": "tao.1.6", 
  "ranges": [
    {
      "start": "/section[1]/article[1]/div[1]/div[1]/form[1]/div[6]/div[1]/div[1]/div[6]/div[1]/div[2]/div[3]/div[1]/div[1]", 
      "end": "/section[1]/article[1]/div[1]/div[1]/form[1]/div[6]/div[1]/div[1]/div[6]/div[1]/div[2]/div[3]/div[1]/div[1]", 
      "startOffset": 0, 
      "endOffset": 5
    }
  ], 
  "uri": "http://localhost:8080/metacat/d1/mn/v1/object/tao.1.6", 
  "links": [
    {
      "type": "text/html", 
      "rel": "alternate", 
      "href": "http://annotateit.org/annotations/48hAIW6TQJyg4uW5Utq7iA"
    }
  ], 
  "permissions": {
    "read": [
      "group:__world__"
    ], 
    "delete": [], 
    "admin": [], 
    "update": []
  }, 
  "updated": "2014-11-26T20:46:44.576047+00:00", 
  "quote": "T_AIR", 
  "tags": [
    "http://purl.dataone.org/odo/ECSO_00001225"
  ]
}

Mapping from AnnotatorJS to OA model

JS field OA property Comments
id dcterms:identifier identifier of the annotation itself
user oa:annotatedBy the user who created the annotation
created oa:annotatedAt timestamp for annotation creation
updated oa: annotatedAt Allow mutable annotations?
uri oa:hasSource D1 resolve endpoint
pid dcterms:identifier identifier of the object being annotated
resource oa:hasSelector oa:FragmentSelectors allow selction in different kinds of resources
ranges oa:hasSelector range selector uses xpaths and character offsets to pinpoint the exact part that the annotation applies to
quote oa:hasSelector the text value of the range being annotated
text oa:hasBody the text content of the annotation (e.g. comment)
tags oa:hasBody the URI of one or more tags (this would be our semantic annotation from a controlled vocabulary/ontology)

Indexing

The DataONE/Metacat Index component has been enhanced to parse semantic annotations provided as either AnnotatorJS JSON or RDF/XML.

The AnnotatorSubprocessor uses a SPARQL-based approach to expand tag[s] in an annotation based on loaded ontologies in the index processor. Instead of relying on an entire graph, the AnnotatorSubprocessor is only informed by the tagged concept[s] and any expansion/node traversal that can be performed using the loaded ontologies.

The general purpose RdfXmlSubprocessor can be used with SparqlFields to extract key concepts from the given model.

The RDF processor assumes that the identifier of the RDF document is the name of the graph being inserted into the triple store and provides that graph name to the query engine for substitution in any query syntax ($GRAPH_NAME).

The SPARQL requirements are that the solution[s] return the identifier (pid) of the object being annotated, and the index field being populated with the given value[s]. If multiple fields are to be extracted from the model for indexing, a distinct SPARQL query should be used for each field.

For RDF models, the query can (and is largely expected to) be constrained to the named graph that contains only that set of annotation triples. While the infrastructure can (and likely will) share the same triple store, we should not assume other models have been loaded when processing any given graph. This means that any solutions will rely on only the named graph being processed during indexing.

A sample SPARQL query used to determine the MeaurementType[s] in a dataset is shown below. Note that the query includes superclasses in the returned solutions so that the index returns a match for both general and specific criteria.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
			PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
			PREFIX owl: <http://www.w3.org/2002/07/owl#> 
			
			SELECT ?sem_annotation
			WHERE { 
					<$CONCEPT_URI> rdfs:subClassOf+ ?sem_annotation .
			 	}

Index Fields

Multi-valued string fields allow us to index the new semantic content. They are multi-valued because they will store the entire class subsumption hierarchy (up) for any matching concepts and because they will store annotations from the same metadata resources for different attributes.

  • sem_anotation - indexes the oboe:MeaurementType[s] for annotations on the datapackage (added directly via manual annotation)
  • sem_anotation_bioportal_sm - holds indexed annotations added by bioportal recommendations
  • sem_anotation_esor_sm - holds indexed annotations added by ESOR recommendations
  • sem_anotation_cosine_sm - holds indexed annotations added by ESOR-Cosine recommendations

Example

Continuing with example model, these concepts would be indexed for the data attributes described in the datapackage metadata. So 'Air Temperature' and it's parent, 'Temperature Measurement Type', and it's grandparent, 'Measurement Type' would all be indexed in sem_annotation.

Object Field Name Field Type Value
eml.1.1 sem_annotation string, multivalued http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#MeasurementType
eml.1.1 sem_annotation string, multivalued http://purl.dataone.org/odo/ECSO_00001104
eml.1.1 sem_annotation string, multivalued http://purl.dataone.org/odo/ECSO_00001225

Queries

These indexed fields will be used primarily by MetacatUI to enhance discovery - both in terms of recall (concept hierarchies are exploited) and precision (concepts like Mass, do not result in false-positives for "Massachusetts"). As more aspects of the annotation model (e.g., observation Entity) are included in the index, the queries can incorporate them for greater query precision. Unfortunately, the flat nature of the SOLR index will prevent us from constructing elaborate queries and some of the flashier "semantic" queries may require more indexing fields that use SPARQL to exploit certain concept relationships above and beyond the simple parent/child relationships.

OA Ontology and Model (For posterity)

NOTE: This section is included for reference, but is no long the target implementation (March 2017).

The OA ontology can be used to describe the following relationships:

  • Which concepts describe which resources and/or parts of resources
  • Where in the structure of a resource a particular annotation applies
  • Who is credited with authoring an annotation.

The PROV ontology will be used to describe the following relationships:

  • Who is credited with generating a resource being annotated
  • Which resources are newer revisions of other resources

Existing ORE resource map relationships can be augmented in this model to provide more explicit linkage between the data files and the section of metadata that documents them. These structural annotations can assist package consumers (human and machine) when interpreting data objects. Using fragment selectors with XML-based metadata associates data resources with their entity and attribute descriptions in a way that existing DataONE ORE maps do not support.

Figure 1. Diagram illustrating the annotation model for a sample data package

figure 1

In an effort to illustrate as many features of the proposed model, the example makes the following assumptions:

  • the EML metadata package describes 1 data table file
  • the data table has 3 columns (patient, weight, height)
  • the EML package has been updated once with a new revision
  • the revised package has a revised annotation
  • there are 2 different users annotating the revised package

Important concepts used in the model:

  • oa:hasBody: The body contains the semantic concept that describes the target

  • oa:hasTarget: The target specifies the resource being annotated

  • oa:hasSource: Identifies the source of a target to which selectors can be applied.

  • oa:hasSelector: Specifies the part of a resource to which an annotation applies. An XPath FragmentSelector will commonly be used for annotating XML-based metadata resources

  • oa:annotatedBy: [subProperty of prov:wasAttributedTo] The object of the relationship is a resource that identifies the agent responsible for creating the Annotation.

  • oboe:Measurement: The primary body of semantic annotations on attributes.

  • oboe:ofCharacteristic: Specifies which Characteristic (subclass) is measured

  • oboe:usesStandard: Specifies in which Standard (Unit subclass) the measurement is recorded.

Model details

Using the weight column in our example data package, we can illustrate the annotation model's use of concepts from OBOE, OA, and PROV.

The primary entry point for the annotation is #ann.4.1 and was asserted by Ben Leinfelder (foaf:name) , identified with his ORCID URI (oa:annotatedBy).

The body of the annotation (oa:hasBody) is comprised of an oboe:Measurement instance, #weight, that measures Mass (oboe:ofCharacteristic) in Gram (oboe:usesStandard).

The target of the annotation (oa:hasTarget) points to the EML metadata resource (oa:hasSource) that documents the data table and selects a particular part of the metadata that describes the specific weight data attribute (oa:hasSelector). Because the EML metadata is serialized as XML, we can use an XPath oa:FragmentSelector to identify the data column being annotated.

Note that our XPath expression identifies weight as the second column in the first data table in the data package: #xpointer(/eml/dataSet/dataTable[1]/attributeList/attribute[2].

In order to bind the column annotation of the metadata to the physical data object (the three-column CSV file), we need to traverse the packaging model where an additional annotation expresses the relationship between the data and metadata objects. The annotation, #ann.1.1, asserts that the Metadata file (#eml.1.1) describes (cito:documents) the data file (#data.1.1). More specifically, the annotation target specifies where in the EML the #data.1.1 object is described by using an oa:FragmentSelector with an XPath pointer to the first data file documented in the EML: #xpointer(/eml/dataSet/dataTable[1].

Note that the annotation model uses a slightly different model than the original ORE resource map model recommended by DataONE. While it is more complicated to include pointers to data documentation within the metadata, we have found that the current ORE maps are not sufficiently descriptive on their own and any consumers must also consult the metadata to figure out which object is the csv, which is the pdf, which is the script, etc...

By incorporating the metadata pointer within the annotation model, we hope to be able to hanlde data packages that use manu different metadata serializations without having to write custom handlers for each formatId.

Extending the model

The proposed system for asserting and indexing annotations can easily be extended. For practical reasons, we do want to codify a preferred mechanism for expressing observation measurements and binding them to their data table attributes. But because the model is essentially just a collection of triples, and the mechanism that indexes those triples is configured with custom SPARQL queries, we can accommodate additional statements about data objects and packages in the future.

One such semantic extension involves a provenance graph for derived data products. For detailed information on that endeavor, see the ore-model-expansion section.

Another area for extension uses ORCIDs to give attribution to the appropriate author/creator. This is expressed in the model using prov:wasAttributedTo and could be readily indexed into a dynamic SOLR field like creator_sm. But until these ORCIDs are more widely adopted, it may be difficult to provide effective querying based on this field. It would also require authors to actively assert that their ORCIDs are associated certain data packages and objects; perhaps using tools that we currently do not have implemented.

Annotation serializations

Our initial serialization technique for annotations is to have a distinct file for the model. We have been using a JSON format specified by AnnotatorJS library, but other syntaxes will likely be supported.

Other methods for serializing the model we have considered and may support in the future include:

  • JSON-LD - The direction Web Annotation is going for supporting Open Annotation model. Hopefully included in AnnotatorJS v2.x
  • RDF/XML - typical RDF model serialization
  • ORE - included as additional triples in our current ORE resource map packaging serializations
  • RDFa - annotations embedded directly within the science metadata
  • triplestore - triples written directly to a triple store endpoint using an API

Annotation permissions

Because annotations ussually assert facts (or opinions) about other objects, we will allow these assertions to be indexed only if the rights holder for the RDF model has the same rightsholder priveledges on the target object. This will prevent both malicious and accidental assertions about objects by other parties who should not be influencing how the object is documented or interpreted. Unfortunately, this also prevents interested, non-rights holder parties from asserting valuable statements about research data in the system. Ideally, we will accommodate third-party annotations and expose them for use in discovery and integration so long as they are effectively labeled (e.g., "alternative annotaiton", "automated annotation", etc...).

Sample annotation using OWL

Serialization of the example model. Authored in and exported from Protege.

<?xml version="1.0"?>

<!DOCTYPE rdf:RDF [
    <!ENTITY oa "http://www.w3.org/ns/oa#" >
    <!ENTITY terms "http://purl.org/dc/terms/" >
    <!ENTITY foaf "http://xmlns.com/foaf/0.1/" >
    <!ENTITY prov "http://www.w3.org/ns/prov#" >
    <!ENTITY cito "http://purl.org/spar/cito/" >
    <!ENTITY owl "http://www.w3.org/2002/07/owl#" >
    <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" >
    <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" >
    <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
]>


<rdf:RDF xmlns="file:///Users/leinfelder/ontologies/brl/oa_sample.owl#"
     xml:base="file:///Users/leinfelder/ontologies/brl/oa_sample.owl"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:prov="http://www.w3.org/ns/prov#"
     xmlns:foaf="http://xmlns.com/foaf/0.1/"
     xmlns:oa="http://www.w3.org/ns/oa#"
     xmlns:cito="http://purl.org/spar/cito/"
     xmlns:terms="http://purl.org/dc/terms/"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <owl:Ontology rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl">
        <owl:imports rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe.owl"/>
        <owl:imports rdf:resource="http://purl.org/NET/dc_owl2dl/terms_od"/>
        <owl:imports rdf:resource="http://purl.org/spar/cito/"/>
        <owl:imports rdf:resource="http://www.w3.org/ns/oa#"/>
        <owl:imports rdf:resource="http://www.w3.org/ns/prov#"/>
        <owl:imports rdf:resource="http://xmlns.com/foaf/0.1/"/>
    </owl:Ontology>
    

    <!-- 
    ///////////////////////////////////////////////////////////////////////////////////////
    //
    // Individuals
    //
    ///////////////////////////////////////////////////////////////////////////////////////
     -->

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder">
        <rdf:type rdf:resource="&prov;Person"/>
        <foaf:name rdf:datatype="&xsd;string">Benjamin River Leinfelder</foaf:name>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#MattJones -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#MattJones">
        <rdf:type rdf:resource="&prov;Person"/>
        <foaf:name rdf:datatype="&xsd;string">Matthew Bently Jones</foaf:name>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.1.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.1.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:b1"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t1"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.2.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.2.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:b1"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t2"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.3.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.3.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:annotatedBy rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#patient"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t3"/>
    </owl:NamedIndividual>
  
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.4.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.4.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:annotatedBy rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t4"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#weight"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.5.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.5.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:annotatedBy rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#height"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t4"/>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.6.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.6.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:annotatedBy rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:rev"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t6"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.7.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#ann.7.1">
        <rdf:type rdf:resource="&oa;Annotation"/>
        <oa:annotatedBy rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#MattJones"/>
        <oa:hasBody rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:alt"/>
        <oa:hasTarget rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t7"/>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#data.1.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#data.1.1">
        <rdf:type rdf:resource="&prov;Entity"/>
        <terms:identifier rdf:datatype="&xsd;string">doi:10.1234/data.1.1</terms:identifier>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1">
        <rdf:type rdf:resource="&prov;Entity"/>
        <terms:identifier rdf:datatype="&xsd;string">doi:10.12345/eml.1.1</terms:identifier>
        <prov:wasAttributedTo rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#BenLeinfelder"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.2.1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.2.1">
        <rdf:type rdf:resource="&prov;Entity"/>
        <terms:identifier rdf:datatype="&xsd;string">doi:10.12345/eml.2.1</terms:identifier>
        <prov:wasRevisionOf rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1"/>
    </owl:NamedIndividual>
 
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#height -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#height">
        <rdf:type rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Measurement"/>
        <rdf:type>
            <owl:Restriction>
                <owl:onProperty rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#usesStandard"/>
                <owl:allValuesFrom rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-standards.owl#Meter"/>
            </owl:Restriction>
        </rdf:type>
        <rdf:type>
            <owl:Restriction>
                <owl:onProperty rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#ofCharacteristic"/>
                <owl:allValuesFrom rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-characteristics.owl#Length"/>
            </owl:Restriction>
        </rdf:type>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#patient -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#patient">
        <rdf:type rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Measurement"/>
        <rdf:type>
            <owl:Restriction>
                <owl:onProperty rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#ofCharacteristic"/>
                <owl:allValuesFrom rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Name"/>
            </owl:Restriction>
        </rdf:type>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:alt -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:alt">
        <rdf:type rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#Body"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:b1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:b1">
        <rdf:type rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#Body"/>
        <cito:documents rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#data.1.1"/>
    </owl:NamedIndividual>
   
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:rev -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:rev">
        <rdf:type rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#Body"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t1 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t1">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1)"/>
    </owl:NamedIndividual>
   
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t2 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t2">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.2.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1)"/>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t3 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t3">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/1)"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t4 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t4">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/2)"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t5 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t5">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.1.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/3)"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t6 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t6">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.2.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/1)"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t7 -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#urn:t7">
        <rdf:type rdf:resource="&oa;SpecificResource"/>
        <oa:hasSource rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#eml.2.1"/>
        <oa:hasSelector rdf:resource="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/1)"/>
    </owl:NamedIndividual>
   
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#weight -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#weight">
        <rdf:type rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#Measurement"/>
        <rdf:type>
            <owl:Restriction>
                <owl:onProperty rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#ofCharacteristic"/>
                <owl:allValuesFrom rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-characteristics.owl#Mass"/>
            </owl:Restriction>
        </rdf:type>
        <rdf:type>
            <owl:Restriction>
                <owl:onProperty rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-core.owl#usesStandard"/>
                <owl:allValuesFrom rdf:resource="http://ecoinformatics.org/oboe/oboe.1.0/oboe-standards.owl#Gram"/>
            </owl:Restriction>
        </rdf:type>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1) -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1)">
        <rdf:type rdf:resource="&oa;FragmentSelector"/>
    </owl:NamedIndividual>
    
    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/1) -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/1)">
        <rdf:type rdf:resource="&oa;FragmentSelector"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/2) -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/2)">
        <rdf:type rdf:resource="&oa;FragmentSelector"/>
    </owl:NamedIndividual>

    <!-- https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/3) -->
    <owl:NamedIndividual rdf:about="https://code.ecoinformatics.org/code/semtools/trunk/docs/design/dataone/oa_sample.owl#xpointer(/eml/dataSet/1/attributeList/3)">
        <rdf:type rdf:resource="&oa;FragmentSelector"/>
    </owl:NamedIndividual>
</rdf:RDF>

<!-- Generated by the OWL API (version 3.4.2) http://owlapi.sourceforge.net -->