KnowWhereGraph has a large ontology.
It's no secret that navigating any ontology is a time consuming, often difficult process. KnowWhereGraph is no exception.
We provide a Widoco documentation page for our ontology which includes diagrams to help compartmentalize, visualize, and digest the various components in a way to help better understand how the graph is structured.
KnowWhereGraph Widoco Ontology Docs
There are several key points that make working with and understanding the ontology easier.
KnowWhereGraph uses OWL time for temporal information. We don't use the entire ontology, just a few pieces that are summarized below.
The most basic nodes that represent time are nodes of type time:Instant
. These nodes typically have four properties:
- A label with the full datetime
- An XSD:Date representation
- An XSD:DateTime representation
- The year
An example is shown below where the full datetime and year are retrieved from a node of type time:Instant
.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
select ?time_label ?datetime ?year where {
?time_node rdf:type time:Instant .
?time_node rdfs:label ?time_label .
?time_node time:inXSDDateTime ?datetime .
?time_node time:inXSDgYear ?year .
} limit 1
Time intervals are nodes that represent a period of time. They have two properties of interest that point to time instants (see above):
time:hasBeginning
(when the period of time starts)time:hasEnd
(when the period of time ends)
The convenient bit about nodes of this type is that they reference time:Instant
nodes through the two relations above.
An example of pulling out the start and end datetimes of an interval is given below. Note how the pattern of querying time:Instant
is used. All we've done is start at a time:Interval
and grabbed the values from the attached time:Instant
.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
select ?time_label?datetime_begin ?datetime_end where {
?time_interval rdf:type time:Interval .
?time_interval rdfs:label ?time_label .
?time_interval time:hasBeginning ?time_begin .
?time_interval time:hasEnd ?time_end .
?time_begin time:inXSDDateTime ?datetime_begin .
?time_end time:inXSDDateTime ?datetime_end .
} limit 1
When connecting events and data to time, KnowWhereGraph uses its own term, kwg-ont:hasTemporalScope
. You will always use this relation to obtain temporal information about an event.
One important note to take is that data of the same class can have either time:Instant
or time:Interval
data. This means that if you're querying for data of type kwg-ont:Hazard
and asking for temporal information — you need to look for both time:Instant
and time:Interval
connections.
An example is shown below where we count the number of kwg-ont:Hazard
s that are connected to time:Instant
. At the time of this writing, there are 1,248,050 hazards with time instant data.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select (count (?scope) as ?count) where {
?hazard rdf:type kwg-ont:Hazard .
?hazard kwg-ont:hasTemporalScope ?scope .
?scope rdf:type time:Instant .
}
Doing the same for intervals, we see that there are 1,048,577 events with time interval data.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select (count (?scope) as ?count) where {
?hazard rdf:type kwg-ont:Hazard .
?hazard kwg-ont:hasTemporalScope ?scope .
?scope rdf:type time:Interval .
}
Because some hazards have instants while others have intervals, the SPARQL becomes a little more complicated to get information about both at the same time. To avoid excluding each type, we have to make use of SPARQL's OPTIONAL
clause.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select ?datetime ?datetime_begin ?datetime_end where {
?hazard rdf:type kwg-ont:Hazard .
?hazard kwg-ont:hasTemporalScope ?hazard_time .
OPTIONAL {
?hazard_time rdf:type time:Interval .
?hazard_time time:hasBeginning ?time_begin .
?hazard_time time:hasBeginning ?time_end .
?time_begin time:inXSDDateTime ?datetime_begin .
?time_end time:inXSDDateTime ?datetime_end .
}
OPTIONAL {
?hazard_time rdf:type time:Instant .
?hazard_time time:inXSDDateTime ?datetime .
}
} LIMIT 16
The query results are shown below. The important thing to note here is that we have datetimes for instants and the full range for time intervals.
Spatial information is encoded using the GeoSPARQL standard.
This means that
- You can expect all classes that represent spatial things to be some subclass of
geo:Feature
. - Geometries will be connected to features with
geo:hasGeometry
andgeo:hasDefaultGeometry
- Geometry literals (the actual coordinates that make up the geometry) can be obtained from the geometry node with
geo:asWKT
An example is shown below where the geometry node for a kwg-ont:Hazard
is retrieved, followed by its geometry literal. This pattern is used across KnowWhereGraph where different node types are in place of kwg-ont:Hazard
.
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select ?hazard_label ?geometry_label ?geometry_literal where {
?hazard rdf:type kwg-ont:Hazard .
?hazard geo:hasGeometry ?geometry .
?hazard rdfs:label ?hazard_label .
?geometry rdfs:label ?geometry_label .
?geometry geo:asWKT ?geometry_literal .
} limit 1
The results for the query are shown below.
Data is encoded using the SOSA ontology. Looking at the SOSA docs, you'll see that it's a large, complicated ontology! Fortunately, KnowWhereGraph only makes use of several components:
sosa:Observation
: Contains numeric or categorical data about an observation which is stored as literal values, accessible throughsosa:hasSimpleResult
.sosa:ObservationCollection
: Nodes of this type point to one or moresosa:Observation
nodes through the relationsosa:hasMember
.
Rather than using the class names above, KnowWhereGraph subclasses them into more specific instances. For example, thunderstorm events are connected to kwg-ont:ImpactObservationCollection
, which is a subclass of sosa:ObservationCollection
. Nodes can be connected to multiple observation collections, of different types.
This won't make a huge impact on the way you query data, but it allows you to be more specific in the kinds of data that you want.
When reading and using the SOSA ontology, it's important to buy into the concept of properties and observations:
- Properties: Things being observed. This could be the air temperature, number of deaths, obesity rates, number of beds that a hospital has, etc.
- Observation: The act that resulted in a property being observed. It provides the context around the property, such as the value of the property or the name of the observation. This would be the literal number of hospital beds.
For example,the following query retrieves all the observation collections for a particular hazard instance.
PREFIX sosa: <http://www.w3.org/ns/sosa/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select ?observation_collection where {
<http://stko-kwg.geog.ucsb.edu/lod/resource/hazard.82519.496804> sosa:isFeatureOfInterestOf ?observation_collection .
?observation_collection rdf:type sosa:ObservationCollection .
}
We see two nodes, which are of type
kwg-ont:ImpactObservationCollection
kwg-ont:WindMagnitudeObservationCollection
The KnowWhereGraph ontology lists all the different kinds of observation collection types that can be requested.
If instead we wanted just the kwg-ont:ImpactObservationCollection
data, we would specify the type.
PREFIX sosa: <http://www.w3.org/ns/sosa/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
select * where {
?hazard rdf:type kwg-ont:Hazard .
?hazard sosa:isFeatureOfInterestOf ?observation_collection .
?observation_collection rdf:type kwg-ont:ImpactObservationCollection .
} LIMIT 10
KnowWhereGraph provides an array of different kinds of data. To make it easy to query, we segment each data type into a different class. The image below shows a node of type kwg-ont:ImpactObservationCollection
. It has several observations, each describing a different type of data. From the names alone, we see that there's data related to
- Deaths caused directly by the incident
- Deaths caused indirectly by the incident
- Injuries caused directly by the incident
- Injuries caused indirectly by the incident
Each of these nodes is a sosa:Observation
and can be queried the same way. For a complete list of types of data, refer to the ontology. In addition to the observation having a type — it also has an important field sosa:observedProperty
. This is also used to filter queries to the desired type. Again, the ontology lists the various properties that have been observed.
A complete example of retrieving the number of direct deaths for several hazards is shown below. Note the connections between the kwg-ont:Hazard
, the sosa:ObservationCollection
(technically, KnowWhereGraph's subclass of it), and the portion of the query obtaining the literal values.
PREFIX sosa: <http://www.w3.org/ns/sosa/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX kwg-ont: <http://stko-kwg.geog.ucsb.edu/lod/ontology/>
PREFIX kwgr: <http://stko-kwg.geog.ucsb.edu/lod/resource/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?hazard_name ?direct_deaths where {
?hazard rdf:type kwg-ont:Hazard .
?hazard rdfs:label ?hazard_name .
?hazard sosa:isFeatureOfInterestOf ?observation_collection .
?observation_collection rdf:type kwg-ont:ImpactObservationCollection .
?observation_collection sosa:hasMember ?observation .
?observation sosa:observedProperty kwgr:impactObservableProperty.deathDirect .
?observation sosa:hasSimpleResult ?direct_deaths .
} LIMIT 10
The results are shown below (luckily these events had 0 associated deaths).