Skip to content

Commit 48fdff7

Browse files
committed
Implement #370 for Scientific Citation Extension
1 parent 1326dea commit 48fdff7

File tree

4 files changed

+168
-2
lines changed

4 files changed

+168
-2
lines changed

pystac/extensions/scientific.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,8 @@ def remove_publication(self, publication: Optional[Publication] = None) -> None:
224224
def get_schema_uri(cls) -> str:
225225
return SCHEMA_URI
226226

227-
@staticmethod
228-
def ext(obj: T) -> "ScientificExtension[T]":
227+
@classmethod
228+
def ext(cls, obj: T) -> "ScientificExtension[T]":
229229
"""Extends the given STAC Object with properties from the :stac-ext:`Scientific
230230
Extension <scientific>`.
231231
@@ -237,8 +237,10 @@ def ext(obj: T) -> "ScientificExtension[T]":
237237
pystac.ExtensionTypeError : If an invalid object type is passed.
238238
"""
239239
if isinstance(obj, pystac.Collection):
240+
cls.validate_has_extension(obj)
240241
return cast(ScientificExtension[T], CollectionScientificExtension(obj))
241242
if isinstance(obj, pystac.Item):
243+
cls.validate_has_extension(obj)
242244
return cast(ScientificExtension[T], ItemScientificExtension(obj))
243245
else:
244246
raise pystac.ExtensionTypeError(
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"stac_version": "1.0.0-rc.1",
3+
"stac_extensions": [
4+
"https://stac-extensions.github.io/scientific/v1.0.0/schema.json"
5+
],
6+
"id": "MERRAclim",
7+
"title": "MERRAclim, a high-resolution global dataset of remotely sensed bioclimatic variables for ecological modelling.",
8+
"description": "Species Distribution Models (SDMs) combine information on the geographic occurrence of species with environmental layers to estimate distributional ranges and have been extensively implemented to answer a wide array of applied ecological questions. Unfortunately, most global datasets available to parameterize SDMs consist of spatially interpolated climate surfaces obtained from ground weather station data and have omitted the Antarctic continent, a landmass covering c. 20% of the Southern Hemisphere and increasingly showing biological effects of global change. Here we introduce MERRAclim, a global set of satellite-based bioclimatic variables including Antarctica for the first time. MERRAclim consists of three datasets of 19 bioclimatic variables that have been built for each of the last three decades (1980s, 1990s and 2000s) using hourly data of 2 m temperature and specific humidity. We provide MERRAclim at three spatial resolutions (10 arc-minutes, 5 arc-minutes and 2.5 arc-minutes). These reanalysed data are comparable to widely used datasets based on ground station interpolations, but allow extending their geographical reach and SDM building in previously uncovered regions of the globe.",
9+
"type": "Collection",
10+
"keywords": [
11+
"bioclimatic",
12+
"MERRAclim",
13+
"macroecology",
14+
"biogeography"
15+
],
16+
"license": "CC0-1.0",
17+
"extent": {
18+
"spatial": {
19+
"bbox": [
20+
[
21+
-180,
22+
-90,
23+
180,
24+
90
25+
]
26+
]
27+
},
28+
"temporal": {
29+
"interval": [
30+
[
31+
"1980-01-01T00:00:00Z",
32+
"2009-12-31T23:59:59Z"
33+
]
34+
]
35+
}
36+
},
37+
"sci:doi": "10.5061/dryad.s2v81.2",
38+
"sci:citation": "Vega GC, Pertierra LR, Olalla-Tárraga MÁ (2017) Data from: MERRAclim, a high-resolution global dataset of remotely sensed bioclimatic variables for ecological modelling. Dryad Digital Repository.",
39+
"sci:publications": [
40+
{
41+
"doi": "10.1038/sdata.2017.78",
42+
"citation": "Vega GC, Pertierra LR, Olalla-Tárraga MÁ (2017) MERRAclim, a high-resolution global dataset of remotely sensed bioclimatic variables for ecological modelling. Scientific Data 4: 170078."
43+
}
44+
],
45+
"links": [
46+
{
47+
"rel": "self",
48+
"href": "https://datadryad.org/resource/doi:10.5061/dryad.s2v81/collection.json"
49+
},
50+
{
51+
"rel": "item",
52+
"href": "https://datadryad.org/resource/doi:10.5061/dryad.s2v81/item.json"
53+
},
54+
{
55+
"rel": "root",
56+
"href": "https://datadryad.org/resource/doi:10.5061/dryad.s2v81/collection.json"
57+
},
58+
{
59+
"rel": "cite-as",
60+
"href": "https://doi.org/10.5061/dryad.s2v81.2"
61+
}
62+
]
63+
}

tests/data-files/scientific/item.json

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
{
2+
"stac_version": "1.0.0-rc.1",
3+
"stac_extensions": [
4+
"https://stac-extensions.github.io/scientific/v1.0.0/schema.json"
5+
],
6+
"id": "MERRAclim.2_5m_min_80s",
7+
"type": "Feature",
8+
"geometry": {
9+
"type": "Polygon",
10+
"coordinates": [
11+
[
12+
[
13+
-180,
14+
-90
15+
],
16+
[
17+
180,
18+
-90
19+
],
20+
[
21+
180,
22+
90
23+
],
24+
[
25+
-180,
26+
90
27+
],
28+
[
29+
-180,
30+
-90
31+
]
32+
]
33+
]
34+
},
35+
"bbox": [
36+
-180,
37+
-90,
38+
180,
39+
90
40+
],
41+
"properties": {
42+
"title": "MERRAclim. 2_5m_min_80s",
43+
"description": "MERRAclim Dataset. 19 global bioclimatic variables from the 1980s decade at 2.5 arcminutes resolution in GEOtiff format. The humidity version used is the min. The variables have been built using the same protocol as WorldClim with data from MERRA. Temperature layers (BIO1-BIO11) are in degree Celsius multiplied by 10, humidity layers (BIO12-BIO19) are in kg of water/kg of air multiplied by 100000.",
44+
"datetime": "1985-07-01T00:00:00Z",
45+
"start_datetime": "1980-01-01T00:00:00Z",
46+
"end_datetime": "1989-12-31T23:59:59Z",
47+
"sci:doi": "10.5061/dryad.s2v81.2/27.2",
48+
"sci:publications": [
49+
{
50+
"doi": "10.5061/dryad.s2v81.2",
51+
"citation": "Vega GC, Pertierra LR, Olalla-Tárraga MÁ (2017) Data from: MERRAclim, a high-resolution global dataset of remotely sensed bioclimatic variables for ecological modelling. Dryad Digital Repository."
52+
},
53+
{
54+
"doi": "10.1038/sdata.2017.78",
55+
"citation": "Vega GC, Pertierra LR, Olalla-Tárraga MÁ (2017) MERRAclim, a high-resolution global dataset of remotely sensed bioclimatic variables for ecological modelling. Scientific Data 4: 170078."
56+
}
57+
]
58+
},
59+
"links": [
60+
{
61+
"rel": "self",
62+
"href": "https://datadryad.org/resource/doi:10.5061/dryad.s2v81/item.json"
63+
},
64+
{
65+
"rel": "root",
66+
"href": "https://datadryad.org/resource/doi:10.5061/dryad.s2v81/catalog.json"
67+
},
68+
{
69+
"rel": "cite-as",
70+
"href": "https://doi.org/10.5061/dryad.s2v81.2/27.2"
71+
}
72+
],
73+
"assets": {
74+
"primary": {
75+
"href": "https://datadryad.org/stash/downloads/file_stream/100467",
76+
"type": "application/zip",
77+
"title": "MERRAclim. 2_5m_min_80s"
78+
}
79+
}
80+
}

tests/extensions/test_scientific.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
ScientificRelType,
1515
remove_link,
1616
)
17+
from tests.utils import TestCases
1718

1819
URL_TEMPLATE = "http://example.com/catalog/%s.json"
1920

@@ -73,6 +74,7 @@ class ItemScientificExtensionTest(unittest.TestCase):
7374
def setUp(self) -> None:
7475
super().setUp()
7576
self.item = make_item()
77+
self.example_item_uri = TestCases.get_path("data-files/scientific/item.json")
7678

7779
def test_stac_extensions(self) -> None:
7880
self.assertTrue(ScientificExtension.has_extension(self.item))
@@ -206,6 +208,14 @@ def test_remove_all_publications_with_none(self) -> None:
206208
self.assertEqual(DOI_URL, links[0].target)
207209
self.item.validate()
208210

211+
def test_extension_not_implemented(self) -> None:
212+
# Should raise exception if Item does not include extension URI
213+
item = pystac.Item.from_file(self.example_item_uri)
214+
item.stac_extensions.remove(ScientificExtension.get_schema_uri())
215+
216+
with self.assertRaises(pystac.ExtensionNotImplemented):
217+
_ = ScientificExtension.ext(item)
218+
209219

210220
def make_collection() -> pystac.Collection:
211221
asset_id = "my/thing"
@@ -227,6 +237,9 @@ class CollectionScientificExtensionTest(unittest.TestCase):
227237
def setUp(self) -> None:
228238
super().setUp()
229239
self.collection = make_collection()
240+
self.example_collection_uri = TestCases.get_path(
241+
"data-files/scientific/collection.json"
242+
)
230243

231244
def test_stac_extensions(self) -> None:
232245
self.assertTrue(ScientificExtension.has_extension(self.collection))
@@ -365,6 +378,14 @@ def test_remove_all_publications_with_none(self) -> None:
365378
self.assertEqual(DOI_URL, links[0].target)
366379
self.collection.validate()
367380

381+
def test_extension_not_implemented(self) -> None:
382+
# Should raise exception if Item does not include extension URI
383+
collection = pystac.Collection.from_file(self.example_collection_uri)
384+
collection.stac_extensions.remove(ScientificExtension.get_schema_uri())
385+
386+
with self.assertRaises(pystac.ExtensionNotImplemented):
387+
_ = ScientificExtension.ext(collection)
388+
368389

369390
class SummariesScientificTest(unittest.TestCase):
370391
def setUp(self) -> None:

0 commit comments

Comments
 (0)