Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support STAC 1.0 - part 0 #96

Merged
merged 14 commits into from
Jun 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ The table below shows the corresponding versions between intake-stac and STAC:
| 0.2.x | 0.6.x |
| 0.3.x | 1.0.0-betaX |
| 0.4.x | 1.0.0-betaX |
| 1.0.0 | 1.0.0 |

## About

Expand Down
4 changes: 3 additions & 1 deletion ci/environment-3.7.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ dependencies:
- geopandas
- intake
- intake-xarray
- pystac
- pytest-cov
- rasterio
- xarray
- pip
- pip:
- pystac>=1.0.0rc1
3 changes: 2 additions & 1 deletion ci/environment-3.8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ dependencies:
- geopandas
- intake
- intake-xarray
- pystac
- pytest-cov
- rasterio
- xarray
- pip:
- pystac>=1.0.0rc1
4 changes: 3 additions & 1 deletion ci/environment-3.9.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ dependencies:
- geopandas
- intake
- intake-xarray
- pystac
- pytest-cov
- rasterio
- xarray
- pip
- pip:
- pystac>=1.0.0rc1
4 changes: 3 additions & 1 deletion ci/environment-unpinned.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ dependencies:
- geopandas
- intake
- intake-xarray
- pystac
- pytest-cov
- rasterio
- xarray
- pip
- pip:
- pystac>=1.0.0rc1
1 change: 0 additions & 1 deletion docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ Catalog Objects
StacCollection
StacItemCollection
StacItem
catalog.StacEntry
29 changes: 5 additions & 24 deletions docs/source/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Catalog:

.. ipython:: python

url = 'https://raw.githubusercontent.com/cholmes/sample-stac/master/stac/catalog.json'
url = 'https://raw.githubusercontent.com/radiantearth/stac-spec/master/examples/catalog.json'
catalog = intake.open_stac_catalog(url)
list(catalog)

Expand Down Expand Up @@ -71,10 +71,10 @@ contents:
.. ipython:: python

print(list(catalog))
cat = catalog['hurricane-harvey']
cat = catalog['extensions-collection']

print(list(cat))
subcat = cat['hurricane-harvey-0831']
subcat = cat['proj-example']

items = list(subcat)
print(items)
Expand All @@ -85,29 +85,10 @@ When you locate an item of interest, you have access to metadata and methods to

.. ipython:: python

item = subcat['Houston-East-20170831-103f-100d-0f4f-RGB']
item = subcat['B1']
print(type(item))
print(item.metadata)

assets = list(item)
print(assets)

asset = item['thumbnail']
print(type(asset))
print(asset.urlpath)


If the catalog has too many entries to comfortably print all at once,
you can narrow it by searching for a term (e.g. 'thumbnail'):

.. ipython:: python

for id, entry in subcat.search('thumbnail').items():
print(id)

asset = subcat['Houston-East-20170831-103f-100d-0f4f-RGB.thumbnail']
print(asset.urlpath)


Loading a dataset
-----------------
Expand All @@ -117,7 +98,7 @@ using Intake's `to_dask()` method. This reads only metadata, and streams values

.. ipython:: python

da = asset.to_dask()
da = item.to_dask()
display(da)


Expand Down
42 changes: 14 additions & 28 deletions intake_stac/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from intake.catalog import Catalog
from intake.catalog.local import LocalCatalogEntry
from pkg_resources import get_distribution
from pystac.extensions.eo import EOExtension

__version__ = get_distribution('intake_stac').version

Expand Down Expand Up @@ -173,21 +174,21 @@ class StacItemCollection(AbstractStacCatalog):
"""

name = 'stac_itemcollection'
_stac_cls = pystac.Catalog
_stac_cls = pystac.ItemCollection

def _load(self):
"""
Load the STAC Item Collection.
"""
if not self._stac_obj.ext.implements('single-file-stac'):
raise ValueError("StacItemCollection requires 'single-file-stac' extension")
for feature in self._stac_obj.ext['single-file-stac'].features:
self._entries[feature.id] = LocalCatalogEntry(
name=feature.id,
# if not self._stac_obj.ext.implements('single-file-stac'):
# raise ValueError("StacItemCollection requires 'single-file-stac' extension")
for item in self._stac_obj.items:
self._entries[item.id] = LocalCatalogEntry(
name=item.id,
description='',
driver=StacItem,
catalog=self,
args={'stac_obj': feature},
args={'stac_obj': item},
)

def to_geopandas(self, crs=None):
Expand Down Expand Up @@ -246,25 +247,8 @@ def _get_band_info(self):
Return list of band info dictionaries (name, common_name, etc.)...
"""
band_info = []
try:
# NOTE: ensure we test these scenarios
# FileNotFoundError: [Errno 2] No such file or directory: '/catalog.json'
collection = self._stac_obj.get_collection()
if 'item-assets' in collection.stac_extensions:
for val in collection.ext['item_assets']:
if 'eo:bands' in val:
band_info.append(val.get('eo:bands')[0])
else:
band_info = collection.summaries['eo:bands']

except Exception:
for band in self._stac_obj.ext['eo'].get_bands():
band_info.append(band.to_dict())
finally:
if not band_info:
raise ValueError(
'Unable to parse "eo:bands" information from STAC Collection or Item Assets'
)
for band in EOExtension.ext(self._stac_obj).bands:
band_info.append(band.to_dict())
return band_info

def stack_bands(self, bands, path_as_pattern=None, concat_dim='band'):
Expand Down Expand Up @@ -298,7 +282,7 @@ def stack_bands(self, bands, path_as_pattern=None, concat_dim='band'):
stack = item.stack_bands(['B4','B5'], path_as_pattern='{band}.TIF')
da = stack(chunks=dict(band=1, x=2048, y=2048)).to_dask()
"""
if 'eo' not in self._stac_obj.stac_extensions:
if not EOExtension.has_extension(self._stac_obj):
raise ValueError('STAC Item must implement "eo" extension to use this method')

band_info = self._get_band_info()
Expand Down Expand Up @@ -430,7 +414,9 @@ def _get_driver(self, asset):

if entry_type in ['', 'null', None]:

suffix = os.path.splitext(asset.media_type)[-1]
suffix = '.tif'
if asset.media_type:
suffix = os.path.splitext(asset.media_type)[-1]
if suffix in ['.nc', '.h5', '.hdf']:
asset.media_type = 'application/netcdf'
warnings.warn(
Expand Down
19 changes: 19 additions & 0 deletions intake_stac/tests/data/1.0.0/catalog/catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"type": "Catalog",
"id": "test",
"stac_version": "1.0.0",
"description": "test catalog",
"links": [
{
"rel": "child",
"href": "./child-catalog.json",
"type": "application/json"
},
{
"rel": "root",
"href": "./catalog.json",
"type": "application/json"
}
],
"stac_extensions": []
}
14 changes: 14 additions & 0 deletions intake_stac/tests/data/1.0.0/catalog/child-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"type": "Catalog",
"id": "test",
"stac_version": "1.0.0",
"description": "child catalog",
"links": [
{
"rel": "root",
"href": "./catalog.json",
"type": "application/json"
}
],
"stac_extensions": []
}
75 changes: 75 additions & 0 deletions intake_stac/tests/data/1.0.0/collection/collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"id": "simple-collection",
"type": "Collection",
"stac_extensions": [
"https://stac-extensions.github.io/eo/v1.0.0/schema.json",
"https://stac-extensions.github.io/view/v1.0.0/schema.json"
],
"stac_version": "1.0.0",
"description": "A simple collection demonstrating core catalog fields with links to a couple of items",
"title": "Simple Example Collection",
"providers": [
{
"name": "Remote Data, Inc",
"description": "Producers of awesome spatiotemporal assets",
"roles": ["producer", "processor"],
"url": "http://remotedata.io"
}
],
"extent": {
"spatial": {
"bbox": [
[
172.91173669923782, 1.3438851951615003, 172.95469614953714,
1.3690476620161975
]
]
},
"temporal": {
"interval": [["2020-12-11T22:38:32.125Z", "2020-12-14T18:02:31.437Z"]]
}
},
"license": "CC-BY-4.0",
"summaries": {
"platform": ["cool_sat1", "cool_sat2"],
"constellation": ["ion"],
"instruments": ["cool_sensor_v1", "cool_sensor_v2"],
"gsd": {
"minimum": 0.512,
"maximum": 0.66
},
"eo:cloud_cover": {
"minimum": 1.2,
"maximum": 1.2
},
"proj:epsg": {
"minimum": 32659,
"maximum": 32659
},
"view:sun_elevation": {
"minimum": 54.9,
"maximum": 54.9
},
"view:off_nadir": {
"minimum": 3.8,
"maximum": 3.8
},
"view:sun_azimuth": {
"minimum": 135.7,
"maximum": 135.7
}
},
"links": [
{
"rel": "root",
"href": "./collection.json",
"type": "application/json"
},
{
"rel": "item",
"href": "./simple-item.json",
"type": "application/geo+json",
"title": "Simple Item"
}
]
}
Loading