diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt index 81b8326760a7..c90f54f23b90 100644 --- a/tests/src/core/CMakeLists.txt +++ b/tests/src/core/CMakeLists.txt @@ -181,6 +181,7 @@ set(TESTS testqgsspatialindexkdbush.cpp testqgssqliteexpressioncompiler.cpp testqgssqliteutils.cpp + testqgsstac.cpp testqgsstackeddiagram.cpp testqgsrelation.cpp testqgsstatisticalsummary.cpp diff --git a/tests/src/core/testqgsstac.cpp b/tests/src/core/testqgsstac.cpp new file mode 100644 index 000000000000..0217b66633a0 --- /dev/null +++ b/tests/src/core/testqgsstac.cpp @@ -0,0 +1,153 @@ +/*************************************************************************** + testqgsstac.cpp + ------------------------- + begin : August 2024 + copyright : (C) 2024 by Stefanos Natsis + email : uclaros at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgstest.h" +#include +#include + +//qgis includes... +#include "qgsstaccontroller.h" +#include "qgsstaccatalog.h" +#include "qgsstaccollection.h" +#include "qgsstacitem.h" +#include "qgsapplication.h" +#include "qgsproject.h" +#include "qgis.h" + +/** + * \ingroup UnitTests + * This is a unit test for STAC + */ +class TestQgsStac : public QObject +{ + Q_OBJECT + + public: + TestQgsStac() = default; + + private slots: + void initTestCase();// will be called before the first testfunction is executed. + void cleanupTestCase();// will be called after the last testfunction was executed. + void init() {} // will be called before each testfunction is executed. + void cleanup() {} // will be called after every testfunction. + + void testParseLocalCatalog(); + void testParseLocalCollection(); + void testParseLocalItem(); + + private: + QString mDataDir; +}; + +void TestQgsStac::initTestCase() +{ + // init QGIS's paths - true means that all path will be inited from prefix + QgsApplication::init(); + QgsApplication::initQgis(); + QgsApplication::showSettings(); + mDataDir = QStringLiteral( "%1/stac/" ).arg( TEST_DATA_DIR ); +} + +void TestQgsStac::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsStac::testParseLocalCatalog() +{ + const QString fileName = mDataDir + QStringLiteral( "catalog.json" ); + QgsStacController c; + QgsStacObject *obj = c.fetchStacObject( QStringLiteral( "file://%1" ).arg( fileName ) ); + QVERIFY( obj ); + QCOMPARE( obj->type(), QgsStacObject::Type::Catalog ); + QgsStacCatalog *cat = dynamic_cast< QgsStacCatalog * >( obj ); + + QVERIFY( cat ); + QVERIFY( cat->isValid() ); + QCOMPARE( cat->id(), QLatin1String( "examples" ) ); + QCOMPARE( cat->stacVersion(), QLatin1String( "1.0.0" ) ); + QCOMPARE( cat->title(), QLatin1String( "Example Catalog" ) ); + QCOMPARE( cat->description(), QLatin1String( "This catalog is a simple demonstration of an example catalog that is used to organize a hierarchy of collections and their items." ) ); + QCOMPARE( cat->links().size(), 6 ); + QVERIFY( cat->stacExtensions().isEmpty() ); + + delete cat; +} + +void TestQgsStac::testParseLocalCollection() +{ + const QString fileName = mDataDir + QStringLiteral( "collection.json" ); + QgsStacController c; + QgsStacObject *obj = c.fetchStacObject( QStringLiteral( "file://%1" ).arg( fileName ) ); + QVERIFY( obj ); + QCOMPARE( obj->type(), QgsStacObject::Type::Collection ); + QgsStacCollection *col = dynamic_cast< QgsStacCollection * >( obj ); + + QVERIFY( col ); + QVERIFY( col->isValid() ); + QCOMPARE( col->id(), QLatin1String( "simple-collection" ) ); + QCOMPARE( col->stacVersion(), QLatin1String( "1.0.0" ) ); + QCOMPARE( col->title(), QLatin1String( "Simple Example Collection" ) ); + QCOMPARE( col->description(), QLatin1String( "A simple collection demonstrating core catalog fields with links to a couple of items" ) ); + QCOMPARE( col->links().size(), 5 ); + QCOMPARE( col->providers().size(), 1 ); + QCOMPARE( col->stacExtensions().size(), 3 ); + QCOMPARE( col->license(), QLatin1String( "CC-BY-4.0" ) ); + QVERIFY( col->assets().isEmpty() ); + + // extent + QgsStacExtent ext( col->extent() ); + QVERIFY( !ext.hasDetailedSpatialExtents() ); + QCOMPARE( ext.spatialExtent().xMinimum(), 172.91173669923782 ); + QCOMPARE( ext.spatialExtent().yMinimum(), 1.3438851951615003 ); + QCOMPARE( ext.spatialExtent().xMaximum(), 172.95469614953714 ); + QCOMPARE( ext.spatialExtent().yMaximum(), 1.3690476620161975 ); + + QVERIFY( !ext.hasDetailedTemporalExtents() ); + QCOMPARE( ext.temporalExtent().begin(), QDateTime::fromString( QStringLiteral( "2020-12-11T22:38:32.125Z" ), Qt::ISODateWithMs ) ); + QCOMPARE( ext.temporalExtent().end(), QDateTime::fromString( QStringLiteral( "2020-12-14T18:02:31.437Z" ), Qt::ISODateWithMs ) ); + + // summaries + QVariantMap sum( col->summaries() ); + QCOMPARE( sum.size(), 9 ); + QCOMPARE( sum.value( QStringLiteral( "platform" ) ).toStringList(), QStringList() << QLatin1String( "cool_sat1" ) << QLatin1String( "cool_sat2" ) ); + + delete col; +} + +void TestQgsStac::testParseLocalItem() +{ + const QString fileName = mDataDir + QStringLiteral( "core-item.json" ); + QgsStacController c; + QgsStacObject *obj = c.fetchStacObject( QStringLiteral( "file://%1" ).arg( fileName ) ); + QVERIFY( obj ); + QCOMPARE( obj->type(), QgsStacObject::Type::Item ); + QgsStacItem *item = dynamic_cast( obj ); + + QVERIFY( item ); + QVERIFY( item->isValid() ); + QCOMPARE( item->id(), QLatin1String( "20201211_223832_CS2" ) ); + QCOMPARE( item->stacVersion(), QLatin1String( "1.0.0" ) ); + QCOMPARE( item->links().size(), 4 ); + QCOMPARE( item->stacExtensions().size(), 0 ); + QCOMPARE( item->assets().size(), 6 ); + + delete item; +} + +QGSTEST_MAIN( TestQgsStac ) +#include "testqgsstac.moc" diff --git a/tests/testdata/stac/README b/tests/testdata/stac/README new file mode 100644 index 000000000000..b2428770d6da --- /dev/null +++ b/tests/testdata/stac/README @@ -0,0 +1,2 @@ +Sample data borrowed from the stac specification: +https://github.com/radiantearth/stac-spec/tree/master/examples diff --git a/tests/testdata/stac/catalog.json b/tests/testdata/stac/catalog.json new file mode 100644 index 000000000000..b5910be3c125 --- /dev/null +++ b/tests/testdata/stac/catalog.json @@ -0,0 +1,43 @@ +{ + "id": "examples", + "type": "Catalog", + "title": "Example Catalog", + "stac_version": "1.0.0", + "description": "This catalog is a simple demonstration of an example catalog that is used to organize a hierarchy of collections and their items.", + "links": [ + { + "rel": "root", + "href": "./catalog.json", + "type": "application/json" + }, + { + "rel": "child", + "href": "./extensions-collection/collection.json", + "type": "application/json", + "title": "Collection Demonstrating STAC Extensions" + }, + { + "rel": "child", + "href": "./collection-only/collection.json", + "type": "application/json", + "title": "Collection with no items (standalone)" + }, + { + "rel": "child", + "href": "./collection-only/collection-with-schemas.json", + "type": "application/json", + "title": "Collection with no items (standalone with JSON Schemas)" + }, + { + "rel": "item", + "href": "./collectionless-item.json", + "type": "application/json", + "title": "Collection with no items (standalone)" + }, + { + "rel": "self", + "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0/examples/catalog.json", + "type": "application/json" + } + ] +} diff --git a/tests/testdata/stac/collection-only/collection-with-schemas.json b/tests/testdata/stac/collection-only/collection-with-schemas.json new file mode 100644 index 000000000000..e0023e239a2c --- /dev/null +++ b/tests/testdata/stac/collection-only/collection-with-schemas.json @@ -0,0 +1,277 @@ +{ + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/eo/v1.0.0/schema.json", + "https://stac-extensions.github.io/sat/v1.0.0/schema.json", + "https://stac-extensions.github.io/view/v1.0.0/schema.json" + ], + "id": "sentinel-2", + "type": "Collection", + "title": "Sentinel-2 MSI: MultiSpectral Instrument, Level-2A", + "description": "The SENTINEL-2 mission is a land monitoring constellation of two satellites each equipped with a MSI (Multispectral Imager) instrument covering 13 spectral bands providing high resolution optical imagery (i.e., 10m, 20m, 60 m) every 10 days with one satellite and 5 days with two satellites", + "license": "proprietary", + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -82.852377834669, + 180, + 82.819463367711 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2017-04-12T02:57:21.459000Z", + "2021-04-22T11:30:12.767000Z" + ] + ] + } + }, + "links": [ + { + "rel": "parent", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "root", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", + "title": "Legal notice on the use of Copernicus Sentinel Data and Service Information" + } + ], + "providers": [ + { + "name": "European Union/ESA/Copernicus", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + }, + { + "name": "AWS", + "roles": [ + "host" + ], + "url": "https://registry.opendata.aws/sentinel-2/" + }, + { + "name": "jeobrowser", + "roles": [ + "processor" + ], + "url": "https://github.com/jjrom/resto" + } + ], + "summaries": { + "datetime": { + "minimum": "2017-04-12T02:57:21Z", + "maximum": "2021-04-22T11:30:12Z" + }, + "instruments": { + "type": "string", + "const": "msi", + "title": "Multispectral Intrument", + "count": 6613431 + }, + "resto:landcover": { + "type": "string", + "oneOf": [ + { + "const": "cultivated", + "title": "Cultivated", + "count": 490750 + }, + { + "const": "desert", + "title": "Desert", + "count": 543120 + }, + { + "const": "flooded", + "title": "Flooded", + "count": 5187 + }, + { + "const": "forest", + "title": "Forest", + "count": 767807 + }, + { + "const": "herbaceous", + "title": "Herbaceous", + "count": 674281 + }, + { + "const": "ice", + "title": "Ice", + "count": 231285 + }, + { + "const": "urban", + "title": "Urban", + "count": 1219 + }, + { + "const": "water", + "title": "Water", + "count": 2303314 + } + ] + }, + "resto:location": { + "type": "string", + "oneOf": [ + { + "const": "tropical", + "title": "Tropical", + "count": 1807474 + }, + { + "const": "southern", + "title": "Southern", + "count": 1671685 + }, + { + "const": "northern", + "title": "Northern", + "count": 4876669 + }, + { + "const": "equatorial", + "title": "Equatorial", + "count": 27302 + }, + { + "const": "coastal", + "title": "Coastal", + "count": 1495516 + } + ] + }, + "platform": { + "type": "string", + "oneOf": [ + { + "const": "sentinel-2b", + "title": "Sentinel 2B", + "count": 3495597 + }, + { + "const": "sentinel-2a", + "title": "Sentinel 2A", + "count": 3117831 + } + ] + }, + "resto:season": { + "type": "integer", + "oneOf": [ + { + "const": 0, + "title": "Winter", + "count": 1621108 + }, + { + "const": 2, + "title": "Summer", + "count": 2279472 + }, + { + "const": 1, + "title": "Spring", + "count": 1577067 + }, + { + "const": 3, + "title": "Autumn", + "count": 1098015 + } + ] + }, + "eo:bands": [ + { + "title": "B1", + "common_name": "coastal", + "center_wavelength": 4.439, + "gsd": 60 + }, + { + "title": "B2", + "common_name": "blue", + "center_wavelength": 4.966, + "gsd": 10 + }, + { + "title": "B3", + "common_name": "green", + "center_wavelength": 5.6, + "gsd": 10 + }, + { + "title": "B4", + "common_name": "red", + "center_wavelength": 6.645, + "gsd": 10 + }, + { + "title": "B5", + "center_wavelength": 7.039, + "gsd": 20 + }, + { + "title": "B6", + "center_wavelength": 7.402, + "gsd": 20 + }, + { + "title": "B7", + "center_wavelength": 7.825, + "gsd": 20 + }, + { + "title": "B8", + "common_name": "nir", + "center_wavelength": 8.351, + "gsd": 10 + }, + { + "title": "B8A", + "center_wavelength": 8.648, + "gsd": 20 + }, + { + "title": "B9", + "center_wavelength": 9.45, + "gsd": 60 + }, + { + "title": "B10", + "center_wavelength": 1.3735, + "gsd": 60 + }, + { + "title": "B11", + "common_name": "swir16", + "center_wavelength": 1.6137, + "gsd": 20 + }, + { + "title": "B12", + "common_name": "swir22", + "center_wavelength": 2.2024, + "gsd": 20 + } + ] + } +} \ No newline at end of file diff --git a/tests/testdata/stac/collection-only/collection.json b/tests/testdata/stac/collection-only/collection.json new file mode 100644 index 000000000000..cc631b485dad --- /dev/null +++ b/tests/testdata/stac/collection-only/collection.json @@ -0,0 +1,233 @@ +{ + "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/projection/v1.0.0/schema.json", + "https://stac-extensions.github.io/view/v1.0.0/schema.json" + ], + "id": "sentinel-2", + "title": "Sentinel-2 MSI: MultiSpectral Instrument, Level-1C", + "description": "Sentinel-2 is a wide-swath, high-resolution, multi-spectral\nimaging mission supporting Copernicus Land Monitoring studies,\nincluding the monitoring of vegetation, soil and water cover,\nas well as observation of inland waterways and coastal areas.\n\nThe Sentinel-2 data contain 13 UINT16 spectral bands representing\nTOA reflectance scaled by 10000. See the [Sentinel-2 User Handbook](https://sentinel.esa.int/documents/247904/685211/Sentinel-2_User_Handbook)\nfor details. In addition, three QA bands are present where one\n(QA60) is a bitmask band with cloud mask information. For more\ndetails, [see the full explanation of how cloud masks are computed.](https://sentinel.esa.int/web/sentinel/technical-guides/sentinel-2-msi/level-1c/cloud-masks)\n\nEach Sentinel-2 product (zip archive) may contain multiple\ngranules. Each granule becomes a separate Earth Engine asset.\nEE asset ids for Sentinel-2 assets have the following format:\nCOPERNICUS/S2/20151128T002653_20151128T102149_T56MNN. Here the\nfirst numeric part represents the sensing date and time, the\nsecond numeric part represents the product generation date and\ntime, and the final 6-character string is a unique granule identifier\nindicating its UTM grid reference (see [MGRS](https://en.wikipedia.org/wiki/Military_Grid_Reference_System)).\n\nFor more details on Sentinel-2 radiometric resoltuon, [see this page](https://earth.esa.int/web/sentinel/user-guides/sentinel-2-msi/resolutions/radiometric).\n", + "license": "proprietary", + "keywords": [ + "copernicus", + "esa", + "eu", + "msi", + "radiance", + "sentinel" + ], + "providers": [ + { + "name": "European Union/ESA/Copernicus", + "roles": [ + "producer", + "licensor" + ], + "url": "https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2015-06-23T00:00:00Z", + null + ] + ] + } + }, + "assets": { + "metadata_iso_19139": { + "roles": [ + "metadata", + "iso-19139" + ], + "href": "https://storage.googleapis.com/open-cogs/stac-examples/sentinel-2-iso-19139.xml", + "title": "ISO 19139 metadata", + "type": "application/vnd.iso.19139+xml" + } + }, + "summaries": { + "datetime": { + "minimum": "2015-06-23T00:00:00Z", + "maximum": "2019-07-10T13:44:56Z" + }, + "platform": [ + "sentinel-2a", + "sentinel-2b" + ], + "constellation": [ + "sentinel-2" + ], + "instruments": [ + "msi" + ], + "view:off_nadir": { + "minimum": 0, + "maximum": 100 + }, + "view:sun_elevation": { + "minimum": 6.78, + "maximum": 89.9 + }, + "gsd": [ + 10, + 30, + 60 + ], + "proj:epsg": [ + 32601, + 32602, + 32603, + 32604, + 32605, + 32606, + 32607, + 32608, + 32609, + 32610, + 32611, + 32612, + 32613, + 32614, + 32615, + 32616, + 32617, + 32618, + 32619, + 32620, + 32621, + 32622, + 32623, + 32624, + 32625, + 32626, + 32627, + 32628, + 32629, + 32630, + 32631, + 32632, + 32633, + 32634, + 32635, + 32636, + 32637, + 32638, + 32639, + 32640, + 32641, + 32642, + 32643, + 32644, + 32645, + 32646, + 32647, + 32648, + 32649, + 32650, + 32651, + 32652, + 32653, + 32654, + 32655, + 32656, + 32657, + 32658, + 32659, + 32660 + ], + "eo:bands": [ + { + "name": "B1", + "common_name": "coastal", + "center_wavelength": 4.439 + }, + { + "name": "B2", + "common_name": "blue", + "center_wavelength": 4.966 + }, + { + "name": "B3", + "common_name": "green", + "center_wavelength": 5.6 + }, + { + "name": "B4", + "common_name": "red", + "center_wavelength": 6.645 + }, + { + "name": "B5", + "center_wavelength": 7.039 + }, + { + "name": "B6", + "center_wavelength": 7.402 + }, + { + "name": "B7", + "center_wavelength": 7.825 + }, + { + "name": "B8", + "common_name": "nir", + "center_wavelength": 8.351 + }, + { + "name": "B8A", + "center_wavelength": 8.648 + }, + { + "name": "B9", + "center_wavelength": 9.45 + }, + { + "name": "B10", + "center_wavelength": 1.3735 + }, + { + "name": "B11", + "common_name": "swir16", + "center_wavelength": 1.6137 + }, + { + "name": "B12", + "common_name": "swir22", + "center_wavelength": 2.2024 + } + ] + }, + "links": [ + { + "rel": "parent", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "root", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "license", + "href": "https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf", + "title": "Legal notice on the use of Copernicus Sentinel Data and Service Information" + } + ] +} diff --git a/tests/testdata/stac/collection.json b/tests/testdata/stac/collection.json new file mode 100644 index 000000000000..07643b6007f4 --- /dev/null +++ b/tests/testdata/stac/collection.json @@ -0,0 +1,112 @@ +{ + "id": "simple-collection", + "type": "Collection", + "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/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", + "title": "Simple Example Collection" + }, + { + "rel": "item", + "href": "./simple-item.json", + "type": "application/geo+json", + "title": "Simple Item" + }, + { + "rel": "item", + "href": "./core-item.json", + "type": "application/geo+json", + "title": "Core Item" + }, + { + "rel": "item", + "href": "./extended-item.json", + "type": "application/geo+json", + "title": "Extended Item" + }, + { + "rel": "self", + "href": "https://raw.githubusercontent.com/radiantearth/stac-spec/v1.0.0/examples/collection.json", + "type": "application/json" + } + ] +} diff --git a/tests/testdata/stac/collectionless-item.json b/tests/testdata/stac/collectionless-item.json new file mode 100644 index 000000000000..6e7beab93e46 --- /dev/null +++ b/tests/testdata/stac/collectionless-item.json @@ -0,0 +1,144 @@ +{ + "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": "various", + "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" + } + } +} diff --git a/tests/testdata/stac/core-item.json b/tests/testdata/stac/core-item.json new file mode 100644 index 000000000000..d07cc8df69bc --- /dev/null +++ b/tests/testdata/stac/core-item.json @@ -0,0 +1,125 @@ +{ + "stac_version": "1.0.0", + "stac_extensions": [], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "title": "Core Item", + "description": "A sample STAC Item that includes examples of all common metadata", + "datetime": null, + "start_datetime": "2020-12-11T22:38:32.125Z", + "end_datetime": "2020-12-11T22:38:32.327Z", + "created": "2020-12-12T01:48:13.725Z", + "updated": "2020-12-12T01:48:13.725Z", + "platform": "cool_sat1", + "instruments": [ + "cool_sensor_v1" + ], + "constellation": "ion", + "mission": "collection 5624", + "gsd": 0.512 + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "parent", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html", + "title": "HTML version of this STAC Item" + } + ], + "assets": { + "analytic": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "4-Band Analytic", + "roles": [ + "data" + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ] + }, + "udm": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif", + "title": "Unusable Data Mask", + "type": "image/tiff; application=geotiff;" + }, + "json-metadata": { + "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/tests/testdata/stac/extended-item.json b/tests/testdata/stac/extended-item.json new file mode 100644 index 000000000000..59f2de1f3972 --- /dev/null +++ b/tests/testdata/stac/extended-item.json @@ -0,0 +1,199 @@ +{ + "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", + "https://stac-extensions.github.io/remote-data/v1.0.0/schema.json" + ], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "title": "Extended Item", + "description": "A sample STAC Item that includes a variety of examples from the stable extensions", + "datetime": "2020-12-14T18:02:31.437000Z", + "created": "2020-12-15T01:48:13.725Z", + "updated": "2020-12-15T01:48:13.725Z", + "platform": "cool_sat2", + "instruments": [ + "cool_sensor_v2" + ], + "gsd": 0.66, + "eo:cloud_cover": 1.2, + "proj:epsg": 32659, + "proj:shape": [ + 5558, + 9559 + ], + "proj:transform": [ + 0.5, + 0, + 712710, + 0, + -0.5, + 151406, + 0, + 0, + 1 + ], + "view:sun_elevation": 54.9, + "view:off_nadir": 3.8, + "view:sun_azimuth": 135.7, + "rd:type": "scene", + "rd:anomalous_pixels": 0.14, + "rd:earth_sun_distance": 1.014156, + "rd:sat_id": "cool_sat2", + "rd:product_level": "LV3A", + "sci:doi": "10.5061/dryad.s2v81.2/27.2" + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "parent", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "alternate", + "type": "text/html", + "href": "http://remotedata.io/catalog/20201211_223832_CS2/index.html", + "title": "HTML version of this STAC Item" + } + ], + "assets": { + "analytic": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "4-Band Analytic", + "roles": [ + "data" + ], + "eo:bands": [ + { + "name": "band1", + "common_name": "blue", + "center_wavelength": 470, + "full_width_half_max": 70 + }, + { + "name": "band2", + "common_name": "green", + "center_wavelength": 560, + "full_width_half_max": 80 + }, + { + "name": "band3", + "common_name": "red", + "center_wavelength": 645, + "full_width_half_max": 90 + }, + { + "name": "band4", + "common_name": "nir", + "center_wavelength": 800, + "full_width_half_max": 152 + } + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/png", + "roles": [ + "thumbnail" + ] + }, + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ], + "eo:bands": [ + { + "name": "band3", + "common_name": "red", + "center_wavelength": 645, + "full_width_half_max": 90 + }, + { + "name": "band2", + "common_name": "green", + "center_wavelength": 560, + "full_width_half_max": 80 + }, + { + "name": "band1", + "common_name": "blue", + "center_wavelength": 470, + "full_width_half_max": 70 + } + ] + }, + "udm": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2_analytic_udm.tif", + "title": "Unusable Data Mask", + "type": "image/tiff; application=geotiff;" + }, + "json-metadata": { + "href": "http://remotedata.io/catalog/20201211_223832_CS2/extended-metadata.json", + "title": "Extended Metadata", + "type": "application/json", + "roles": [ + "metadata" + ] + }, + "ephemeris": { + "href": "http://cool-sat.com/catalog/20201211_223832_CS2/20201211_223832_CS2.EPH", + "title": "Satellite Ephemeris Metadata" + } + } +} diff --git a/tests/testdata/stac/extensions-collection/collection.json b/tests/testdata/stac/extensions-collection/collection.json new file mode 100644 index 000000000000..bfbc3c1e58bf --- /dev/null +++ b/tests/testdata/stac/extensions-collection/collection.json @@ -0,0 +1,68 @@ +{ + "id": "extensions-collection", + "type": "Collection", + "stac_version": "1.0.0", + "description": "A heterogenous collection containing deeper examples of various extensions", + "links": [ + { + "rel": "parent", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "root", + "href": "../catalog.json", + "type": "application/json", + "title": "Example Catalog" + }, + { + "rel": "item", + "href": "./proj-example/proj-example.json", + "title": "Proj extension example" + }, + { + "rel": "license", + "href": "https://remotedata.io/license.html", + "title": "Remote Data License Terms" + } + ], + "stac_extensions": [], + "title": "Collection of Extension Items", + "keywords": [ + "examples", + "sar", + "projection" + ], + "providers": [ + { + "name": "Remote Data, Inc.", + "roles": [ + "producer", + "licensor" + ], + "url": "https://remotedata.io" + } + ], + "extent": { + "spatial": { + "bbox": [ + [ + -180, + -56, + 180, + 83 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2009-05-20T02:40:01.042784Z", + "2018-11-03T23:59:55.112875Z" + ] + ] + } + }, + "license": "PDDL-1.0" +} diff --git a/tests/testdata/stac/extensions-collection/proj-example/proj-example.json b/tests/testdata/stac/extensions-collection/proj-example/proj-example.json new file mode 100644 index 000000000000..09b7986da679 --- /dev/null +++ b/tests/testdata/stac/extensions-collection/proj-example/proj-example.json @@ -0,0 +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" +} diff --git a/tests/testdata/stac/simple-item.json b/tests/testdata/stac/simple-item.json new file mode 100644 index 000000000000..1e413c43d9c8 --- /dev/null +++ b/tests/testdata/stac/simple-item.json @@ -0,0 +1,81 @@ +{ + "stac_version": "1.0.0", + "stac_extensions": [], + "type": "Feature", + "id": "20201211_223832_CS2", + "bbox": [ + 172.91173669923782, + 1.3438851951615003, + 172.95469614953714, + 1.3690476620161975 + ], + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 172.91173669923782, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3438851951615003 + ], + [ + 172.95469614953714, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3690476620161975 + ], + [ + 172.91173669923782, + 1.3438851951615003 + ] + ] + ] + }, + "properties": { + "datetime": "2020-12-11T22:38:32.125000Z" + }, + "collection": "simple-collection", + "links": [ + { + "rel": "collection", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "root", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + }, + { + "rel": "parent", + "href": "./collection.json", + "type": "application/json", + "title": "Simple Example Collection" + } + ], + "assets": { + "visual": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.tif", + "type": "image/tiff; application=geotiff; profile=cloud-optimized", + "title": "3-Band Visual", + "roles": [ + "visual" + ] + }, + "thumbnail": { + "href": "https://storage.googleapis.com/open-cogs/stac-examples/20201211_223832_CS2.jpg", + "title": "Thumbnail", + "type": "image/jpeg", + "roles": [ + "thumbnail" + ] + } + } +}