From 53fa030f38c1ed6c969499119592111bdd715384 Mon Sep 17 00:00:00 2001 From: Matthias Mohr Date: Mon, 5 Aug 2024 09:30:43 +0200 Subject: [PATCH] Bands RFC #1213 (#1254) Co-authored-by: Emmanuel Mathot Co-authored-by: Pete Gadomski --- CHANGELOG.md | 2 + best-practices.md | 250 +++++++- .../collection-with-schemas.json | 44 +- examples/collection-only/collection.json | 44 +- examples/collection.json | 2 +- examples/collectionless-item.json | 287 +++++---- examples/extended-item.json | 47 +- .../proj-example/proj-example.json | 570 +++++++++--------- extensions/README.md | 10 +- item-spec/common-metadata.md | 118 +++- item-spec/item-spec.md | 6 +- item-spec/json-schema/bands.json | 24 + item-spec/json-schema/common.json | 6 + item-spec/json-schema/data-values.json | 84 +++ item-spec/json-schema/item.json | 108 +++- 15 files changed, 1050 insertions(+), 552 deletions(-) create mode 100644 item-spec/json-schema/bands.json create mode 100644 item-spec/json-schema/data-values.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 865168693..bea674931 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added +- `bands` is a new field in common metadata to replace `eo:bands` and `raster:bands` ([#1213](https://github.com/radiantearth/stac-spec/discussions/1213)) +- The fields `data_type`, `nodata`, `statistics` and `unit` have been added to common metadata ([#1213](https://github.com/radiantearth/stac-spec/discussions/1213)) - The `keywords` field known from Collections is available in common metadata. ([#1187](https://github.com/radiantearth/stac-spec/issues/1187)) - New fields `method`, `headers` and `body` in the Link Object. ([#1198](https://github.com/radiantearth/stac-spec/issues/1198)) - The `license` field additionally supports SPDX expressions and the value `other`. diff --git a/best-practices.md b/best-practices.md index 11c4fd28d..1d08e1d0c 100644 --- a/best-practices.md +++ b/best-practices.md @@ -15,16 +15,12 @@ - [Field selection and Metadata Linking](#field-selection-and-metadata-linking) - [Datetime selection](#datetime-selection) - [Unlocated Items](#unlocated-items) - - [Unrectified Satellite Data](#unrectified-satellite-data) - - [Data that is not spatial](#data-that-is-not-spatial) - [Representing Vector Layers in STAC](#representing-vector-layers-in-stac) - **[Asset and Link Best Practices](#asset-and-link-best-practices)** - [Common Use Cases of Additional Fields for Assets](#common-use-cases-of-additional-fields-for-assets) - [Working with Media Types](#working-with-media-types) - - [Common Media Types in STAC](#common-media-types-in-stac) - - [Formats with no registered media type](#formats-with-no-registered-media-type) - [Asset Roles](#asset-roles) - - [List of Asset Roles](#list-of-asset-roles) + - [Bands](#bands) - **[Catalog & Collection Best Practices](#catalog--collection-practices)** - [Static and Dynamic Catalogs](#static-and-dynamic-catalogs) - [Static Catalogs](#static-catalogs) @@ -38,13 +34,11 @@ - [Published Catalogs](#published-catalogs) - [Using Relation Types](#using-relation-types) - [Versioning for Catalogs](#versioning-for-catalogs) - - [Example](#example) - [Static to Dynamic best practices](#static-to-dynamic-best-practices) - [Ingestion and links](#ingestion-and-links) - [Keep catalogs in sync with cloud notification and queue services](#keep-catalogs-in-sync-with-cloud-notification-and-queue-services) - [How to Differentiate STAC Files](#how-to-differentiate-stac-files) - This document makes a number of recommendations for creating real world SpatioTemporal Asset Catalogs. None of them are required to meet the core specification, but following these practices will make life easier for client tooling and for users. They come about from practical experience of implementors and introduce a bit more 'constraint' for @@ -294,7 +288,7 @@ providing them at the Asset level can prove to be very useful for using the data with different spatial resolution than the overall best resolution. Note this should not be used for different spatial resolutions due to specific processing of assets - look into the [raster extension](https://github.com/stac-extensions/raster) for that use case. -- `eo:bands` ([EO extension](https://github.com/stac-extensions/eo/)): +- `bands` (e.g. in combination with the [EO extension](https://github.com/stac-extensions/eo/)): Provide spectral band information, and order of bands, within an individual asset. - `proj:epsg`/`proj:wkt2`/`proj:projjson` ([projection extension](https://github.com/stac-extensions/projection/)): Specify different projection for some assets. If the projection is different @@ -305,7 +299,7 @@ providing them at the Asset level can prove to be very useful for using the data If assets have different spatial resolutions and slightly different exact bounding boxes, specify these per asset to indicate the size of the asset in pixels and its exact GeoTransform in the native projection. - `sar:polarizations` ([sar extension](https://github.com/stac-extensions/sar)): - Provide the polarization content and ordering of a specific asset, similar to `eo:bands`. + Provide the polarization content and ordering of a specific asset. - `sar:product_type` ([sar extension](https://github.com/stac-extensions/sar)): If mixing multiple product types within a single Item, this can be used to specify the product_type for each asset. @@ -428,6 +422,236 @@ If your data for the Item does not come with a thumbnail already we do recommend | Spatial extent | Limited | Full | Full | | Use case | Quick overview, often in lists of items/collections | Display for a single Item/Collection, sometimes shown on a web map | Display for a single Item/Collection, often shown on a map, may be displayed in GIS software | +### Bands + +As of STAC 1.1, the `bands` array can be used in combination with property inheritance to provide users with more flexibility. +The following best practices should be considered, especially when migrating from `eo:bands` and `raster:bands`. + +#### Single band + +Single band assets can be defined in two ways. +Properties can be defined in the `bands` array or in the assets directly. + +Example using the `bands` array: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "bands": [ + { + "data_type": "uint16", + "eo:common_name": "red", + "raster:spatial_resolution": 10 + } + ] + } + } +} +``` + +Example without bands: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "data_type": "uint16", + "eo:common_name": "red", + "raster:spatial_resolution": 10 + } + } +} +``` + +STAC recommands that single band assets should only use the `bands` array in the following cases: + +1. **It's important in to convey that a band is present in the asset.** + - This is the case if the data access mechanism requires you to specify the name of index of the band to retrieve the data, + then the band should be specified as such. + - This is also the case if the band has a specific name. + The `name` property is only available in bands and as such can't be specified for the Asset. +2. **It is important that the (often spectral) band is part of a set of bands.** + - For example, if the `bands` array is exposed in the Collection Summaries, + there should be bands defined in the Items or Item Assets as otherwise there's nothing to summarize. +3. **Individual bands are repeated in different assets.** + - This may happen if you provide assets with different resolutions or file formats. + The `name` property with the same value should be used so that users can identify that the bands are the same. + It also enables clients to easily combine and summarize the bands. + +#### Multiple bands + +Generally, all properties that have the same value across all bands should not be listed in bands but in assets directly. + +For example, if your bands in an asset is defined as follows: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "bands": [ + { + "name": "r", + "eo:common_name": "red", + "data_type": "uint16", + "raster:spatial_resolution": 10 + }, + { + "name": "g", + "eo:common_name": "green", + "data_type": "uint16", + "raster:spatial_resolution": 10 + }, + { + "name": "b", + "eo:common_name": "blue", + "data_type": "uint16", + "raster:spatial_resolution": 10 + } + ] + } + } +} +``` + +The `data_type` and `raster:spatial_resolution` has the same value for all bands. +As such you can deduplicate those properties and list them in the asset directly: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "data_type": "uint16", + "raster:spatial_resolution": 10, + "bands": [ + { + "name": "r", + "eo:common_name": "red" + }, + { + "name": "g", + "eo:common_name": "green" + }, + { + "name": "b", + "eo:common_name": "blue" + } + ] + } + } +} +``` + +#### Band migration + +It should be relatively simple to migrate from STAC 1.0 (i.e. `eo:bands` and/or `raster:bands`) to the new `bands` array. + +Usually, you can simply merge the each object on a by-index basis. +Nevertheless, you should consider deduplicating properties with the same values across all bands to the Asset. +For some fields you need to add the extension prefix of the `eo` or `raster` extension to the property name. + +STAC 1.0 example: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "eo:bands": [ + { + "name": "r", + "common_name": "red" + }, + { + "name": "g", + "common_name": "green" + }, + { + "name": "b", + "common_name": "blue" + }, + { + "name": "nir", + "common_name": "nir" + } + ], + "raster:bands": [ + { + "data_type": "uint16", + "spatial_resolution": 10, + "sampling": "area" + }, + { + "data_type": "uint16", + "spatial_resolution": 10, + "sampling": "area" + }, + { + "data_type": "uint16", + "spatial_resolution": 10, + "sampling": "area" + }, + { + "data_type": "uint16", + "spatial_resolution": 30, + "sampling": "area" + } + ] + } + } +} +``` + +After migrating to STAC 1.1 this is ideally provided as follows: + +```json +{ + "assets": { + "example": { + "href": "example.tif", + "data_type": "uint16", + "raster:sampling": "area", + "raster:spatial_resolution": 10, + "bands": [ + { + "name": "r", + "eo:common_name": "red", + }, + { + "name": "g", + "eo:common_name": "green" + }, + { + "name": "b", + "eo:common_name": "blue" + }, + { + "name": "nir", + "eo:common_name": "nir", + "raster:spatial_resolution": 30 + } + ] + } + } +} +``` + +The following was done: + +- The arrays have been merged into a single property `bands`. +- The properties `common_name` and `spatial_resolution` were renamed to include the extension prefixes. +- The properties `data_type` and `raster:sampling` (renamed from `sampling`) were deduplicated to the Asset + as the values were the same across all bands. +- The `spatial_resolution` was also deduplicated, i.e. `10` is provided on the asset level, + which is inherited by the bands unless explicitly overridden. + Therefore, the `nir` band overrides the value `10` with a value of `30`. + +As a result, the new `bands` array is more lightweight and easier to handle. + ## Catalog & Collection Practices *Note: This section uses the term 'Catalog' (with an uppercase C) to refer to the JSON entity specified in the @@ -577,11 +801,11 @@ in the array are meaningless, as each Item is describing its transform, so combi So if the values contained in the array are independently meaningful (not interconnected) and there aren't hundreds of potential values then it is likely a good candidate to summarize. -We do highly recommend including an [`eo:bands`](https://github.com/stac-extensions/eo/blob/main/README.md#eobands) -summary if your Items implement `eo:bands`, +We do highly recommend including a [`bands`](./item-spec/common-metadata.md#bands) +summary if your Items implement `bands`, especially if it represents just one satellite or constellation. This should be a union of all the potential bands that you -have in assets. It is ok to only add the summary at the Collection level without putting an explicit `eo:bands` summary at the -`properties` level of an Item, since that is optional. This gives users of the Collection a sense of the sensor capabilities without +have in assets. It is ok to only add the summary at the Collection level without putting `bands` at the +`properties` level of an Item. This gives users of the Collection a sense of the sensor capabilities without having to examine specific Items or aggregate across every Item. Note that the ranges of summaries don't have to be exact. If you are publishing a catalog that is constantly updating with diff --git a/examples/collection-only/collection-with-schemas.json b/examples/collection-only/collection-with-schemas.json index ba4387632..997f23a56 100644 --- a/examples/collection-only/collection-with-schemas.json +++ b/examples/collection-only/collection-with-schemas.json @@ -1,7 +1,7 @@ { "stac_version": "1.0.0", "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json", "https://stac-extensions.github.io/sat/v1.0.0/schema.json", "https://stac-extensions.github.io/view/v1.0.0/schema.json" ], @@ -199,77 +199,77 @@ } ] }, - "eo:bands": [ + "bands": [ { "title": "B1", - "common_name": "coastal", - "center_wavelength": 0.4439, + "eo:common_name": "coastal", + "eo:center_wavelength": 0.4439, "gsd": 60 }, { "title": "B2", - "common_name": "blue", - "center_wavelength": 0.4966, + "eo:common_name": "blue", + "eo:center_wavelength": 0.4966, "gsd": 10 }, { "title": "B3", - "common_name": "green", - "center_wavelength": 0.56, + "eo:common_name": "green", + "eo:center_wavelength": 0.56, "gsd": 10 }, { "title": "B4", - "common_name": "red", - "center_wavelength": 0.6645, + "eo:common_name": "red", + "eo:center_wavelength": 0.6645, "gsd": 10 }, { "title": "B5", - "center_wavelength": 0.7039, + "eo:center_wavelength": 0.7039, "gsd": 20 }, { "title": "B6", - "center_wavelength": 0.7402, + "eo:center_wavelength": 0.7402, "gsd": 20 }, { "title": "B7", - "center_wavelength": 0.7825, + "eo:center_wavelength": 0.7825, "gsd": 20 }, { "title": "B8", - "common_name": "nir", - "center_wavelength": 0.8351, + "eo:common_name": "nir", + "eo:center_wavelength": 0.8351, "gsd": 10 }, { "title": "B8A", - "center_wavelength": 0.8648, + "eo:center_wavelength": 0.8648, "gsd": 20 }, { "title": "B9", - "center_wavelength": 0.945, + "eo:center_wavelength": 0.945, "gsd": 60 }, { "title": "B10", - "center_wavelength": 1.3735, + "eo:center_wavelength": 0.13735, "gsd": 60 }, { "title": "B11", - "common_name": "swir16", - "center_wavelength": 1.6137, + "eo:common_name": "swir16", + "eo:center_wavelength": 0.16137, "gsd": 20 }, { "title": "B12", - "common_name": "swir22", - "center_wavelength": 2.2024, + "eo:common_name": "swir22", + "eo:center_wavelength": 0.22024, "gsd": 20 } ] diff --git a/examples/collection-only/collection.json b/examples/collection-only/collection.json index eb733bf2e..98b9cb1db 100644 --- a/examples/collection-only/collection.json +++ b/examples/collection-only/collection.json @@ -2,7 +2,7 @@ "type": "Collection", "stac_version": "1.0.0", "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json", "https://stac-extensions.github.io/projection/v1.0.0/schema.json", "https://stac-extensions.github.io/view/v1.0.0/schema.json" ], @@ -149,65 +149,65 @@ 32659, 32660 ], - "eo:bands": [ + "bands": [ { "name": "B1", - "common_name": "coastal", - "center_wavelength": 0.4439 + "eo:common_name": "coastal", + "eo:center_wavelength": 0.4439 }, { "name": "B2", - "common_name": "blue", - "center_wavelength": 0.4966 + "eo:common_name": "blue", + "eo:center_wavelength": 0.4966 }, { "name": "B3", - "common_name": "green", - "center_wavelength": 0.56 + "eo:common_name": "green", + "eo:center_wavelength": 0.56 }, { "name": "B4", - "common_name": "red", - "center_wavelength": 0.6645 + "eo:common_name": "red", + "eo:center_wavelength": 0.6645 }, { "name": "B5", - "center_wavelength": 0.7039 + "eo:center_wavelength": 0.7039 }, { "name": "B6", - "center_wavelength": 0.7402 + "eo:center_wavelength": 0.7402 }, { "name": "B7", - "center_wavelength": 0.7825 + "eo:center_wavelength": 0.7825 }, { "name": "B8", - "common_name": "nir", - "center_wavelength": 0.8351 + "eo:common_name": "nir", + "eo:center_wavelength": 0.8351 }, { "name": "B8A", - "center_wavelength": 0.8648 + "eo:center_wavelength": 0.8648 }, { "name": "B9", - "center_wavelength": 0.945 + "eo:center_wavelength": 0.945 }, { "name": "B10", - "center_wavelength": 1.3735 + "eo:center_wavelength": 1.3735 }, { "name": "B11", - "common_name": "swir16", - "center_wavelength": 1.6137 + "eo:common_name": "swir16", + "eo:center_wavelength": 1.6137 }, { "name": "B12", - "common_name": "swir22", - "center_wavelength": 2.2024 + "eo:common_name": "swir22", + "eo:center_wavelength": 2.2024 } ] }, diff --git a/examples/collection.json b/examples/collection.json index dd9dc3a1b..c69bce951 100644 --- a/examples/collection.json +++ b/examples/collection.json @@ -2,7 +2,7 @@ "id": "simple-collection", "type": "Collection", "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json", "https://stac-extensions.github.io/projection/v1.0.0/schema.json", "https://stac-extensions.github.io/view/v1.0.0/schema.json" ], diff --git a/examples/collectionless-item.json b/examples/collectionless-item.json index a5137b490..b49dc80ec 100644 --- a/examples/collectionless-item.json +++ b/examples/collectionless-item.json @@ -1,144 +1,143 @@ -{ - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json" - ], - "type": "Feature", - "id": "CS3-20160503_132131_08", - "bbox": [ - -122.59750209, - 37.48803556, - -122.2880486, - 37.613537207 - ], - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - -122.308150179, - 37.488035566 - ], - [ - -122.597502109, - 37.538869539 - ], - [ - -122.576687533, - 37.613537207 - ], - [ - -122.2880486, - 37.562818007 - ], - [ - -122.308150179, - 37.488035566 - ] - ] - ] - }, - "properties": { - "title": "Full Item", - "description": "A sample STAC Item demonstrates an Item that does not have a collection, which is not recommended, but allowed by the spec.", - "datetime": null, - "start_datetime": "2016-05-03T13:22:30Z", - "end_datetime": "2016-05-03T13:27:30Z", - "created": "2016-05-04T00:00:01Z", - "updated": "2017-01-01T00:30:55Z", - "license": "other", - "providers": [ - { - "name": "Remote Data, Inc", - "description": "Producers of awesome spatiotemporal assets", - "roles": [ - "producer", - "processor" - ], - "url": "http://remotedata.it" - } - ], - "platform": "cool_sat2", - "instruments": [ - "cool_sensor_v1" - ], - "view:sun_elevation": 33.4, - "gsd": 0.512, - "cs:type": "scene", - "cs:anomalous_pixels": 0.14, - "cs:earth_sun_distance": 1.014156, - "cs:sat_id": "CS3", - "cs:product_level": "LV1B" - }, - "links": [ - { - "rel": "root", - "href": "./catalog.json", - "type": "application/json", - "title": "Example Catalog" - }, - { - "rel": "parent", - "href": "./catalog.json", - "type": "application/json", - "title": "Example Catalog" - }, - { - "rel": "alternate", - "type": "text/html", - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.html", - "title": "HTML representation of this STAC Item" - }, - { - "rel": "license", - "type": "text/html", - "href": "http://remotedata.io/license.html", - "title": "Data License for Remote Data, Inc." - } - ], - "assets": { - "analytic": { - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/analytic.tif", - "title": "4-Band Analytic", - "eo:bands": [ - { - "name": "band1" - }, - { - "name": "band1" - }, - { - "name": "band2" - }, - { - "name": "band3" - } - ] - }, - "thumbnail": { - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/thumbnail.png", - "title": "Thumbnail", - "type": "image/png", - "roles": [ - "thumbnail" - ] - }, - "udm": { - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/UDM.tif", - "title": "Unusable Data Mask" - }, - "json-metadata": { - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/extended-metadata.json", - "title": "Extended Metadata", - "type": "application/json", - "roles": [ - "metadata" - ] - }, - "ephemeris": { - "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/S3-20160503_132130_04.EPH", - "title": "Satellite Ephemeris Metadata" - } - } -} +{ + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/view/v1.0.0/schema.json" + ], + "type": "Feature", + "id": "CS3-20160503_132131_08", + "bbox": [ + -122.59750209, + 37.48803556, + -122.2880486, + 37.613537207 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.308150179, + 37.488035566 + ], + [ + -122.597502109, + 37.538869539 + ], + [ + -122.576687533, + 37.613537207 + ], + [ + -122.2880486, + 37.562818007 + ], + [ + -122.308150179, + 37.488035566 + ] + ] + ] + }, + "properties": { + "title": "Full Item", + "description": "A sample STAC Item demonstrates an Item that does not have a collection, which is not recommended, but allowed by the spec.", + "datetime": null, + "start_datetime": "2016-05-03T13:22:30Z", + "end_datetime": "2016-05-03T13:27:30Z", + "created": "2016-05-04T00:00:01Z", + "updated": "2017-01-01T00:30:55Z", + "license": "other", + "providers": [ + { + "name": "Remote Data, Inc", + "description": "Producers of awesome spatiotemporal assets", + "roles": [ + "producer", + "processor" + ], + "url": "http://remotedata.it" + } + ], + "platform": "cool_sat2", + "instruments": [ + "cool_sensor_v1" + ], + "view:sun_elevation": 33.4, + "gsd": 0.512, + "cs:type": "scene", + "cs:anomalous_pixels": 0.14, + "cs:earth_sun_distance": 1.014156, + "cs:sat_id": "CS3", + "cs:product_level": "LV1B" + }, + "links": [ + { + "rel": "root", + "href": "./catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "parent", + "href": "./catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.html", + "title": "HTML representation of this STAC Item" + }, + { + "rel": "license", + "type": "text/html", + "href": "http://remotedata.io/license.html", + "title": "Data License for Remote Data, Inc." + } + ], + "assets": { + "analytic": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/analytic.tif", + "title": "4-Band Analytic", + "bands": [ + { + "name": "band1" + }, + { + "name": "band1" + }, + { + "name": "band2" + }, + { + "name": "band3" + } + ] + }, + "thumbnail": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/thumbnail.png", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "udm": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/UDM.tif", + "title": "Unusable Data Mask" + }, + "json-metadata": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/CS3-20160503_132130_04/S3-20160503_132130_04.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/examples/extended-item.json b/examples/extended-item.json index 7b23d2f12..4251d13f0 100644 --- a/examples/extended-item.json +++ b/examples/extended-item.json @@ -1,7 +1,6 @@ { "stac_version": "1.0.0", "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", "https://stac-extensions.github.io/projection/v1.0.0/schema.json", "https://stac-extensions.github.io/scientific/v1.0.0/schema.json", "https://stac-extensions.github.io/view/v1.0.0/schema.json", @@ -120,30 +119,30 @@ "roles": [ "data" ], - "eo:bands": [ + "bands": [ { "name": "band1", - "common_name": "blue", - "center_wavelength": 0.47, - "full_width_half_max": 70 + "eo:common_name": "blue", + "eo:center_wavelength": 0.47, + "eo:full_width_half_max": 70 }, { "name": "band2", - "common_name": "green", - "center_wavelength": 0.56, - "full_width_half_max": 80 + "eo:common_name": "green", + "eo:center_wavelength": 0.56, + "eo:full_width_half_max": 80 }, { "name": "band3", - "common_name": "red", - "center_wavelength": 0.645, - "full_width_half_max": 90 + "eo:common_name": "red", + "eo:center_wavelength": 0.645, + "eo:full_width_half_max": 90 }, { "name": "band4", - "common_name": "nir", - "center_wavelength": 0.8, - "full_width_half_max": 152 + "eo:common_name": "nir", + "eo:center_wavelength": 0.8, + "eo:full_width_half_max": 152 } ] }, @@ -162,24 +161,24 @@ "roles": [ "visual" ], - "eo:bands": [ + "bands": [ { "name": "band3", - "common_name": "red", - "center_wavelength": 0.645, - "full_width_half_max": 90 + "eo:common_name": "red", + "eo:center_wavelength": 0.645, + "eo:full_width_half_max": 90 }, { "name": "band2", - "common_name": "green", - "center_wavelength": 0.56, - "full_width_half_max": 80 + "eo:common_name": "green", + "eo:center_wavelength": 0.56, + "eo:full_width_half_max": 80 }, { "name": "band1", - "common_name": "blue", - "center_wavelength": 0.47, - "full_width_half_max": 70 + "eo:common_name": "blue", + "eo:center_wavelength": 0.47, + "eo:full_width_half_max": 70 } ] }, diff --git a/examples/extensions-collection/proj-example/proj-example.json b/examples/extensions-collection/proj-example/proj-example.json index 09b7986da..c6faa88dd 100644 --- a/examples/extensions-collection/proj-example/proj-example.json +++ b/examples/extensions-collection/proj-example/proj-example.json @@ -1,285 +1,285 @@ -{ - "type": "Feature", - "stac_version": "1.0.0", - "id": "proj-example", - "properties": { - "datetime": "2018-10-01T01:08:32.033000Z", - "proj:epsg": 32614, - "proj:wkt2": "PROJCS[\"WGS 84 / UTM zone 14N\",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.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-99],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32614\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", - "proj:projjson": { - "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", - "type": "ProjectedCRS", - "name": "WGS 84 / UTM zone 14N", - "base_crs": { - "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 - } - }, - "conversion": { - "name": "UTM zone 14N", - "method": { - "name": "Transverse Mercator", - "id": { - "authority": "EPSG", - "code": 9807 - } - }, - "parameters": [ - { - "name": "Latitude of natural origin", - "value": 0, - "unit": "degree", - "id": { - "authority": "EPSG", - "code": 8801 - } - }, - { - "name": "Longitude of natural origin", - "value": -99, - "unit": "degree", - "id": { - "authority": "EPSG", - "code": 8802 - } - }, - { - "name": "Scale factor at natural origin", - "value": 0.9996, - "unit": "unity", - "id": { - "authority": "EPSG", - "code": 8805 - } - }, - { - "name": "False easting", - "value": 500000, - "unit": "metre", - "id": { - "authority": "EPSG", - "code": 8806 - } - }, - { - "name": "False northing", - "value": 0, - "unit": "metre", - "id": { - "authority": "EPSG", - "code": 8807 - } - } - ] - }, - "coordinate_system": { - "subtype": "Cartesian", - "axis": [ - { - "name": "Easting", - "abbreviation": "E", - "direction": "east", - "unit": "metre" - }, - { - "name": "Northing", - "abbreviation": "N", - "direction": "north", - "unit": "metre" - } - ] - }, - "area": "World - N hemisphere - 102°W to 96°W - by country", - "bbox": { - "south_latitude": 0, - "west_longitude": -102, - "north_latitude": 84, - "east_longitude": -96 - }, - "id": { - "authority": "EPSG", - "code": 32614 - } - }, - "proj:geometry": { - "coordinates": [ - [ - [ - 169200, - 3712800 - ], - [ - 403200, - 3712800 - ], - [ - 403200, - 3951000 - ], - [ - 169200, - 3951000 - ], - [ - 169200, - 3712800 - ] - ] - ], - "type": "Polygon" - }, - "proj:bbox": [ - 169200, - 3712800, - 403200, - 3951000 - ], - "proj:centroid": { - "lat": 34.595302781575604, - "lon": -101.34448382627504 - }, - "proj:shape": [ - 8391, - 8311 - ], - "proj:transform": [ - 30, - 0, - 224985, - 0, - -30, - 6790215, - 0, - 0, - 1 - ] - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 152.52758, - 60.63437 - ], - [ - 149.1755, - 61.19016 - ], - [ - 148.13933, - 59.51584 - ], - [ - 151.33786, - 58.97792 - ], - [ - 152.52758, - 60.63437 - ] - ] - ] - }, - "links": [ - { - "rel": "root", - "href": "../../catalog.json", - "type": "application/json", - "title": "Example Catalog" - }, - { - "rel": "parent", - "href": "../collection.json", - "type": "application/json", - "title": "Collection of Extension Items" - }, - { - "rel": "collection", - "href": "../collection.json", - "type": "application/json", - "title": "Collection of Extension Items" - } - ], - "assets": { - "B1": { - "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B1.TIF", - "type": "image/tiff; application=geotiff", - "title": "Band 1 (coastal)", - "eo:bands": [ - { - "name": "B1", - "common_name": "coastal", - "center_wavelength": 0.44, - "full_width_half_max": 0.02 - } - ] - }, - "B8": { - "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B8.TIF", - "type": "image/tiff; application=geotiff", - "title": "Band 8 (panchromatic)", - "eo:bands": [ - { - "name": "B8", - "center_wavelength": 0.59, - "full_width_half_max": 0.18 - } - ], - "proj:shape": [ - 16781, - 16621 - ], - "proj:transform": [ - 15, - 0, - 224992.5, - 0, - -15, - 6790207.5, - 0, - 0, - 1 - ] - } - }, - "bbox": [ - 148.13933, - 59.51584, - 152.52758, - 60.63437 - ], - "stac_extensions": [ - "https://stac-extensions.github.io/eo/v1.0.0/schema.json", - "https://stac-extensions.github.io/projection/v1.0.0/schema.json" - ], - "collection": "landsat-8-l1" -} +{ + "type": "Feature", + "stac_version": "1.0.0", + "id": "proj-example", + "properties": { + "datetime": "2018-10-01T01:08:32.033000Z", + "proj:epsg": 32614, + "proj:wkt2": "PROJCS[\"WGS 84 / UTM zone 14N\",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.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-99],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],AUTHORITY[\"EPSG\",\"32614\"],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]", + "proj:projjson": { + "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", + "type": "ProjectedCRS", + "name": "WGS 84 / UTM zone 14N", + "base_crs": { + "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 + } + }, + "conversion": { + "name": "UTM zone 14N", + "method": { + "name": "Transverse Mercator", + "id": { + "authority": "EPSG", + "code": 9807 + } + }, + "parameters": [ + { + "name": "Latitude of natural origin", + "value": 0, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8801 + } + }, + { + "name": "Longitude of natural origin", + "value": -99, + "unit": "degree", + "id": { + "authority": "EPSG", + "code": 8802 + } + }, + { + "name": "Scale factor at natural origin", + "value": 0.9996, + "unit": "unity", + "id": { + "authority": "EPSG", + "code": 8805 + } + }, + { + "name": "False easting", + "value": 500000, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8806 + } + }, + { + "name": "False northing", + "value": 0, + "unit": "metre", + "id": { + "authority": "EPSG", + "code": 8807 + } + } + ] + }, + "coordinate_system": { + "subtype": "Cartesian", + "axis": [ + { + "name": "Easting", + "abbreviation": "E", + "direction": "east", + "unit": "metre" + }, + { + "name": "Northing", + "abbreviation": "N", + "direction": "north", + "unit": "metre" + } + ] + }, + "area": "World - N hemisphere - 102°W to 96°W - by country", + "bbox": { + "south_latitude": 0, + "west_longitude": -102, + "north_latitude": 84, + "east_longitude": -96 + }, + "id": { + "authority": "EPSG", + "code": 32614 + } + }, + "proj:geometry": { + "coordinates": [ + [ + [ + 169200, + 3712800 + ], + [ + 403200, + 3712800 + ], + [ + 403200, + 3951000 + ], + [ + 169200, + 3951000 + ], + [ + 169200, + 3712800 + ] + ] + ], + "type": "Polygon" + }, + "proj:bbox": [ + 169200, + 3712800, + 403200, + 3951000 + ], + "proj:centroid": { + "lat": 34.595302781575604, + "lon": -101.34448382627504 + }, + "proj:shape": [ + 8391, + 8311 + ], + "proj:transform": [ + 30, + 0, + 224985, + 0, + -30, + 6790215, + 0, + 0, + 1 + ] + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 152.52758, + 60.63437 + ], + [ + 149.1755, + 61.19016 + ], + [ + 148.13933, + 59.51584 + ], + [ + 151.33786, + 58.97792 + ], + [ + 152.52758, + 60.63437 + ] + ] + ] + }, + "links": [ + { + "rel": "root", + "href": "../../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "parent", + "href": "../collection.json", + "type": "application/json", + "title": "Collection of Extension Items" + }, + { + "rel": "collection", + "href": "../collection.json", + "type": "application/json", + "title": "Collection of Extension Items" + } + ], + "assets": { + "B1": { + "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B1.TIF", + "type": "image/tiff; application=geotiff", + "title": "Band 1 (coastal)", + "bands": [ + { + "name": "B1", + "eo:common_name": "coastal", + "eo:center_wavelength": 0.44, + "eo:full_width_half_max": 0.02 + } + ] + }, + "B8": { + "href": "https://landsat-pds.s3.amazonaws.com/c1/L8/107/018/LC08_L1TP_107018_20181001_20181001_01_RT/LC08_L1TP_107018_20181001_20181001_01_RT_B8.TIF", + "type": "image/tiff; application=geotiff", + "title": "Band 8 (panchromatic)", + "bands": [ + { + "name": "B8", + "eo:center_wavelength": 0.59, + "eo:full_width_half_max": 0.18 + } + ], + "proj:shape": [ + 16781, + 16621 + ], + "proj:transform": [ + 15, + 0, + 224992.5, + 0, + -15, + 6790207.5, + 0, + 0, + 1 + ] + } + }, + "bbox": [ + 148.13933, + 59.51584, + 152.52758, + 60.63437 + ], + "stac_extensions": [ + "https://stac-extensions.github.io/eo/v2.0.0-beta.1/schema.json", + "https://stac-extensions.github.io/projection/v1.0.0/schema.json" + ], + "collection": "landsat-8-l1" +} diff --git a/extensions/README.md b/extensions/README.md index 59dd2fac2..b3233aabc 100644 --- a/extensions/README.md +++ b/extensions/README.md @@ -72,11 +72,11 @@ Collection. Asset should contain the extension identifier. - If a Collection [summary](../collection-spec/collection-spec.md#summaries) contains Item fields that implement an extension, then the `stac_extensions` array of that Collection should list the extension identifier. For example, if a Collection `summaries` field - contains a summary of `eo:bands`, then that Collection should have the EO extension JSON Schema URL in the `stac_extensions` array. + contains a summary of `eo:cloud_cover`, then that Collection should have the EO extension JSON Schema URL in the `stac_extensions` array. - If an object implements an extension that results in fields from a separate extension to be referenced, then the latter extension identifier should be included in the `stac_extensions` array for that object. For example, if a Collection implements the [item_assets](https://github.com/stac-extensions/item-assets) extension, and in the `item_assets` field there is an Asset Definition - which includes `eo:bands`, then the EO extension identifier should be listed in that Collection's `stac_extensions`. + which includes `proj:wkt2`, then the Projection extension identifier should be listed in that Collection's `stac_extensions`. ## Community Extensions @@ -132,8 +132,8 @@ can theoretically add fields anywhere in JSON there are some conventions as to w 1. Additional attributes relating to an [Item](../item-spec/item-spec.md) should be added into the Item Properties object, rather than directly in the Item object. 2. In general, additional attributes that apply to an Item Asset should also be allowed in Item Properties and vice-versa. - For example, the `eo:bands` attribute may be used in Item Properties to describe the aggregation of all bands available in - the Item Asset objects contained in the Item, but may also be used in an individual Item Asset to describe only the bands available in that asset. + For example, the `gsd` attribute may be used in Item Properties to describe the best GSD available in + the Item Asset objects contained in the Item, but may also be used in an individual Item Asset to describe only the specific GSD of that asset. 3. Additional attributes relating to a [Catalog](../catalog-spec/catalog-spec.md) or [Collection](../collection-spec/collection-spec.md) should be added to the top-level of the object. 4. All other objects can generally also be extended, e.g. Link Objects, Provider Objects, Band Objects, etc. @@ -220,4 +220,4 @@ there are multiple options (tl;dr: option **3** is recommended): This rules only applies to the fields defined directly for the Item's `properties`. For fields and structures defined on other levels (e.g. in the root of an Item or in an array), extension authors can freely define the structure. -So an array of objects such as the `eo:bands` are fine to use, but keep in mind that the drawbacks mentioned above usually still apply. +So an array of objects such as the `bands` are fine to use, but keep in mind that the drawbacks mentioned above usually still apply. diff --git a/item-spec/common-metadata.md b/item-spec/common-metadata.md index da36a6bcf..1fd45ada3 100644 --- a/item-spec/common-metadata.md +++ b/item-spec/common-metadata.md @@ -8,11 +8,8 @@ or [Collection Asset](../collection-spec/collection-spec.md#asset-object). - [STAC Common Metadata](#stac-common-metadata) - [Basics](#basics) - [Date and Time](#date-and-time) - - [Date and Time Range](#date-and-time-range) - [Licensing](#licensing) - [Provider](#provider) - - [Provider Object](#provider-object) - - [roles](#roles) - [Instrument](#instrument) - [Additional Field Information](#additional-field-information) - [platform](#platform) @@ -20,6 +17,8 @@ or [Collection Asset](../collection-spec/collection-spec.md#asset-object). - [constellation](#constellation) - [mission](#mission) - [gsd](#gsd) + - [Bands](#bands) + - [Data Values](#data-values) - [Relation types](#relation-types) - [Hierarchical relations](#hierarchical-relations) - [Self relation](#self-relation) @@ -219,6 +218,119 @@ PlanetScope Ortho Tile Product has an `gsd` of 3.7 (or 4 if rounding), even thou For example, one might choose for WorldView-2 the Multispectral 20° off-nadir value of 2.07 and for WorldView-3 the Multispectral 20° off-nadir value of 1.38. +## Bands + +| Field Name | Type | Description | +| ---------- | ------------------------------ | ------------------------------------------------------------------------------- | +| bands | \[[Band Object](#band-object)] | An array of available bands where each object is a [Band Object](#band-object). | + +The `bands` array is used to describe the available bands in a STAC entity or Asset. +This fields describes the general construct of a band or layer, which doesn't necessarily need to be a spectral band. +By adding fields from extensions you can indicate that a band, for example, is + +- a spectral band ([EO extension](https://github.com/stac-extensions/eo)), +- a band with classification results ([classification extension](https://github.com/stac-extensions/classification)), +- a band with quality information such as cloud cover probabilities, +- etc. + +Please refer to the [Bands best practices](../best-practices.md#bands) for more details. + +> \[!NOTE] +> This property is the successor of the `eo:bands` and `raster:bands` fields, which has been present in previous versions of these extensions. +> The behavior is very similar and they can be migrated easily. +> Usually, you can simply merge the each object on a by-index basis. +> Nevertheless, you should consider deduplicating properties with the same values across all bands to the asset level +> (see the [best practices](../best-practices.md#multiple-bands)). +> For some fields you need to add the extension prefix of the `eo` or `raster` extension to the property name though. +> See the [Band migration best practice](../best-practices.md#band-migration) for details. + +### Band Object + +Specifically defined for the Band Object is just a single property `name`, which serves as a unique identifier. +You can add additional fields from the common metadata such as a [`description`](#basics) or the [value-related](#data-values) properties. + +| Field Name | Type | Description | +| ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | string | The name of the band (e.g., "B01", "B8", "band2", "red"), which should be unique across all bands defined in the list of bands. This is typically the name the data provider uses for the band. | +| description | string | Description to fully explain the band. [CommonMark 0.29](http://commonmark.org/) syntax MAY be used for rich text representation. | + +A Band Object must contain at least one property, which is not necessarily one of the properties +defined here and can be a property from an extension or common metadata. + +## Data Values + +Adds metadata about the data values or measurement values contained in the entity that is described by +the object these fields get added to (e.g., an asset or a band). +These fields will often be combined with extensions that group data values into a "unit" or "chunk", e.g., +a band or layer in a file (`raster` and `eo` extensions), +a column in a table (`table` extension), +or dimensions in a datacube (`datacube` extension). + +| Field Name | Type | Description | +| ---------- | --------------------------------------- | ------------------------------------------------------ | +| nodata | number\|string | Value used to identify no-data, see [below](#no-data). | +| data_type | string | The data type of the values, see [below](#data-types). | +| statistics | [Statistics Object](#statistics-object) | Statistics of all the values. | +| unit | string | Unit of measurement of the value, see [below](#units). | + +### No-data + +The no-data value must be provided either as: + +- a number +- a string: + - `nan` - [NaN](https://de.wikipedia.org/wiki/NaN) (not a number) as defined in IEEE-754 + - `inf` - Positive Infinity + - `-inf` - Negative Infinity + +### Units + +It is STRONGLY RECOMMENDED to provide units in one of the following two formats: + +- [UCUM](https://ucum.org/): The unit code that is compliant to the UCUM specification. +- [UDUNITS-2](https://ncics.org/portfolio/other-resources/udunits2/): The unit symbol if available, otherwise the singular unit name. + +### Statistics Object + +| Field Name | Type | Description | +| ------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| minimum | number | minimum value of the values in the band. If not present, the minimum value of the given data type or negative infinity can be assumed. | +| maximum | number | maximum value of the values in the band. If not present, the maximum value of the given data type or positive infinity can be assumed. | +| mean | number | mean value of all the values in the band | +| stddev | number | standard deviation value of the values in the band | +| count | integer | Total number of all data values (>= 0) | +| valid_percent | number | Percentage of valid (not `nodata`) values (0-100) | + +### Data Types + +The data type gives information about the values. +This can be used to indicate the (maximum) range of numerical values expected. +For example `uint8` indicates that the numbers are in a range between 0 and 255, +they can never be smaller or larger. This can help to pick the optimal numerical +data type when reading the files to keep memory consumption low. +Nevertheless, it doesn't necessarily mean that the expected values fill the whole range. +For example, there can be use cases for `uint8` that just use the numbers 0 to 10 for example. +Through the [Statistics Object](#statistics-object) it is possible to specify an exact value range so +that visualizations can be optimized. +The allowed values for `data_type` are: + +- `int8`: 8-bit integer +- `int16`: 16-bit integer +- `int32`: 32-bit integer +- `int64`: 64-bit integer +- `uint8`: unsigned 8-bit integer (common for 8-bit RGB PNG's) +- `uint16`: unsigned 16-bit integer +- `uint32`: unsigned 32-bit integer +- `uint64`: unsigned 64-bit integer +- `float16`: 16-bit float +- `float32`: 32-bit float +- `float64`: 64-big float +- `cint16`: 16-bit complex integer +- `cint32`: 32-bit complex integer +- `cfloat32`: 32-bit complex float +- `cfloat64`: 64-bit complex float +- `other`: Other data type than the ones listed above (e.g. boolean, string, higher precision numbers) + ## Relation types STAC Entities use a variety of `rel` types in the link object, diff --git a/item-spec/item-spec.md b/item-spec/item-spec.md index 17d656045..7e51135c1 100644 --- a/item-spec/item-spec.md +++ b/item-spec/item-spec.md @@ -181,7 +181,7 @@ fields but it is recommended to add multiple fields for related values instead o e.g., two fields `view:azimuth` and `view:off_nadir` instead of a field `view` with an object value containing the two fields. The convention (as used within Extensions) is for related fields to use a common prefix on the field names to group them, e.g. `view`. A nested data structure should -only be used when the data itself is nested, as with `eo:bands`. +only be used when the data itself is nested, as with `bands`. ### Link Object @@ -284,7 +284,7 @@ should be used sparingly.** It is primarily used to define properties at the Ass the data instead of for searching. For example, `gsd` defined for an Item represents the best Ground Sample Distance (resolution) for the data within the Item. -However, some assets may be lower resolution and thus have a higher `gsd`. The `eo:bands` field from the EO extension defines +However, some assets may be lower resolution and thus have a higher `gsd`. The `bands` field in combination with the EO extension defines an array of spectral bands. However, it may be useful instead to specify the bands that are used in a particular asset. For an example see the [sentinel2-sample](https://github.com/stac-utils/stac-examples/blob/main/sentinel2/sentinel2-sample.json). @@ -294,7 +294,7 @@ Band 5 and others have a `gsd` of 20m, so that asset specifies the `gsd` as well one asset. The example also includes reduced resolution versions of files included as assets, using `gsd` to represent the proper resolution. -For `eo:bands`, it could be put in Item properties as an array of all the bands, but in this case it's not. Instead, +For `bands`, it could be put in Item properties as an array of all the bands, but in this case it's not. Instead, the assets each define an array containing the spectral band information for that asset (in the order the bands appear in the file). diff --git a/item-spec/json-schema/bands.json b/item-spec/json-schema/bands.json new file mode 100644 index 000000000..f87d56187 --- /dev/null +++ b/item-spec/json-schema/bands.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/bands.json", + "title": "Bands Field", + "type": "object", + "properties": { + "bands": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "allOf": [ + { + "$ref": "common.json" + } + ] + } + } + } + } \ No newline at end of file diff --git a/item-spec/json-schema/common.json b/item-spec/json-schema/common.json index 12fa35f66..66520e61d 100644 --- a/item-spec/json-schema/common.json +++ b/item-spec/json-schema/common.json @@ -8,9 +8,15 @@ { "$ref": "basics.json" }, + { + "$ref": "bands.json" + }, { "$ref": "datetime.json" }, + { + "$ref": "data-values.json" + }, { "$ref": "instrument.json" }, diff --git a/item-spec/json-schema/data-values.json b/item-spec/json-schema/data-values.json new file mode 100644 index 000000000..ac82815a3 --- /dev/null +++ b/item-spec/json-schema/data-values.json @@ -0,0 +1,84 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/data-values.json#", + "title": "Fields related to data values", + "type": "object", + "properties": { + "data_type": { + "title": "Data type of the values", + "type": "string", + "enum": [ + "int8", + "int16", + "int32", + "int64", + "uint8", + "uint16", + "uint32", + "uint64", + "float16", + "float32", + "float64", + "cint16", + "cint32", + "cfloat32", + "cfloat64", + "other" + ] + }, + "nodata": { + "title": "No data value", + "oneOf": [ + { + "type": "number" + }, + { + "type": "string", + "enum": [ + "nan", + "inf", + "-inf" + ] + } + ] + }, + "statistics": { + "title": "Statistics", + "type": "object", + "minProperties": 1, + "properties": { + "minimum": { + "title": "Minimum value of all the data values", + "type": "number" + }, + "maximum": { + "title": "Maximum value of all the data values", + "type": "number" + }, + "mean": { + "title": "Mean value of all the data values", + "type": "number" + }, + "stddev": { + "title": "Standard deviation value of all the data values", + "type": "number" + }, + "count": { + "title": "Total number of all data values", + "type": "integer", + "minimum": 0 + }, + "valid_percent": { + "title": "Percentage of valid (not nodata) values", + "type": "number", + "minimum": 0, + "maximum": 100 + } + } + }, + "unit": { + "title": "Unit denomination of the data value", + "type": "string" + } + } +} \ No newline at end of file diff --git a/item-spec/json-schema/item.json b/item-spec/json-schema/item.json index 232dd7de5..5d814299c 100644 --- a/item-spec/json-schema/item.json +++ b/item-spec/json-schema/item.json @@ -129,42 +129,90 @@ ] } }, - "if": { - "properties": { - "links": { - "contains": { - "required": [ - "rel" - ], - "properties": { - "rel": { - "const": "collection" + "$comment": "Rules enforcement for STAC Item", + "allOf": [ + { + "if": { + "properties": { + "links": { + "contains": { + "required": [ + "rel" + ], + "properties": { + "rel": { + "const": "collection" + } + } } } } + }, + "then": { + "required": [ + "collection" + ], + "properties": { + "collection": { + "title": "Collection ID", + "description": "The ID of the STAC Collection this Item references to.", + "type": "string", + "minLength": 1 + } + } + }, + "else": { + "properties": { + "collection": { + "not": {} + } + } } - } - }, - "then": { - "required": [ - "collection" - ], - "properties": { - "collection": { - "title": "Collection ID", - "description": "The ID of the STAC Collection this Item references to.", - "type": "string", - "minLength": 1 - } - } - }, - "else": { - "properties": { - "collection": { - "not": {} + }, + { + "$comment": "The if-then-else below checks whether the bands field is given in assets or not. If not, allows bands in properties (then), otherwise, disallows bands in properties (else).", + "if": { + "required": [ + "assets" + ], + "properties": { + "assets": { + "type": "object", + "additionalProperties": { + "properties": { + "bands": false + } + } + } + } + }, + "then": { + "properties": { + "properties": { + "anyOf": [ + { + "$ref": "bands.json" + }, + { + "properties": { + "bands": false + } + } + ] + } + } + }, + "else": { + "properties": { + "properties": { + "properties": { + "bands": false + } + } + } } } - } + ] } ] },