!pip install -U rio_stac parse xpystac pystac nbss-upload --quiet
STAC Item Creation
Run this notebook
You can launch this notebook in VEDA JupyterHub by clicking the link below.
Launch in VEDA JupyterHub (requires access)
Learn more
Inside the Hub
This notebook was written on a VEDA JupyterHub instance
See (VEDA Analytics JupyterHub Access)[https://nasa-impact.github.io/veda-docs/veda-jh-access.html] for information about how to gain access.
Outside the Hub
You are welcome to run this anywhere you like (Note: alternatively you can run this on https://daskhub.veda.smce.nasa.gov/, MAAP, locally, …), just make sure that the data is accessible, or get in contact with the VEDA team to enable access.
Install extra packages
from datetime import datetime
import rio_stac
import xarray as xr
from parse import parse
Create pystac.Item
In this section we will be creating a pystac.Item
object. This is the part of that notebook that you should update.
Declare constants
Start by declaring some string fields.
= "no2-monthly-diff"
COLLECTION_ID = "OMI_trno2_0.10x0.10_202212_Col3_V4.nc"
ITEM_ID = "s3://veda-data-store-staging/no2-monthly-diff/OMI_trno2_0.10x0.10_202212_Col3_V4.nc.tif" SOURCE
Calculate datetime
Create a function that calculates datetime when given an item_id
. You can change this to depend on the source
instead if that works better.
def datetime_func(item_id: str) -> datetime:
"""Given the item_id, figure out the datetime"""
= parse("OMI_trno2_0.10x0.10_{year:4}{month:2}_Col3_V4.nc", item_id)
fields = int(fields["year"])
year = int(fields["month"])
month = 1
day return datetime(year, month, day)
Test out the datetime function:
datetime_func(ITEM_ID)
datetime.datetime(2022, 12, 1, 0, 0)
Put it together
Now take your constants and datetime function and create the STAC Item using rio_stac
.
= rio_stac.stac.create_stac_item(
item id=ITEM_ID,
=SOURCE,
source=COLLECTION_ID,
collection=datetime_func(ITEM_ID),
input_datetime=True,
with_proj=True,
with_raster="cog_default",
asset_name=["data", "layer"],
asset_roles="image/tiff; application=geotiff; profile=cloud-optimized",
asset_media_type )
Try it out!
Now that you have an item you can try it out and make sure it looks good and passes validation checks.
item.validate()
['https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json',
'https://stac-extensions.github.io/projection/v1.1.0/schema.json',
'https://stac-extensions.github.io/raster/v1.1.0/schema.json']
item.to_dict()
{'type': 'Feature',
'stac_version': '1.0.0',
'id': 'OMI_trno2_0.10x0.10_202212_Col3_V4.nc',
'properties': {'proj:epsg': 4326,
'proj:geometry': {'type': 'Polygon',
'coordinates': [[[-180.0, -90.0],
[180.0, -90.0],
[180.0, 90.0],
[-180.0, 90.0],
[-180.0, -90.0]]]},
'proj:bbox': [-180.0, -90.0, 180.0, 90.0],
'proj:shape': [1800, 3600],
'proj:transform': [0.1, 0.0, -180.0, 0.0, -0.1, 90.0, 0.0, 0.0, 1.0],
'proj:projjson': {'$schema': 'https://proj.org/schemas/v0.7/projjson.schema.json',
'type': 'GeographicCRS',
'name': 'WGS 84',
'datum': {'type': 'GeodeticReferenceFrame',
'name': 'World Geodetic System 1984',
'ellipsoid': {'name': 'WGS 84',
'semi_major_axis': 6378137,
'inverse_flattening': 298.257223563}},
'coordinate_system': {'subtype': 'ellipsoidal',
'axis': [{'name': 'Geodetic latitude',
'abbreviation': 'Lat',
'direction': 'north',
'unit': 'degree'},
{'name': 'Geodetic longitude',
'abbreviation': 'Lon',
'direction': 'east',
'unit': 'degree'}]},
'id': {'authority': 'EPSG', 'code': 4326}},
'proj:wkt2': 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]',
'datetime': '2022-12-01T00:00:00Z'},
'geometry': {'type': 'Polygon',
'coordinates': [[(-180.0, -90.0),
(180.0, -90.0),
(180.0, 90.0),
(-180.0, 90.0),
(-180.0, -90.0)]]},
'links': [{'rel': 'collection',
'href': 'no2-monthly-diff',
'type': 'application/json'}],
'assets': {'cog_default': {'href': 's3://veda-data-store-staging/no2-monthly-diff/OMI_trno2_0.10x0.10_202212_Col3_V4.nc.tif',
'type': 'image/tiff; application=geotiff; profile=cloud-optimized',
'raster:bands': [{'data_type': 'float32',
'scale': 1.0,
'offset': 0.0,
'sampling': 'area',
'nodata': -1.2676506002282294e+30,
'statistics': {'mean': 12233282717799.0,
'minimum': -1.30282195779584e+16,
'maximum': 2.082349180465971e+16,
'stddev': 416857512760678.5,
'valid_percent': 82.7056884765625},
'histogram': {'count': 11,
'min': -1.30282195779584e+16,
'max': 2.082349180465971e+16,
'buckets': [20, 138, 881, 421049, 11300, 203, 20, 3, 1, 1]}}],
'roles': ['data', 'layer']}},
'bbox': [-180.0, -90.0, 180.0, 90.0],
'stac_extensions': ['https://stac-extensions.github.io/projection/v1.1.0/schema.json',
'https://stac-extensions.github.io/raster/v1.1.0/schema.json'],
'collection': 'no2-monthly-diff'}
Plot it (optional)
Create a quick visual to make sure that data loads and visualizes properly.
= xr.open_dataset(item).cog_default.isel(time=0)
data data
<xarray.DataArray 'cog_default' (latitude: 1800, longitude: 3600)> Size: 26MB [6480000 values with dtype=float32] Coordinates: * latitude (latitude) float64 14kB 89.95 89.85 89.75 ... -89.85 -89.95 * longitude (longitude) float64 29kB -179.9 -179.8 -179.8 ... 179.9 180.0 spatial_ref int32 4B ... time datetime64[ns] 8B 2022-12-01 Attributes: nodata: -1.2676506002282294e+30
"longitude", "latitude") data.hvplot(