Index


Structured Data on the Web#
About#
Structured data on the web is a way to provide semantics and linked data in an
approachable manner.  This approach expresses concepts in JSON-LD which is a
JavaScript notation popular among developers which easily expresses  concepts
(terms) and links to related resources (things).   This structured data on the
web approach has been popularized by the large commercial search providers like
Google, Bing, Yandex and others via schema.org  As described at schema.org:
“Schema.org is a collaborative, community activity with a mission to create,
maintain, and promote schemas for structured data on the Internet, on web pages,
in email messages, and beyond.”
The popularity of leveraging the schema.org approach in the earth sciences can
be attributed to both this ease of developer adoption and also to its
foundational use of web architecture. A web architecture foundation aids
adoption by the operations side as well as the developer side.  It also takes
advantage of the scale and resilience of the web.
The broad nature of schema.org even scopes to the concepts of Datasets.  It is
the existence of schema.org/Dataset that was a focus of several EarthCube
projects (Project 418, Project 419 and the Resource Registry) from which spun up
the ESIP Science on Schema work.
Additionally, Google leveraged schema.org/Dataset to develop and populate the


Additionally, Google leveraged schema.org/Dataset to develop and populate the
Google Data Set Search and provides guidance to developers to facilitate this.
Web architecture approach#
OIH is focused on leveraging the web architecture as the foundation for this
approach.  There are several key reasons for this vs approaches like OAI-PMH or
others.
A key point is that in the processes of establishing a web presence, a standard
step for groups, they have already begun to build the infrastructure needed for
structured data on the web.  Setting up special servers or establishing and
maintaining special APIs to support harvesting is not required.
Also, a large collection of tooling already exists around JSON that is directly
usable in JSON-LD.  That scale extends to the use of schema.org patterns which
have become common in the commercial web.  Allowing us to bring those same
patterns and the tooling to the science community.
Additionally, this approach keeps the metadata and its representation a product
of the data providers.  The actor in the life cycle most aware of needed edits,
new records or other events.  That same record then serves multiple consumers
able to generate various value add products.  This benefits the provider by
facilitating multiple and varied discovery vectors for their holdings.
Another key factor is the web native and semantic nature of this representation


Another key factor is the web native and semantic nature of this representation
of metadata.  Traditional metadata, such as ISO, by itself does not express a
web referenceable instance of concepts.  In doing this, structured data on the
web allow connections to be made and discovered by people and machines across
many holdings.  This aids in both serendipitous discovery and can also be
leveraged to aid discovery via semantic relations.
Terminology#
A CSV file is a text file containing spreadsheet information following a data
model that is encoded using a convention of rows and commas defining columns.
A JSON-LD fle is a text file containing graph information following the RDF data
model that is encoded using a convention based on JSON syntax.
JSON-LD is a way to serialize RDF that uses JSON notation.  It is really no
different then than RDF-XML, turtle, n-triples, etc.  There are several ways to
represent the RDF data model in text files (and some emerging binary ones like
CBOR and parquet patterns).
Schema.org is a vocabulary for describing things similar to DCAT, FOAF, Dublin
Core.  It does this by using RDF as the underlying data model to represent this
“ontology”.
The confusion comes from the collision of outcomes.  JSON-LD came about, partly,
to allow the use of the RDF data model by a broader audience.  This is done by


to allow the use of the RDF data model by a broader audience.  This is done by
leveraging a more popular notation for the data model, JSON, in the form of
JSON-LD.  Schema.org also wanted to advance the use of structured [meta]data by
making it easier to use and connecting structured data to web pages.  At the
start, there were three approaches; RDFa, microformats and JSON-LD, to putting
schema.org in web pages.  However, the JSON-LD approach to incorporating this
structured data has grown in popularity far beyond the others. As the popularity
of both JSON-LD and schema.org grew,  they often got conflated with each other.
The term  “structured data on the web” is perhaps a more neutral way to discuss
the use of vocabularies encoding in JSON-LD used in web pages.  However,  the
phrase “schema.org” is starting to become the term for “structured data on the
web using JSON-LD as a serialization”.    Even in cases where you combine other
vocabularies such as DCAT with JSON-LD with no schema.org involved, it seems the
way to convey this is to say: “We will use the schema.org ‘pattern’ with DCAT”.
It is arguably not the best or most accurate communications strategy.  It can


It is arguably not the best or most accurate communications strategy.  It can
conflate data models, serialization and vocabularies.  However, it is concise
and ubiquitous and not likely to change.
Intellectual Merit#
OIH leverages structured data o the web patterns in the form of of
Schema.org and JSON-LD encoding.  This means that much of what is done
to address OIH implementation by providers also is available both to existing
commercial indexing approaches as well as emerging community practices
Additionally, both the publishing and indexing approaches are based
on several web architecture patterns.  Meaning that existing organization skills
are leveraged and staff experience is enhanced.   This helps to address both
the sustainability of the OIH connection and the efficiency of
organizational operation.
Broader Impacts#
By leveraging existing technology and approaches a larger community is enabled
to engage and make more samples discoverable and usable.
The nature of structured data on the web also provides the ability to apply
semantic context to samples.  This means richer discovery and information about
samples, the past uses and potential future uses is more readily available.
Simplified architecture also means easier development of tools and interfaces to
present the data.  Allowing the presentation of samples and their information in
a manner aligned with a given community’s needs.    A simplified architecture
aids sustainability from both a technical and financial perspective.


Search
    Please activate JavaScript to enable the search
    functionality.

    Searching for multiple words only shows matches that contain
    all words.


The Ocean InfoHub Project#
Introduction#
The Ocean InfoHub aims to build a sustainable, interoperable, and inclusive digital ecosystem for all Ocean data centres. Existing and emerging data systems are linked, with the ultimate goal of coordinating action and capacity to improve access to Ocean data and knowledge.
The following video provide brief high level context to the Ocean InfoHub project.
Broucher
Organizations are increasingly exposing data and resources on the Web.   A popular approach to this is using web architecture to expose structured data on the web using the schema.org vocabulary.   Doing this makes resources discoverable by a range of organizations leveraging this architecture to build indexes.  These include major commercial indexes, large domain focused groups and community focused services.
The Ocean Data and Information System (ODIS) will provide a schema.org based interoperability layer and supporting technology to allow existing and emerging ocean data and information systems, from any stakeholder, to interoperate with one another. This will enable and accelerate more effective development and dissemination of digital technology and sharing of ocean data, information, and knowledge. As such, ODIS will not be a new portal or centralized system, but will provide a collaborative solution to interlink distributed systems for common goals. Together with global project partners and partners in the three regions, a process of co-design will enable a number of global and regional nodes to test the proof of concept for the ODIS.


The ODIS-architecture development is being supported by the Ocean InfoHub Project, and it has been tested initially on IOC and partner databases. However, the system and standards are open for any institution or initiative that is interested in accessing the global data ecosystem to adopt and implement.
Guidance for the implementation of the ODIS-architecture#
OIH is providing guidance on the various stages of such an
architecture including authoring, publishing, indexing and interfaces.
The basics of this approach can be described as:
Providers publish HTML pages for a resource.  This may be a publication, course description, research instrument or other.   The core themes for OIH are described in the Authoring section below.
A HTML page then has a small JSON based snippet added to the HTML.  This is
described in the Including JSON-LD in your resource page in the Publishing
resource below.
If you wish a resource to be included in the OIH index, then you need to
include it in a sitemap file.  This is a small XML document that lists links
to the resources you wish to be part of the index.  This approach is shown in
the sitemap.xml section of the Publishing resource.
Once the above is done the publishing phase is over.  At this point, OIH or
other groups can now access and index your resources.   OIH is using some


other groups can now access and index your resources.   OIH is using some
existing software to index and generate the graph and expose a simple
reference interface to them.  This software is open and available and others
are free to implement the approach with other software.  Links to other
software are at the repository.
The OIH index/graph and a simple interface is current at a development site
and in a later phase of OIH a production interface will be developed.
Additionally, software to aid in validating and checking the resources is under
development and will be available at the repository.   This will aid providers
in expressing the information needed to address interfaces and services of
interest to the community.
The result is a sustainable architecture to address discovery and access to
various resources published by the community and a shared graph of these
resources.  That shared graph can be used by all members to link and discover
across groups.
Key links to the OIH GitHub repository#
Interested groups can review material addressing these stages at the OIH GitHub
repository.  Links and descriptions of these stages are described below.
Authoring Thematic Patterns#
The ODIS OIH is working across five major thematic areas; Experts and
Institutions, Documents, Projects, Training, Vessels.   Examples of these
thematic concepts are being hosted and developed with input from the community.


thematic concepts are being hosted and developed with input from the community.
Additionally, methods for validation and simple tooling for authoring and
testing are hosted at this repository.  Alongside these five thematic topics
guidance on connecting services and spatial context on resources.
Publishing#
Guidance on implementation the web architecture approach is also available.
This includes approaches on leveraging robots.txt and sitemaps.xml file for
expressing hosted resources to the net.
Indexing#
The architecture approach is open and standards based.  As such, many
organizations will be able to leverage the authoring and publishing approaches
above to index a providers resources.  OIH will be providing reference
implementations of software that can generate the index.
Interfaces and Services#
During the development of the OIH a basic reference implementation for an
interface has been generated.  This is a development site meant to test and
exercise the above elements.   It serves to demonstrate how others could also
implement this approach and how future interfaces could be developed.
An example of the value of implementing a lightweight can be seen with the
Government of Canada:
The Federal Geospatial Platform is a intra-governmental data catalogue
implementing the Harmonized North American Profile of ISO 19115 (HNAP), with
content exposed externally via OGC CSW (Catalogue Services Web).
This content is harvested by the public facing Open Maps platform, which


This content is harvested by the public facing Open Maps platform, which
includes a catalogue component that is fed in part by the Federal Geospatial
Platform. DCAT-based metadata is derived from the original ISO 19115 based
metadata. As this markup is recognized by web crawlers such as those hosted by
Google, content is harvested and is subsequently visible through Google
Dataset Search. Furthermore, the cited publication for the data is also link
via a complementary link to Google Scholar.


Publisher#
About#
This page describes the publishing process for structured data
on the web approach OIH will use.
Note many software packages you are using might already
implement this approach.  See the section:
Existing support in software at the bottom of this document.
See also
We also recommend reviewing the document:
Schema.org for Research Data Managers: A Primer
Architecture Implementation#
The Ocean Info Hub (OIH) will leverage structured data on the web and web
architecture patterns to expose metadata about resources of interest to the
community.  The primary tasks include:
Authoring JSON-LD documents (https://json-ld.org/) aligned with ODIS OIH
guidance to express the structured metadata for a resource.  This step will
require experience with using the existing metadata resources within an
organization.  So any necessary skills needed to access or query existing
facility data systems will be needed to assemble the information to populate
the JSON-LD data graph.  The JSON-LD documents need to be generated using the
tools/languages at the previous reference or through other means.
Within the system architecture of the site, a JSON-LD document needs to be
placed into the HTML DOM as a SCRIPT tag within the HEAD tag of each
published resource.   The SCRIPT tag pattern is:
<script type="application/ld+json">JSON_LD content</script>


<script type="application/ld+json">JSON_LD content</script>
Additionally these resources that are marked up with these tags and JSON-LD
documents should be expressed in an XML sitemap file.  This should follow the
guidance at https://www.sitemaps.org/.  It should also include a lastmod node
element as described at https://www.sitemaps.org/protocol.html which should
indicate the date the resource metadata was last updated and published to the
web.
The process of aligning the JSON-LD is iterative at this stage as the OIH
profile is evolved.  To aid this we can leverage existing validation tools
including JSONSchema, W3C SPARQL and more to communicate structure changes.
These tools exist and need only be implemented using knowledge of command
line environments.  The results will then indicate revisions needed in the
JSON-LD.  OIH will provide the necessary templates for the tools to use
against the authored JSON-LD documents.
Information on the sources, standards and vocabularies to be used can be found
at: https://github.com/iodepo/odis-arch/tree/schema-dev/docs
Including JSON-LD in your resource page#
To provide detailed and semantically described details on a resource, OIH uses
a JSON-LD snippet or data graph.  This small document


a JSON-LD snippet or data graph.  This small document
provides details on the resource.  It can also express any explicate
connections to other resources an author may wish to express.  The semantic
nature of the document also means that connections may later be discovered
through graph queries.
Pages will need a JSON-LD data graph placed in it via a typed script
tag/element in the document head element like the following.
<script type="application/ld+json"></script>
An example data graph can be seen below.   However, check the various
thematic sections for more examples for a given thematic area.
{
    "@context": {
        "@vocab": "https://schema.org/",
        "endDate": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
        },
        "startDate": {
            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
        }
    },
    "@id": "https://foo.org/url/to/metadata/representation",
    "@type": "Course",
    "description": "In this course you will get an introduction to the main tools and ideas in the data scientist's toolbox...",
    "hasCourseInstance": {
        "@type": "CourseInstance",
        "courseMode": [
            "MOOC",
            "online"


"courseMode": [
            "MOOC",
            "online"
        ],
        "endDate": "2019-03-21",
        "startDate": "2019-02-15"
    }
}
This example is from the training and courses thematic
section.  To view all the types
being developed reference
the Thematic section.
These JSON-LD documents leverage schema.org as the primary vocabulary.
The examples in the thematic section provide examples for the various type.
JSON-LD Tools and References#
A key resource for JSON-LD can be found at JSON-LD.
There is also an interactive playground hosted there.  The JSON-LD
Playground is useful when testing or
exploring approaches for JSON-LD data graphs.  It will catch basic errors of
syntax and use.  Note, it will not catch semantic issues such as using
properties on types that are out of range.  Tools like the Structured Data
Testing Tool are
better at that.  Also the documents and validation material created here OIH
will also allow for that sort of testing and feedback.
Providers may also wish to provide content negotiation for type application/ld+json
for these resources. Some indexers,  like Gleaner, will attempt to negotiate for
the specific serialization and this will likely lighten the load on the servers going forward.


the specific serialization and this will likely lighten the load on the servers going forward.
Validation With SHACL or ShEx#
To help facilitate the interconnection of resource, some application focused validation
will be developed. Note, this validation does not limit what can be in the graphs.
Rather, it simply provides insight on to how well a given graph can be
leveraged for a specific application.  For this project, the application will
be the OIH search portal.
Some initial development work for this can be found in the
validation directory
Validation Tools and References#
SHACL playground
Schemarama
Schimatos.org
demo
Comparing ShEx and SHACL
Validation Leveraging JSON Schema#
We have been exploring the potential to use JSON Schema combined with various
on-line JSON editors (JSON Schema driven) to provide a potential approach to a
more visual editing workflow. The workflow presented here is very ad hoc but
exposes a potential route a group might take to develop a usable tool. Such a
tool might, for example, leverage the Electron app dev environment to evolve
this approach in a more dedicated tool/manner.
Use a JSON-LD document (Example) one could
load this into something like
the JSONschema.net tool.
The results of the above can then been loaded into the online JSON-Editor at
https://json-editor.github.io/json-editor/. (Ref:


https://json-editor.github.io/json-editor/. (Ref:
https://github.com/json-editor/json-editor)
The results of this then can be loaded into https://json-ld.org/playground/ to
validate that we have well formed JSON-LD.
Though this workflow is rather crude and manual it exposes a route to a defined
workflow based around established schema that leverages other tools and
software libraries to generate a workable tool.
Basics#
The basic activity can be seen in the following diagram:
Elements in detail#
robots.txt#
OPTIONAL: Providers may decide to generate or modify their robots.txt
file to provide guidance to the aggregators.
The plan is to use the Gleaner software (gleaner.io) as well as some
Python based notebooks and a few other approaches in this test.
Gleaner uses an agent string of EarthCube_DataBot/1.0 and this can be
used a robots.txt file to specify alternative sitemaps and guidance.
This also allows a provider to provide guidance to Google and other potential
indexers both for allow and disallow directives.
Sitemap: http://samples.earth/sitemap.xml
User-agent: *
Crawl-delay: 4
Allow: /
User-agent: Googlebot
Disallow: /id
User-agent: EarthCube_DataBot/1.0
Allow: /


User-agent: EarthCube_DataBot/1.0
Allow: /
Sitemap: https://example.org/sitemap.xml
sitemap.xml#
Providers will need to expose a set of resource
landing pages using a sitemap.xml file. As noted above, providers
can expose a sitemap file to just the target agent
to avoid indexing test pages by commercial providers.  You may wish
to do this during testing or for other reasons.  Otherwise,
a sitemap.xml file exposed in general from somewhere in your site is
perfectly fine.
Information on the sitemap structure can be found at sitemaps.org.
It is encouraged to use the sitemap lastmod node
to provide guidance to indexers on page updates.
Additionally indexers may test ways to evaluate additions and
removals from the sitemap URL set to manage new or removed resources.
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/site0.9">
   <sitemap>
      <loc>http://samples.earth/sitemap_websites_sampleseaxml</loc>
      <lastmod>2004-10-01T18:23:17+00:00</lastmod>
   </sitemap>
   <sitemap>


</sitemap>
   <sitemap>
      <loc>http://samples.easitemap_doclouds_igsndatagraphs.xml</loc>
      <lastmod>2005-01-01</lastmod>
   </sitemap>
</sitemapindex>
Full Workflow#
The architecture defines a workflow for objects seen in the above diagram.
The documents flow from; authoring, publishing and indexing to
storage for the objects and the resulting graph.  These resources are
then ready for use in search and other functions.
Moving left to right we can review the image.
Providers are engaged in the process of developing the OIH example
documents.  These provide a profile to follow to represent the semantic
metadata.  Note, these are not limiters, simply guidance on minimum and
recommend elements to address the functional goals of the OIH portal.
Providers use these documents to generate the JSON-LD data graphs.
These can be either static documents or generated and placed in pages
dynamically with Javascript or server side templates.  These are the
existing web pages for the resoruces, not enhanced with the
semantic metadata snippets in the HTML source.
These are published to the web and referenced in the sitemap.xml
document that is also made available.  At this point this material is
available to anyone who may wish to index it and provide discovery
for these resources.


available to anyone who may wish to index it and provide discovery
for these resources.
OIH Portal will then index and validate these resources on a
recurring bases to maintain a current index.  This index will include
both the JSON-LD objects and the graph they form.  This graph can
be used for search, connections and other value add services for the
community. The graph is also directly available to the community for them
to use in support of services they may wish to provide.
Existing support in software#
Many content management systems other web based data interfaces
may already have support for the structured data on the web pattern and
schema.org specifically. While it is beyond the scope of this project to
detail each one, a few starting points for exploration are provided below
for some of the more common ones.
Drupal
CKAN
DSpace
DKAN
ERDDAP (native support)
OPeNDAP (native support)
GeoNode
schema.org issue ref


JSON-LD Foundation#
Introduction#
JSON-LD is a way of encoding Linked Data in JSON, the popular data interchange
format used by many web APIs. Linked Data is a method of representing information
on the web in a way that allows it to be linked and interconnected with other data.
This allows data from different sources to be connected and used together in new
and powerful ways. JSON-LD uses a standardized syntax to represent Linked Data,
making it easier to integrate with other systems and tools. It is often used to
add structured data to web pages, making it easier for search engines and other
applications to understand and process the information on the page.
This document provide a very brief introduction to the JSON-LD serialization format.
The JSON-LD website has some detailed material and videos in
their documentation section.
The material here is just a brief introduction.   For this page we will be using
a simplified version of a CreativeWork document. All the types used by OIH are defined
by Schema.org types.  In this case it is CreativeWork.
At the Schema.org site you will find extensive details on what the various types mean and
the full range of their properties. For OIH we are defining only a few of these properties
as of interest in the Thematic section.  You are free to use additional
properties to describe your resources.  It will not cause any issues, however, the OIH interfaces


may not leverage them.  However, if you feel others would, or you use them yourself, it’s encouraged
to add them.
We will use the following simple JSON-LD document to show the various features of the format.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"
10}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
sys.path.insert(0, currentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/foundation/graphs/simple.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)


compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Note
A small note on nomenclature. In Schema.org, as in ontologies, the class or type
names of Things will be uppercase.  So, for example, in the above JSON-LD data graph,
this is describing a resource of type CreativeWork.   So the type CreativeWork will
start with an uppercase letter.  The property name is a property of the type and
properties like this will be lowercase.
The Context#
The context is where the terms used in a document are connected to definitions and identifiers for them.
If you wish to dive into the details of the context check out the
W3 JSON-LD 1.1 Recommendations Context section.
The context part of this document is highlighted below.
 1{
 2    "@context": {


1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"
10}
Note
This @context section will be the same for all
the documents described in OIH documentation with the exception of the spatial patterns.
As justed noted, for the spatial patterns we add in the OGC context
to all us to use terms from that vocabulary.
Below we can see the addition of the geosparql context in line 4 and the use of the vocabulary, using the defined geosparql: prefix in lines 9, 11 and 15.
If we wanted to use other vocabularies like DCAT or FOAF, we would add them to the context with a
prefix and then the vocabulary namespace.  We could then use terms from that vocabulary in our document
following the same prefix:term pattern.
 1{
 2    "@context": {
 3      "@vocab": "https://schema.org/",


3      "@vocab": "https://schema.org/",
 4      "geosparql": "http://www.opengis.net/ont/geosparql#"
 5    },
 6    "@id": "https://example.org/id/XYZ",
 7    "@type": "Dataset",
 8    "name": "Data set name",
 9    "geosparql:hasGeometry": {
10        "@type": "http://www.opengis.net/ont/sf#Point",
11        "geosparql:asWKT": {
12            "@type": "http://www.opengis.net/ont/geosparql#wktLiteral",
13            "@value": "POINT(-76 -18)"
14        },
15        "geosparql:crs": {
16            "@id": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
17        }
18    }
19}
20
Graph#
The next section we will discuss is the graph part of the document seen in lines 5-9 below.  This is where the properties and
values of our resource are described.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },


3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"
10}
First though, let’s visit a couple special properties in our
document.
Node identifiers (@id)#
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"
10}
The first special property is the @id property.  This is the identifier for the top level node in the
graph and is typically the identifier for the record.
Note


graph and is typically the identifier for the record.
Note
It should be noted this is the not the ID for the object being described but rather the record itself.
If you are describing a dataset with a DOI, for example, the @id is not that DOI.  Rather it is the
ID, potentially the URL, for the metadata record about that dataset.  Your dataset ID would be included
in the metadata record using the the identifier property.
It’s good practice to ensure all your records have an @id property.  If there is no value then the
resource is identified by what is known as a blank node.  Such identifiers do not allowing use in
a Linked Open Data approach and are generally not recommended.
The @id should be the URL for the metadata record itself.  Not the HTML page the record is in.  However,
these might be the same if use use content negotiation to select between HTML and JSON-LD representations
of the record.
Type identifiers (@type)#
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",


8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"
10}
The next property to focus on is the @type property.  This describes the type of record we are describing.
Note
In Schema.org and in most vocabularies, types will be named with a capitol letter.  Properties on these
types will be all lower case.  So, CreateWork, as a type, starts with a upper case C.  Then, name, as
a property on the CreateWork type, starts with a lower case n.
For OIH these type for the various thematic profiles are defined in the documentation for the types.
Other properties#
At this point we can return to look at the other properties for our type.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@type": "CreativeWork",
 6    "@id": "https://example.org/id/XYZ",
 7    "name": "Name or title of the document",
 8    "description": "Description of the creative work to aid in searching",
 9    "url":  "https://www.sample-data-repository.org/creativework/report.pdf"


10}
As noted, we are using Schema.org type for OIH.  In this case, as mentioned,
this is type  CreativeWork.  So any of the properties
seen at the Schema.org site can be used.   The key properties of value to the OIH implementation can then
be found, for this type, in the Documents thematic type.
For the OIH implementation, we will use the following properties as core properties we
want all OIH documents to have.  These include:
name:  The name of the document or item being described
description:  A description of the document or item being described
url: A URL for the document or item being described.
Domain and range#
The domain of a property identifies the type of object it can be applied to.
So if the domain of a property like schema.org/knowsAbout
is Person and Organization.  Then that property can only be used on those types.
For example, it would not be correct to use knowsAbout on a resource of type Dataset.
The range of a property identifies the type of object the property can point to.  In
the case of knowAbout, we see its range as Text, Thing or URL.  This means the property
can point to a Text, Thing or URL object.
In schema.org, the domain will be identified as “Used on these types”, and the


In schema.org, the domain will be identified as “Used on these types”, and the
range will be identified as “Values expected to be one of these types”.  You can see
this at the schema.org/knowsAbout page.
Thing and DataType#
The Thing and Datatype types
are two special types we should mention.  Thing is the upper level and most generic
type in schema.org.   Everything in schema.org is descended from Thing.  So when
knowsAbout says its range includes Thing, it means you can use any type in schema.org
as the value of that property.
DataType is the basic data type Thing in schema.org and is a subclass of rdfs:Class.
A DataType includes things like Integers, Strings, DateTime, etc.  So, using again
knowsAbout, we see the range includes not only Thing by also the DataTypes Text
and URL, where URL is actually a sub-type of Text.


Thematic Patterns#
Introduction#
These thematic patterns are managed by OIH and the community to add in the discovery and use
of ocean related resources.  The patterns are simple examples of Schema.org types, with a focus
on the properties and type relations of value to the Ocean InfoHub and the community it engages.
These “profiles” provide both a starting point for new users and a catalysis for discussion and
extension with the community.
Thematic Profiles#
These profiles represent a reference implementation of schema.org Types
related to the identified ODIS thematic areas.  They provide a set of minimal elements
and notes on more detailed elements.
These are not final and will evolve with community input.  As this process moves forward we will implement
versioning of the profiles to provide stable implementations providers can reliably leverage in their workflows.
Core Profiles#
Six key categories of interest:
Experts and Institutions
Documents
Spatial Maps
Projects
Training
Vessels
Supporting Profiles#
In support of these five thematic types above, these cross cutting types and properties were
selected for attention.  They represent some key patterns people may wish to leverage when
describing their resources.
Spatial Geometry
Services
Term Lists
Languages
Linking to Principles
Identifier Patterns
See also
For OIH the focus is on generic documents which can scope reports, data and other resources.


For OIH the focus is on generic documents which can scope reports, data and other resources.
In those cases where the resources being described are of type Dataset you may wish to review
patterns developed for GeoScience Datasets by the ESIP
Science on Schema community.


Training#
About#
A thematic type to describe potential training activities.  In Schema.org a Course
is a subtype of CreativeWork and LearningResource.
As defined from https://schema.org/Course:
Course: A description of an educational course which may be offered as distinct
instances at which take place at different times or take place at different
locations, or be offered through different media or modes of study. An
educational course is a sequence of one or more educational events and/or
creative works which aims to build knowledge, competence or ability of learners.
We can start by looking at a basic Course description.
Simple Course#
A basic course might simply present the name and description of the course along
with a few other key properties.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@id": "https://example.org/id/course/2",
 6    "@type": "Course",
 7    "courseCode": "SD100",
 8    "name": "Structured Data",
 9    "description": "An introduction to authoring JSON-LD documents for OIH",
10    "provider": {
11        "@type": "Organization",
12        "name": "Example University",


11        "@type": "Organization",
12        "name": "Example University",
13        "@id": "https://grid.ac/institutes/grid.475727.4",
14        "description": "UN Department of Economic and Social Affairs Sustainable Development"
15    }
16}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/training/graphs/course2.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document


Here we can see the emphasized line 7 and lines 10-15 highlighting some
unique types.
courseCode:
The courseCode is used to provide the ID used by the provider for this course.
provider:
The provider is the organization offering the course.
This property is from the CreativeWork supertype.  In this case the provider may
be of type Organization or Person.  For Ocean InfoHub these would be described in
the Experts and Institutions section.
Note
In this case you can see we use a simple @id in the provider property.  You can
see this same @id used in the  Experts and Institutions section.
By doing this, we connect this provider to the Organization described by that document.
As such these will be connected in the graph.  So there is no need to duplicate
the information here.  This is a common graph pattern that allows us to simply
connect resources.   If there was no existing Organization or Person resource you could
simply create one here.   However, you may also find it useful to create a given
resource and link to it in the graph.
Detailed Course#
There are a wide range of properties that can be used to describe a course.
Many of these can be seen at the Course type as
the properties from Course and properties
from LearningResource.


the properties from Course and properties
from LearningResource.
We wont go into the details of each property here, but we will show a couple.
The example below present two.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/",
 4        "endDate": {
 5            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
 6        },
 7        "startDate": {
 8            "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
 9        }
10    },
11    "@id": "https://example.org/id/course/2",
12    "@type": "Course",
13    "courseCode": "SD100",
14    "name": "Structured Data",
15    "description": "An introduction to authoring JSON-LD documents for OIH",
16    "teaches": "JSON-LD",
17    "provider": {
18        "@type": "Organization",
19        "name": "Example University",
20        "@id": "https://grid.ac/institutes/grid.475727.4",
21        "description": "UN Department of Economic and Social Affairs Sustainable Development"
22    },
23    "hasCourseInstance": [
24        {


22    },
23    "hasCourseInstance": [
24        {
25            "@type": "CourseInstance",
26            "courseMode": [
27                "MOOC1",
28                "online"
29            ],
30            "endDate": "2019-03-21",
31            "startDate": "2019-02-15",
32            "attendee": {
33                "@type": "Person",
34                "name": "Jane Doe",
35                "jobTitle": "Professor",
36                "telephone": "(425) 123-4567",
37                "url": "http://www.janedoe.com",
38                "identifier": {
39                    "@id": "ID_value_string",
40                    "@type": "PropertyValue",
41                    "propertyID": "This can be text or URL for an ID like ORCID",
42                    "url": "https://foo.org/linkToPropertyIDPage",
43                    "description": "Optional description of the ID"
44                }
45            }
46        },
47        {
48            "@type": "CourseInstance",
49            "courseMode": [
50                "MOOC2",
51                "online"
52            ],
53            "endDate": "2019-05-21",


52            ],
53            "endDate": "2019-05-21",
54            "startDate": "2019-04-15"
55        }
56    ]
57}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/training/graphs/course1.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Line 16 shows the teaches property.  It
should be noted while this propery can point to simple text, it is


should be noted while this propery can point to simple text, it is
also possible to leverage DefinedTerm.  This
means a controlled vocabulary can be used to describe what the course
teaches.  Ocean InfoHub provides some more information and links to further
information on defined term in
the Keywords and Defined Terms section.
Lines 23-56 show using a hasCourseInstance
property to show instances where this course is being taught.  Also of note
in this example are the lines 4-9 in the context where we can type the
endDate and startDate as type dateTime.  By doing this we must provide the
dates in a format that is in line with the [XML Datatype] and in particular the
ISO 8601 Data and Time Formats.
By doing this we can then later conduct searches on the graph that use date ranges
to allow us to find courses, or any resources, that are being taught in a
given time period.
References#
RDA Education and Training on handling of research data IG
DC Tabular Application Profiles (DC TAP) - Primer
https://www.w3.org/TR/xmlschema11-2/
Use YYYY-MM-DDThh:mm:ss or YYYY-MM-DD
http://www.marinetraining.eu/
Example page
https://oceanexpert.org/
Example page
OCTO
https://oceansummerschools.iode.org/


Example page
OCTO
https://oceansummerschools.iode.org/
https://octogroup.org/webinars/
https://catalogue.odis.org/search/type=16
https://clmeplus.org/


Languages#
About#
JSON-LD fully support the identification of the language types.  For the canonical
guide refernece JSON-LD 1.1 Language-indexing section.
Properties such as label, description, keyword and others can be
extended in the context with a container language attribute notation.
For example:
{
  "@context": "https://schema.org/",
  "@type": "Person",
  "name": {"@value": "Jane Doe","@language": "en"},
  "jobTitle": "Professor",
  "telephone": "(425) 123-4567",
  "url": "http://www.janedoe.com"
}
Shows the name Jane Doe as typed english.
Use standard language codes (fr, es, en, de, etc) to
be used when describing these properties.   A list of codes can be seen
at the [Online Browsing Platform (OBP)](https://www.iso.org/obp/ui/#search and)
and Popular standards ISO 3166 Country Codes.
Additional use the 2-letter codes is demonstrated below.
 1{
 2    "@context": {
 3      "vocab": "http://example.com/vocab/",
 4      "label": {
 5        "@id": "vocab:label",
 6        "@container": "@language"


6        "@container": "@language"
 7      }
 8    },
 9    "@id": "http://example.com/queen",
10    "label": {
11      "en": "The Queen",
12      "de": [ "Die Königin", "Ihre Majestät" ]
13    }
14  }
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/languages/graphs/language.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document


Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
In graph space the resulting triples from the above are:
<http://example.com/queen> <http://example.com/vocab/label> "Die Königin"@de .
<http://example.com/queen> <http://example.com/vocab/label> "Ihre Majestät"@de .
<http://example.com/queen> <http://example.com/vocab/label> "The Queen"@en .
with language encoding attributes in place.  These can be used in
searching and result filters.
Note, this can cause issues in query space since the concept of
"Semua orang dilahirkan merdeka dan mempunyai martabat dan hak-hak yang sama.
Mereka dikaruniai akal dan hati nurani dan hendaknya bergaul satu
sama lain dalam semangat persaudaraan."
and
"Semua orang dilahirkan merdeka dan mempunyai martabat
dan hak-hak yang sama. Mereka dikaruniai akal dan hati nurani
dan hendaknya bergaul satu sama lain dalam semangat persaudaraan."@id


are different and so care must be taken the creation of the SPARQL
queries not to accidentally imposed implicate filters through the use
of language types.
When trying to note the language of a distribution, the approach is a bit different.
Here we are not noting the encoding of the literal value in a record. Rather, we are
providing information about a remote resource.  So for example:
"distribution": [
    {
      "@type": "DataDownload",
      "contentUrl": "https://www.example-data-repository.org/dataset/3300/data/larval-krill.tsv",
      "encodingFormat": "text/tab-separated-values",
      "datePublished": "2010-02-03",
      "inLanguage": "de"
    }
  ],
The above snippet is using the schema.org/inLanguage property to note the resources is in German.
Multiple distributions with multiple languages would look like
"distribution": [
    {
      "@type": "DataDownload",
      "contentUrl": "https://www.example-data-repository.org/dataset/3300/data/larval-krill_de.tsv",
      "encodingFormat": "text/tab-separated-values",
      "datePublished": "2010-02-03",
      "inLanguage": "de"
    },
   {


"inLanguage": "de"
    },
   {
      "@type": "DataDownload",
      "contentUrl": "https://www.example-data-repository.org/dataset/3300/data/larval-krill_en.tsv",
      "encodingFormat": "text/tab-separated-values",
      "datePublished": "2010-02-03",
      "inLanguage": "en"
    }
  ],
There is also the schema.org/knowsLanguage for use on other types like Person and Organization.
There you could use the short form like:
"knowsLanguage" : "de"
or a more detailed approach like:
"knowsLanguage" : {
      "@type": "Language",
      "name": "Spanish",
      "alternateName": "es"
    }


Licenses#
Schema.org License#
https://schema.org/license
URL
CreativeWork
License as URL - Good#
{
  "@context": "https://schema.org/",
  "license": "https://creativecommons.org/licenses/by/4.0/"
}
License as CreativeWork - Better?#
{
  "@context": "https://schema.org/",
  "license": {
    "@type": "CreativeWork",
    "name": "Creative Commons Attribution 4.0",
    "url": "https://creativecommons.org/licenses/by/4.0/"
  }
}
License as SPDX URL - Best#
Use a simple URL
SPDX creates URLs for many licenses including those that don’t have URLs
From a source that harvesters can rely on (e.g. use URL to lookup more information about the license)
{
  "@context": "https://schema.org/",
  "license": "https://spdx.org/licenses/CC-BY-4.0"
}
OR, include both the SPDX and the Creative Commons URLs in an array:
{
  "@context": "https://schema.org/",
  "license": ["https://spdx.org/licenses/CC-BY-4.0", "https://creativecommons.org/licenses/by/4.0/"]
}


Spatial Geometry#
About#
For spatial geometry Ocean InfoHub guidance will be to use the OGC GeoSPARQL
vocabulary to express geometry using Well Known Text (WKT).  The schema.org spatial types and propeties are not well
defined and difficult at times to reliably translate to geometries for use in more Open Geospatial Consortium (OGC)
environments.
Simple GeoSPARQL WKT#
The following is a simple example of how to embed a WKT string via GeoSPARQL into a JSON-LD record.
Well Know Text (WKT) is a OGC standard referenced at: https://www.ogc.org/standards/wkt-crs.
A more accessible description and set of examples can be found at WikiPedia:
Well-known text representation of geometry.
 1{
 2    "@context": {
 3      "@vocab": "https://schema.org/",
 4      "geosparql": "http://www.opengis.net/ont/geosparql#"
 5    },
 6    "@id": "https://example.org/id/XYZ",
 7    "@type": "Dataset",
 8    "name": "Data set name",
 9    "geosparql:hasGeometry": {
10        "@type": "http://www.opengis.net/ont/sf#Point",


10        "@type": "http://www.opengis.net/ont/sf#Point",
11        "geosparql:asWKT": {
12            "@type": "http://www.opengis.net/ont/geosparql#wktLiteral",
13            "@value": "POINT(-76 -18)"
14        },
15        "geosparql:crs": {
16            "@id": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
17        }
18    }
19}
Line 4 declare the GeoSPARQL prefix for the vocabulary that we will leverage in this document.
Lines 9-17 are the GeoSPARQL node and property definitions.  In this case our type is a simple
point geometry.  We then go on to declare the asWKT with a type and value.  The value
is our actual WKT string for our geometry.   We can further
declare the coordinate reference system (CRS) of the geometry using the crs property.
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/spatial/graphs/basic.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
WKT Bounding Box#
Note that WKT doesn’t directly have a bounding box, in that case you
would need to use a polygon.  The following is an example of a WKT string:


would need to use a polygon.  The following is an example of a WKT string:
POLYGON((45.066730529474505 2.6430807905900235,47.395832091974505 2.6430807905900235,47.395832091974505 0.3588601145746598,45.066730529474505 0.3588601145746598,45.066730529474505 2.6430807905900235))
This following the pattern:
'POLYGON(x1 y1, x1 y2, x2 y2, x2 y1, x1 y1)'
Classic Schema.org#
Ocean InfoHub only recommends the use of Schema.org spatial geometries in
the case where a provider wishes to be properly indexed by Google and to have the
spatial information used by Google for maps.  Note, the lack of spatial information will
not prevent Google from indexing your resources.
Schema.org spatial geometries are not well defined in comparison to OGC standards and
recommendations.  Also, converting from Schema.org spatial to geometries in WKT or GeoJSON
can be problematic.  There are inconsistencies with
Schema.org guidance for textual geometry representation and that of Well
Known Text (WKT).
That said, if you desire to leverage Schema.org geometries an example follows.  This


That said, if you desire to leverage Schema.org geometries an example follows.  This
is a simple example of the existing Schema.org pattern for a lat long value.   There is the
pending GeospatialGeometry which is a
type Intangible (and not Place referenced by spatialCoverage).  This will be a
subtype of GeoShape.
Schema.org spatial relations are guided by DE-9IM.
 1{
 2  "@context": {
 3    "@vocab": "https://schema.org/"
 4  },
 5  "@id": "https://example.org/id/XYZ",
 6  "@type": "Dataset",
 7  "name": "Data set name",
 8  "spatialCoverage": {
 9    "@type": "Place",
10    "geo": {
11      "@type": "GeoCoordinates",
12      "latitude": 39.3280,
13      "longitude": 120.1633
14    }
15  }
16}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/spatial/graphs/sos.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Option review, SOS Issue 105#
There are several approaches to expressing spatial geometries in JSON-LD.
While Ocean InfoHub will recommend the use of GeoSPARQL, it is worth noting that there
are alternative and solid cases for using them
One such case could be the case where your WKT geometry string are highly detailed and
as a result quite long.  These might result in both very large JSON-LD documents that are hard to


read and maintain.  It may also be that this imparts a performance penalty in your GeoSPARQL
queries.
It may be tha that you simplify your WKT geometry strings to a more basic form.  Then link out
to the detailed geometry in a separate document.   The simplified WKT (or Schema.org spatial)
make the documents smaller and easier to read and could help query performance.  The resource
can then point to a dereferencable URL for the detailed geometry.
ref Selfie:  When linking out to complex geometries we recommend following: https://docs.ogc.org/per/20-067.html
From the referenced SOS issue 105:
 1{
 2    "@context": {
 3        "@version": 1.1,
 4        "geoblob": {
 5            "@id": "http://example.com/vocab/json",
 6            "@type": "@json"
 7        },
 8        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
 9        "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
10        "xsd": "http://www.w3.org/2001/XMLSchema#",
11        "description": "http://igsn.org/core/v1/description",


11        "description": "http://igsn.org/core/v1/description",
12        "geosparql": "http://www.opengis.net/ont/geosparql#",
13        "schema": "https://schema.org/"
14    },
15    "@id": "https://samples.earth/id/do/bqs2dn2u6s73o70jdup0",
16    "@type": "http://igsn.org/core/v1/Sample",
17    "description": "A fake ID for testing",
18    "schema:subjectOf": [
19        {
20            "schema:url": "https://samples.earth/id/do/bqs2dn2u6s73o70jdup0.geojson",
21            "@type": "schema:DigitalDocument",
22            "schema:format": [
23                "application/vnd.geo+json"
24            ],
25            "schema:conformsTo": "https://igsn.org/schema/spatial.schema.json"
26        }
27    ],
28    "geosparql:hasGeometry": {
29        "@id": "_:N98e75cacc29f40deb555eb583cb162dc",
30        "@type": "http://www.opengis.net/ont/sf#Point",
31        "geosparql:asWKT": {


31        "geosparql:asWKT": {
32            "@type": "http://www.opengis.net/ont/geosparql#wktLiteral",
33            "@value": "POINT(-76 -18)"
34        },
35        "geosparql:crs": {
36            "@id": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
37        }
38    },
39    "geoblob": {
40        "type": "GeometryCollection",
41        "geometries": [{
42            "type": "Point",
43            "coordinates": [-76, -18]
44        }]
45    },
46    "schema:spatialCoverage": {
47        "@type": "schema:Place",
48        "schema:geo": {
49          "@type": "schema:GeoCoordinates",
50          "schema:latitude": -18,
51          "schema:longitude": -76
52        }
53      }
54}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/spatial/graphs/issue105.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
References#
GeoAPI at GitHub
Science on Schema Issue 105
Leverages subjectOf to connect to a Thing / CreativeWork
https://www.unsalb.org/
https://www.un.org/geospatial/
schema.org/spatial
schema.org/GeospatialGeometry
SOS patern follows:
spatialCoverage -> Place -> geo -> GeoCoordinates OR GeoShape
Some groups are using GeoNode
schema.org issues
ICAN & Schema.org
OGC SELFIE
Think broad


schema.org issues
ICAN & Schema.org
OGC SELFIE
Think broad
Science on Schema spatial for dataset guidance


Service#
About#
This section will provide information on the service type.  This is not
one of the main OIH types.  However, we will provide guidance here on describing
services using schema.org.
It should be noted that this might be a simple link to an OpenAPI or some
other descriptor document.  Also, schema.org is not rich enough for complex
descriptions and itself borrows from the Hydra
vocabulary.  It may be required to leverage Hydra if complex descriptions are
needed.
The graph describes a service than can be invoked with:
curl --data-binary "@yourfile.jpg" -X POST https://us-central1-top-operand-112611.cloudfunctions.net/function-1
This with POST a jpeg to the service and get back a simple text response with some information
about the image.
 1{
 2  "@context": {
 3    "@vocab": "https://schema.org/"
 4  },
 5  "@type": "Service",
 6  "@id": "URL:  Optional. A URL that resolves to *this* JSON-LD document, NOT the URL of the Service that this JSON-LD document describes. To link to the Service itself, please use 'url' and/or 'identifier')",
 7  "aggregateRating": {"@type": "https://schema.org/aggregateRating"},


8  "areaServed": [
 9    "Text: The geographic area where the service is provided.",
10    {"@type": "https://schema.org/Place"},
11    {"@type": "https://schema.org/GeoShape"},
12    {"@type": "https://schema.org/AdministrativeArea"}
13  ],
14  "audience": {"@type": "https://schema.org/Audience"},
15  "availableChannel": {"@type": "https://schema.org/ServiceChannel"},
16  "award": "Text: An award won by or for this service.",
17  "brand": [
18    "Text: The brand(s) associated with the service, or the brand(s) maintained by an organization or business person.",
19    {"@type": "https://schema.org/Brand"},
20    {"@type": "https://schema.org/Organization"}
21  ],
22  "broker": [
23  {"@type": "https://schema.org/Person"},
24  {"@type": "https://schema.org/Organization"}
25  ],
26  "category": [
27    "Text: A category for the service.",
28    "URL",
29    {"@type": "https://schema.org/CategoryCode"},


29    {"@type": "https://schema.org/CategoryCode"},
30    {"@type": "https://schema.org/PhysicalActivityCategory"},
31    {"@type": "https://schema.org/Thing"}
32  ],
33  "hasOfferCatalog": "https://schema.org/OfferCatalog",
34  "hoursAvailable": "https://schema.org/OpeningHoursSpecification",
35  "isRelatedTo": [
36    {"@type": "https://schema.org/Product"},
37    {"@type": "https://schema.org/Service"}
38  ] ,
39  "isSimilarTo": [
40    {"@type": "https://schema.org/Product"},
41    {"@type": "https://schema.org/Service"}
42  ] ,
43  "logo": [
44    {"@type": "https://schema.org/ImageObject"},
45    "URL"
46  ] ,
47  "offers": [
48    {"@type": "https://schema.org/Demand"},
49    {"@type": "https://schema.org/Offer"}
50  ] ,
51  "provider": [
52    "Text: The service provider, service operator, or service performer; the goods producer. Another party (a seller) may offer those services or goods on behalf of the provider.",


53    {"@type": "https://schema.org/Person"},
54    {"@type": "https://schema.org/Organization"}
55  ],
56  "providerMobility": "Text: Indicates the mobility of a provided service (e.g. 'static', 'dynamic').",
57  "review": {"@type": "https://schema.org/Review"},
58
59  "serviceOutput":  {"@type": "https://schema.org/Thing"},
60  "serviceType":  [
61    "Text: Human-readable terms of service documentation",
62    {"@type": "https://schema.org/GovernmentBenefitsType"}
63  ],
64  "slogan": "Text: A slogan or motto associated with the item.",
65  "termsOfService": [
66    "Text: Human-readable terms of service documentation",
67    {"@type": "https://schema.org/Url"}
68  ],
69
70
71  "additionalType": [
72    "Text: An additional type for the item, typically used for adding more specific types from external vocabularies in microdata syntax.",
73    "URL"
74  ],
75  "alternateName": "Text: An alternative name for this Thing.",
76  "description": "Text: Free text which describes this Thing.",


76  "description": "Text: Free text which describes this Thing.",
77  "disambiguatingDescription": "Text: A sub property of description. A short description of the item used to disambiguate from other, similar items. Information from other properties (in particular, name) may be necessary for the description to be useful for disambiguation",
78  "identifier": [
79      {"@type": "https://schema.org/PropertyValue"},
80      "Text - The identifier property represents any kind of identifier for any kind of Thing, such as ISBNs, GTIN codes, UUIDs etc. Schema.org provides dedicated properties for representing many of these, either as textual strings or as URL (URI) links. See background notes for more details.",
81      "URL"
82  ],
83  "image": [
84      "URL",
85      {"@type": "https://schema.org/ImageObject"}
86  ],
87  "mainEntityOfPage": [
88    "URL",
89    {"@type": "https://schema.org/CreativeWork"}
90  ],
91  "name": "Text: The name of the item.",
92  "potentialAction": {"@type": "https://schema.org/Action"},
93  "sameAs": "URL",
94  "subjectOf": "URL",


93  "sameAs": "URL",
94  "subjectOf": "URL",
95  "url": "URL - the URL to the item described by this JSON-LD document"
96}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/services/graphs/service.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/tmp/ipykernel_3668524/3307491376.py in <module>
     16
     17 compacted = jsonld.compact(doc, context)
---> 18 jbutils.show_graph(compacted)
~/src/Projects/OIH/odis-arch/bookRev1/lib/jbutils.py in show_graph(doc, size)
     44     for edge in rdf:
     45         subj = short_name(edge['subject'])
---> 46         obj = short_name(edge['object'])


---> 46         obj = short_name(edge['object'])
     47         pred = short_name(edge['predicate'])
     48         if subj and obj and pred:
~/src/Projects/OIH/odis-arch/bookRev1/lib/jbutils.py in short_name(value, max_length)
     22             # If the URL is too long, hide it
     23             if len(short_url) > max_length:
---> 24                 pieces = split_uri(short_url)
     25                 return join_uri(pieces[0], '...')
     26             else:
NameError: name 'split_uri' is not defined
References#
https://schema.org/docs/actions.html
https://schema.org/Action
https://www.w3.org/TR/web-share/
https://www.hydra-cg.com/spec/latest/core/


Experts and Institutions#
About#
This thematic type provides a way to describe the experts and institutions.
In this case the following definitions are used:
Expert:  A person who has a deep understanding of a particular subject area.
Institution: A group of people working together to provide a particular service.
Example: Person Graph#
The following graph present a basic record we might use for a person.
We will break down some of the key properties used in this graph.
As Ocean InfoHub is levergaing Schema.org we are
using schema.org/Person for this type.
Any of the properties of Person seen there are valid to use in such a record.
While publishers are free to use as many elements as they wish, our goal
with this documentation is provide a simple example that address some of the search
and discovery goals of OIH along with those properties most useful in the linking
of resources between OIH participants.
 1{
 2  "@context": {
 3    "@vocab": "https://schema.org/"
 4  },
 5  "@id": "https://example.org/id/x",
 6  "@type": "Person",
 7  "name": "Jane Doe",
 8  "jobTitle": "Professor",
 9  "workLocation": {
10    "@type": "Place",


9  "workLocation": {
10    "@type": "Place",
11    "address": "54 Ocean Drive, 23521 Ocean City, CountryName",
12    "name": "Place name"
13  },
14  "telephone": "(425) 123-4567",
15  "url": "http://www.janedoe.com",
16  "knowsAbout": [
17    {
18      "@type": "Text",
19      "description": "Invasive species in brackish water"
20    },
21    {
22      "@type": "URL",
23      "url": "https://www.wikidata.org/wiki/Q183368"
24    },
25    {
26      "@id": "https://example.org/id/course/x",
27      "@type": "Course",
28      "description": "In this course ...",
29      "url": "URL to the course"
30    }
31  ],
32  "identifier": {
33    "@id": "https://orcid.org/0000-0002-2257-9127",
34    "@type": "PropertyValue",
35    "propertyID": "https://registry.identifiers.org/registry/orcid",


35    "propertyID": "https://registry.identifiers.org/registry/orcid",
36    "url": "https://orcid.org/0000-0002-2257-9127",
37    "description": "Optional description of this record..."
38  },
39  "nationality": [
40    {
41      "@type": "Country",
42      "name": "Fiji"
43    },
44    {
45      "@type": "DefinedTerm",
46      "url": "https://unece.org/trade/cefact/unlocode-code-list-country-and-territory",
47      "inDefinedTermSet": "UN/LOCODE Code List by Country and Territory",
48      "name": "Fiji",
49      "termCode": "FJ"
50    }
51  ],
52  "knowsLanguage": {
53    "@type": "Language",
54    "name": "Spanish",
55    "alternateName": "es"
56  }
57}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../book/thematics/expinst/graphs/person.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Details: Identifier#
For each profile there are a few key elements we need to know about.  One
key element is what the authoritative reference or canonical identifier is for
a resource.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))


import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/person.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@type":     "Person",
  "identifier": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {


{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/x",
    "@type": "Person",
    "identifier": {
        "@id": "https://orcid.org/0000-0002-2257-9127",
        "@type": "PropertyValue",
        "description": "Optional description of this record...",
        "propertyID": "https://registry.identifiers.org/registry/orcid",
        "url": "https://orcid.org/0000-0002-2257-9127"
    }
}
Details: nationality#
Nationality provide connections to languages a person is
connected with.  The property, schema.org/nationality,
is used to present that.  In the OIH we need to state what the semantics of
nationality are for our use case.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/person.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@type":     "Person",
  "nationality": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },


"@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/x",
    "@type": "Person",
    "nationality": [
        {
            "@type": "Country",
            "name": "Fiji"
        },
        {
            "@type": "DefinedTerm",
            "inDefinedTermSet": "UN/LOCODE Code List by Country and Territory",
            "name": "Fiji",
            "termCode": "FJ",
            "url": "https://unece.org/trade/cefact/unlocode-code-list-country-and-territory"
        }
    ]
}
Note
The visual above demonstrates an issue that can be seen in several of the graph.  Where we
don’t use an @id the graph will be represented as a “blank node”.
These will be uniquely identified in the graph, however, in the construction of the visual
this is a common blank node and results in the double arrows pointing to an underscore.
This is a visualization issue and not a proper representation of the graph structure.
Details: knowsLanguage#
Knows about provide connections to languages a person is
connected with.  The property, schema.org/knowsLanguage,
is used to present that.   Multiple languages can be expressed using the JSON


is used to present that.   Multiple languages can be expressed using the JSON
array [] syntax.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/person.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@type":     "Person",
  "knowsLanguage": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)


print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/x",
    "@type": "Person",
    "knowsLanguage": {
        "@type": "Language",
        "alternateName": "es",
        "name": "Spanish"
    }
}
Details: Knows About#
Knows about provide connections to resources a person is
connected with.  The property, schema.org/knowsAbout,
can connect a Person or Organization to Text, URL or any Thing type.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld


from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/person.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@type":     "Person",
  "knowsAbout": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document


Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/x",
    "@type": "Person",
    "knowsAbout": [
        {
            "@type": "Text",
            "description": "Invasive species in brackish water"
        },
        {
            "@type": "URL",
            "url": "https://www.wikidata.org/wiki/Q183368"
        },
        {
            "@id": "https://example.org/id/course/x",
            "@type": "Course",
            "description": "In this course ...",
            "url": "URL to the course"
        }
    ]
}
Example: Institution Graph#
Here we have an example of an data graph for type schema.org/Organization.
For the identifier we are using the a GRID, but this could also be something like a ROR.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@id": "https://index.example.org/id/org/x",


5    "@id": "https://index.example.org/id/org/x",
 6    "@type": "Organization",
 7    "address": {
 8        "@type": "PostalAddress",
 9        "addressLocality": "Paris, France",
10        "postalCode": "F-75002",
11        "streetAddress": "38 avenue de l'Opera"
12    },
13    "location": {
14        "@type": "Place",
15        "address": "38 avenue de l'Opera, F-75002, Paris, France",
16        "name": "Paris"
17    },
18    "email": "secretariat(at)example.org",
19    "name": "Organization X",
20    "description": "Description of org ...",
21    "telephone": "( 33 1) 42 68 53 00",
22    "url": "https://example.org/",
23    "member": [
24        {
25            "@id": "https://example.org/id/org/1",
26            "@type": "Organization",
27            "name": "Organization A",
28            "description": "Org A is a potential parent organization of Org X"
29        },
30        {


29        },
30        {
31            "@id": "https://orcid.org/0000-0002-2257-9127",
32            "@type": "Person"
33        }
34    ],
35    "identifier": {
36        "@id": "https://grid.ac/institutes/grid.475727.4",
37        "@type": "PropertyValue",
38        "description": "UN Department of Economic and Social Affairs Sustainable Development",
39        "propertyID": "https://registry.identifiers.org/registry/grid",
40        "url": "https://grid.ac/institutes/grid.475727.4"
41    }
42}
On the property membership#
Line 18-29 show the inclusion of a schema.org/member
property.  There are issues to note here both for consumers (aggregators) and
providers (publishers).   The Person type is show connected simply on a type and
id.  This provides the cleanest connection.  If a member is added by type and id, as
in the case of the “Organization A” link, there is the problem of additional triples
being added.  Here, the name and description properties are going to add triples to the
OIH KG.  In so doing, we run the risk or adding potentially un-authoritative information.


The aggregator doesn’t know if triples here are or are not provided by an actor
authoritative for those properties.  This could be addresses with framing or validation
workflows, or ignored.  The prov elements stored could be leveraged to later track
down sources, but don’t provide further information on the issue of authority.
It is recommended that best practice is to attempt to link only on ids (with a type in
all cases) where possible.  If you are connecting with a type, do not provide additional
properties.  In cases where such an id can not be provided, you may wish to fill out
basic properties you can provide with confidence.
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/organization.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document


Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Details: Indentifier#
For each profile there are a few key elements we need to know about.  One
key element is what the authoritative reference or canonical identifier is for
a resource.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/expinst/graphs/organization.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@requireAll": "true",
  "@type":     "Organization",
  "identifier": ""
}
context = {


"identifier": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://index.example.org/id/org/x",
    "@type": "Organization",
    "identifier": {
        "@id": "https://grid.ac/institutes/grid.475727.4",
        "@type": "PropertyValue",
        "description": "UN Department of Economic and Social Affairs Sustainable Development",
        "propertyID": "https://registry.identifiers.org/registry/grid",


"propertyID": "https://registry.identifiers.org/registry/grid",
        "url": "https://grid.ac/institutes/grid.475727.4"
    }
}
References#
schema:Person
scheme:Organization
Science on Schema Repository
https://oceanexpert.org/
Example page expert
Example page institution
Ocean Expert: reference: Adam Leadbetter


Vessels#
About#
OIH is exploring how we might leverage schema.org to describe research vessels.
Note that schema.org is a very broad vocabulary and as such specific concepts
like research vessel is not well aligned to current types.
In Schema.org the type Vehicle is described as a device that is designed
or used to transport people or cargo over land, water, air, or through space.
We have used this broad scoping to cover research vessels.  We could go on to
connect this type then to a descriptive property in a concept such as
the WikiData entry for Research Vessel, Q391022.
We may also wish to leverage some of the approaches in Keywords and Defined Terms.
Our goal is to use schema.org as a simple upper level vocabulary that allows
us to describe research vessels in a simple manner and then connect to more
detailed information on them.
So the goal here is to show how we can use schema.org as a discovery layer
and then link more directly to detailed institutional metadata records.
This may also leverage the approaches similar to what is shown in
the Publishing Principles resources.
Observing Infrastructure in general represents an interesting challenge.  A
specified infrastructure could be referenced as a ResearchProject within Schema.org,
though other types would be explored.  One could also build off the base Thing class,
parent to all Schema.org types, then leverage the property schema.org/instrument, itself


parent to all Schema.org types, then leverage the property schema.org/instrument, itself
of type Thing.  This approach provides an initial starting point to build out the
approach.
It should be noted that schema.org/Observation also exists but can only
currently be used with the property schema.org/diseaseSpreadStatistics.
However, if seen useful, there is the potential to connect Observation back to a
type of Infrastructure that does not currently exist in Schema.org but could be
proposed.
Addressing the challenge of Observation Infrastructure, and
potentially revisiting the current OIH type Vessel, may involve engagement with
Schema.org itself, something they encourage.
 1{
 2    "@context": {
 3        "@vocab": "https://schema.org/"
 4    },
 5    "@id": "https://example.org/id/X",
 6    "@type": "Vehicle",
 7    "name": "JOIDES Resolution",
 8    "identifier": {
 9        "@id": "https://example.org/id/vessel/X",
10        "@type": "PropertyValue",
11        "propertyID": "https://en.wikipedia.org/wiki/IMO_number",
12        "url": "https://example.org/id/vessel/X",
13        "description": "Vessel ID "
14    },


13        "description": "Vessel ID "
14    },
15    "countryOfLastProcessing": "Angola",
16    "countryOfOrigin": {
17        "@type": "Country",
18        "name": "Fiji"
19    },
20    "additionalProperty": {
21        "@id": "ID_value_string",
22        "@type": "PropertyValue",
23        "propertyID": "https://en.wikipedia.org/wiki/IMO_number",
24        "url": "https://foo.org/linkToPropertyIDPage",
25        "description": "Any additional properties for the vessel"
26    },
27    "subjectOf": {
28        "@type": "DataDownload",
29        "name": "external-metadata.xml",
30        "description": "Metadata describing the vessel",
31        "encodingFormat": [
32            "application/xml",
33            "https://foo.org/ship01"
34        ],
35        "dateModified": "2019-06-12T14:44:15Z"
36    }
37}
import json
from pyld import jsonld
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils


sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/vessels/graphs/ship.json") as dgraph:
    doc = json.load(dgraph)
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
jbutils.show_graph(compacted)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/tmp/ipykernel_3668912/1146838844.py in <module>
     17
     18 compacted = jsonld.compact(doc, context)
---> 19 jbutils.show_graph(compacted)
~/src/Projects/OIH/odis-arch/bookRev1/lib/jbutils.py in show_graph(doc, size)
     45         subj = short_name(edge['subject'])
     46         obj = short_name(edge['object'])
---> 47         pred = short_name(edge['predicate'])
     48         if subj and obj and pred:
     49             # Apply different styles to the nodes based on whether they're
~/src/Projects/OIH/odis-arch/bookRev1/lib/jbutils.py in short_name(value, max_length)
     22             # If the URL is too long, hide it


22             # If the URL is too long, hide it
     23             if len(short_url) > max_length:
---> 24                 pieces = split_uri(short_url)
     25                 return join_uri(pieces[0], '...')
     26             else:
NameError: name 'split_uri' is not defined
Details: Indentifier#
For each profile there are a few key elements we need to know about.  One
key element is what the authoritative reference or canonical identifier is for
a resource.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/vessels/graphs/ship.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@requireAll": "true",
  "@type":     "Vehicle",


"@requireAll": "true",
  "@type":     "Vehicle",
  "identifier": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/X",
    "@type": "Vehicle",
    "identifier": {
        "@id": "https://example.org/id/vessel/X",
        "@type": "PropertyValue",
        "description": "Vessel ID ",
        "propertyID": "https://en.wikipedia.org/wiki/IMO_number",


"propertyID": "https://en.wikipedia.org/wiki/IMO_number",
        "url": "https://example.org/id/vessel/X"
    }
}
Details: subjectOf#
Like SOS, we are recommending the use of subjectOf to link a simple
Schema.org type to a more detailed metadata description record.  This
allows us to use the easy discovery layer in Schema.org but connect to
domain specific metadata records.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/vessels/graphs/ship.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@requireAll": "true",
  "@type":     "Vehicle",
  "subjectOf": ""
}
context = {
    "@vocab": "https://schema.org/",
}


}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/X",
    "@type": "Vehicle",
    "subjectOf": {
        "@type": "DataDownload",
        "dateModified": "2019-06-12T14:44:15Z",
        "description": "Metadata describing the vessel",
        "encodingFormat": [
            "application/xml",
            "https://foo.org/ship01"
        ],


"application/xml",
            "https://foo.org/ship01"
        ],
        "name": "external-metadata.xml"
    }
}
References#
ICES
POGO
EurOcean
https://vocab.nerc.ac.uk/search_nvs/C17/
SeaDataNet
Marine Facilities Planner
EuroFleets
Identifiers to use include NOCD Code, Call Sign, ICES Shipcode, MMSI Code, IMO Code


Projects#
About#
Project: An enterprise (potentially individual but typically
collaborative), planned to achieve a particular aim. Use properties from
Organization, subOrganization/parentOrganization to indicate project sub-structures.
Research Project#
This is what a basic research project data graph might look like.  We have
the full record below, but this shows some of the basics we would be
looking for.
This type is based on the Schema.org type Project which
has a sub-type of ResearchProject.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/projects/graphs/proj.json") as dgraph:
    doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@requireAll": "true",
  "@type":     "ResearchProject",
  "legalName": "",
  "name": "",


"legalName": "",
  "name": "",
  "url": "",
  "description": "",
  "identifier": {}
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/resproj/X",
    "@type": [
        "ResearchProject",
        "PropertyValue"
    ],
    "description": "Repo description ... ",
    "identifier": {
        "@id": "https://grid.ac/institutes/grid.475727.4",


"@id": "https://grid.ac/institutes/grid.475727.4",
        "@type": "PropertyValue",
        "description": "UN Department of Economic and Social Affairs Sustainable Development",
        "propertyID": "https://registry.identifiers.org/registry/grid",
        "url": "https://grid.ac/institutes/grid.475727.4"
    },
    "legalName": "Example Data Repository",
    "name": "ExDaRepo",
    "url": [
        "https://dio.org/id/XYZ",
        "https://www.example-data-repository.org"
    ]
}
Details: Identifier#
For each profile there are a few key elements we need to know about.  One
key element is what the authoritative reference or canonical identifier is for
a resource.
import json
from rdflib.extras.external_graph_libs import rdflib_to_networkx_multidigraph
from rdflib.extras.external_graph_libs import rdflib_to_networkx_graph
from pyld import jsonld
import graphviz
import os, sys
currentdir = os.path.dirname(os.path.abspath(''))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir)
from lib import jbutils
with open("../../../odis-in/dataGraphs/thematics/projects/graphs/proj.json") as dgraph:


doc = json.load(dgraph)
frame = {
  "@context": {"@vocab": "https://schema.org/"},
  "@explicit": "true",
  "@requireAll": "true",
  "@type":     "ResearchProject",
  "identifier": ""
}
context = {
    "@vocab": "https://schema.org/",
}
compacted = jsonld.compact(doc, context)
framed = jsonld.frame(compacted, frame)
jd = json.dumps(framed, indent=4)
print(jd)
jbutils.show_graph(framed)
Fontconfig error: "/etc/fonts/conf.d/30-0-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/60-open-sans.conf", line 1: Extra content at the end of the document
Fontconfig error: "/etc/fonts/conf.d/62-google-crosextra-caladea-fonts.conf", line 1: Extra content at the end of the document
{
    "@context": {
        "@vocab": "https://schema.org/"
    },
    "@id": "https://example.org/id/resproj/X",
    "@type": [
        "ResearchProject",
        "PropertyValue"
    ],
    "identifier": {


"ResearchProject",
        "PropertyValue"
    ],
    "identifier": {
        "@id": "https://grid.ac/institutes/grid.475727.4",
        "@type": "PropertyValue",
        "description": "UN Department of Economic and Social Affairs Sustainable Development",
        "propertyID": "https://registry.identifiers.org/registry/grid",
        "url": "https://grid.ac/institutes/grid.475727.4"
    }
}
Full Research Project#
Here is what our full record looks like.  We have added in several
more nodes to cover things like funding source, policy connections,
spatial area served and parent organization.
  1{
  2  "@context": {
  3    "@vocab": "https://schema.org/"
  4  },
  5  "@type": "ResearchProject",
  6  "@id": "https://example.org/id/resproj/X",
  7  "legalName": "Example Data Repository",
  8  "name": "ExDaRepo",
  9  "url": "https://www.example-data-repository.org",
 10  "description": "Repo description ... ",
 11  "logo": {
 12    "@type": "ImageObject",


11  "logo": {
 12    "@type": "ImageObject",
 13    "url": "https://www.example-data-repository.org/logo.jpg"
 14  },
 15  "identifier": {
 16    "@id": "https://grid.ac/institutes/grid.475727.4",
 17    "@type": "PropertyValue",
 18    "description": "UN Department of Economic and Social Affairs Sustainable Development",
 19    "propertyID": "https://registry.identifiers.org/registry/grid",
 20    "url": "https://grid.ac/institutes/grid.475727.4"
 21  },
 22  "contactPoint": {
 23    "@id": "https://www.example-data-repository.org/about-us",
 24    "@type": "ContactPoint",
 25    "name": "Support",
 26    "email": "info@example-data-repository.org",
 27    "url": "https://www.example-data-repository.org/about-us",
 28    "contactType": "customer support"
 29  },
 30  "funder": {
 31    "@type": "FundingAgency",
 32    "@id": "https://dx.doi.org/10.13039/10000001",