STAC Item Creation

Once you have created a collection (see stac-collection-creation.ipynb) use this notebook to create items for that collection.
Author

Julia Signell

Published

June 12, 2023

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

!pip install -U rio_stac parse xpystac pystac nbss-upload --quiet
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.

COLLECTION_ID = "no2-monthly-diff"
ITEM_ID = "OMI_trno2_0.10x0.10_202212_Col3_V4.nc"
SOURCE = "s3://veda-data-store-staging/no2-monthly-diff/OMI_trno2_0.10x0.10_202212_Col3_V4.nc.tif"

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"""

    fields = parse("OMI_trno2_0.10x0.10_{year:4}{month:2}_Col3_V4.nc", item_id)
    year = int(fields["year"])
    month = int(fields["month"])
    day = 1
    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.

item = rio_stac.stac.create_stac_item(
    id=ITEM_ID,
    source=SOURCE,
    collection=COLLECTION_ID,
    input_datetime=datetime_func(ITEM_ID),
    with_proj=True,
    with_raster=True,
    asset_name="cog_default",
    asset_roles=["data", "layer"],
    asset_media_type="image/tiff; application=geotiff; profile=cloud-optimized",
)

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.

data = xr.open_dataset(item).cog_default.isel(time=0)
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
data.hvplot("longitude", "latitude")