Skip to content

Commit

Permalink
Add bounding box property
Browse files Browse the repository at this point in the history
  • Loading branch information
amercader committed Oct 9, 2024
1 parent 4040074 commit 712b804
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 6 deletions.
1 change: 1 addition & 0 deletions ckanext/dcat/profiles/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
RDFS,
DCAT,
DCATAP,
DCATUS,
DCT,
ADMS,
VCARD,
Expand Down
2 changes: 2 additions & 0 deletions ckanext/dcat/profiles/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
DCT = Namespace("http://purl.org/dc/terms/")
DCAT = Namespace("http://www.w3.org/ns/dcat#")
DCATAP = Namespace("http://data.europa.eu/r5r/")
DCATUS = Namespace("http://resources.data.gov/ontology/dcat-us#")
ADMS = Namespace("http://www.w3.org/ns/adms#")
VCARD = Namespace("http://www.w3.org/2006/vcard/ns#")
FOAF = Namespace("http://xmlns.com/foaf/0.1/")
Expand All @@ -30,6 +31,7 @@
"dct": DCT,
"dcat": DCAT,
"dcatap": DCATAP,
"dcatus": DCATUS,
"adms": ADMS,
"vcard": VCARD,
"foaf": FOAF,
Expand Down
50 changes: 49 additions & 1 deletion ckanext/dcat/profiles/dcat_us_3.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from rdflib import Literal
from decimal import Decimal, DecimalException

from rdflib import Literal, BNode

from ckanext.dcat.profiles import (
DCAT,
DCATUS,
DCT,
FOAF,
RDF,
SKOS,
XSD,
)
from ckanext.dcat.utils import resource_uri

Expand Down Expand Up @@ -57,6 +61,21 @@ def graph_from_catalog(self, catalog_dict, catalog_ref):

def _parse_dataset_v3_us(self, dataset_dict, dataset_ref):

g = self.g

# Bounding box
for bbox_ref in g.objects(dataset_ref, DCATUS.geographicBoundingBox):
if not dataset_dict.get("bbox"):
dataset_dict["bbox"] = []
dataset_dict["bbox"].append(
{
"west": self._object_value(bbox_ref, DCATUS.westBoundingLongitude),
"east": self._object_value(bbox_ref, DCATUS.eastBoundingLongitude),
"north": self._object_value(bbox_ref, DCATUS.northBoundingLatitude),
"south": self._object_value(bbox_ref, DCATUS.southBoundingLatitude),
}
)

for distribution_ref in self._distributions(dataset_ref):

# Distribution identifier
Expand Down Expand Up @@ -91,6 +110,35 @@ def _graph_from_dataset_v3_us(self, dataset_dict, dataset_ref):
if name:
g.add((publisher_ref, SKOS.prefLabel, Literal(name)))

# Bounding box
# TODO: we could fall back to spatial or spatial_coverage's bbox/geom
bboxes = self._get_dataset_value(dataset_dict, "bbox")
if bboxes:
for bbox in bboxes:
bbox_ref = BNode()
g.add((dataset_ref, DCATUS.geographicBoundingBox, bbox_ref))
g.add((bbox_ref, RDF.type, DCATUS.geographicBoundingBox))

def add_bounding(predicate, value):
try:
g.add(
(
bbox_ref,
predicate,
Literal(value, datatype=XSD.decimal),
)
)
except (ValueError, TypeError, DecimalException):
g.add((bbox_ref, predicate, Literal(value)))

for item in (
(DCATUS.westBoundingLongitude, bbox["west"]),
(DCATUS.eastBoundingLongitude, bbox["east"]),
(DCATUS.northBoundingLatitude, bbox["north"]),
(DCATUS.southBoundingLatitude, bbox["south"]),
):
add_bounding(item[0], item[1])

for resource_dict in dataset_dict.get("resources", []):

distribution_ref = CleanedURIRef(resource_uri(resource_dict))
Expand Down
17 changes: 17 additions & 0 deletions ckanext/dcat/schemas/dcat_us_full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ dataset_fields:
label: Temporal resolution
help_text: Minimum time period resolvable in the dataset.

- field_name: bbox
label: Geographic Bounding Box
repeating_subfields:

- field_name: west
label: West Longitude

- field_name: east
label: East Longitude

- field_name: north
label: North Latitude

- field_name: south
label: South Latitude
help_text: A geographic bounding box in WGS84 coordinate system (Lat/Long) that describes the spatial extent of the dataset.

- field_name: spatial_coverage
label: Spatial coverage
repeating_subfields:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,39 @@ def test_e2e_dcat_to_ckan(self):
assert resource["access_services"][0]["endpoint_url"] == [
"http://publications.europa.eu/webapi/rdf/sparql"
]

def test_bbox(self):

data = """
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix dcat-us: <http://resources.data.gov/ontology/dcat-us#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix locn: <http://www.w3.org/ns/locn#> .
@prefix gsp: <http://www.opengis.net/ont/geosparql#> .
<https://example.com/dataset1>
a dcat:Dataset ;
dcterms:title "Dataset 1" ;
dcterms:description "This is a dataset" ;
dcterms:publisher <https://example.com/publisher1> ;
dcat-us:geographicBoundingBox [
a dcat-us:GeographicBoundingBox ;
dcat-us:westBoundingLongitude 22.3;
dcat-us:eastBoundingLongitude 10.3;
dcat-us:northBoundingLatitude 50.2;
dcat-us:southBoundingLatitude 20.2;
]
.
"""
p = RDFParser()

p.parse(data, _format="ttl")

datasets = [d for d in p.datasets()]

dataset = datasets[0]

assert dataset["bbox"][0]["west"] == "22.3"
assert dataset["bbox"][0]["east"] == "10.3"
assert dataset["bbox"][0]["north"] == "50.2"
assert dataset["bbox"][0]["south"] == "20.2"
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@

from ckanext.dcat import utils
from ckanext.dcat.profiles import (
RDF,
DCAT,
DCATAP,
DCATUS,
DCT,
ADMS,
XSD,
Expand Down Expand Up @@ -317,7 +316,7 @@ def test_e2e_ckan_to_dcat(self):

# Resources: statements
statement = [s for s in g.objects(distribution_ref, DCT.rights)][0]
assert self._triple(g, statement, RDFS.label, resource['rights'])
assert self._triple(g, statement, RDFS.label, resource["rights"])

def test_distribution_identifier(self):

Expand Down Expand Up @@ -366,6 +365,48 @@ def test_distribution_identifier_falls_back_to_id(self):
distribution_ref = self._triple(g, dataset_ref, DCAT.distribution, None)[2]
resource = dataset_dict["resources"][0]

assert self._triple(g, distribution_ref, DCT.identifier, resource["id"])

def test_bbox(self):
dataset_dict = {
"name": "test-dcat-us",
"description": "Test",
"bbox": [
{"west": -179.15, "east": -129.98, "north": 71.54, "south": 51.21}
],
}

s = RDFSerializer(profiles=DCAT_AP_PROFILES)
g = s.g

dataset_ref = s.graph_from_dataset(dataset_dict)

bbox_ref = [s for s in g.objects(dataset_ref, DCATUS.geographicBoundingBox)][0]
assert self._triple(
g,
bbox_ref,
DCATUS.westBoundingLongitude,
dataset_dict["bbox"][0]["west"],
data_type=XSD.decimal,
)
assert self._triple(
g,
bbox_ref,
DCATUS.eastBoundingLongitude,
dataset_dict["bbox"][0]["east"],
data_type=XSD.decimal,
)
assert self._triple(
g, distribution_ref, DCT.identifier, resource["id"]
g,
bbox_ref,
DCATUS.northBoundingLatitude,
dataset_dict["bbox"][0]["north"],
data_type=XSD.decimal,
)
assert self._triple(
g,
bbox_ref,
DCATUS.southBoundingLatitude,
dataset_dict["bbox"][0]["south"],
data_type=XSD.decimal,
)
1 change: 1 addition & 0 deletions ckanext/dcat/tests/shacl/test_shacl.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def test_validate_dcat_us_3_graph():

graph = graph_from_dataset("ckan_full_dataset_dcat_us_vocabularies.json")

graph.serialize(destination="graph.ttl")
path = _get_shacl_file_path("dcat-us_3.0_shacl_shapes.ttl")
r = validate(graph, shacl_graph=path)
conforms, results_graph, results_text = r
Expand Down
15 changes: 14 additions & 1 deletion examples/ckan/ckan_full_dataset_dcat_us_vocabularies.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,22 @@
"start": "2024-04-10",
"end": "2024-05-29"
}

],
"temporal_resolution": "PT15M",
"bbox": [
{
"west": -179.15,
"east": -129.98,
"north": 71.54,
"south": 51.21
},
{
"west": -125.0,
"east": -66.9,
"north": 49.4,
"south": 24.4
}
],
"spatial_coverage": [
{
"geom": {
Expand Down

0 comments on commit 712b804

Please sign in to comment.