diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 161423ea..ccdcc643 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -53,5 +53,5 @@ jobs: - name: Install dotnet format run: dotnet tool update -g dotnet-format - name: Check Format - run: dotnet format --verify-no-changes --severity error src/ + run: dotnet format --verify-no-changes --severity warn src/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 20e0f7c0..11d74fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). -## [1.6.6](https://github.com/Terradue/DotNetStac/compare/1.6.5...1.6.6) +## [1.7.0](https://github.com/Terradue/DotNetStac/compare/1.6.6...1.7.0) + +Style and format improvements + +### Merged + +- Style and format improvements [`#23`](https://github.com/Terradue/DotNetStac/pull/23) + +### Commits + +- removed item-collection extension [`f99d497`](https://github.com/Terradue/DotNetStac/commit/f99d4970501650ddb04811e13a81e9445b3f2e01) +- many format fix with dotnet format [`f7a3898`](https://github.com/Terradue/DotNetStac/commit/f7a3898967bb3f8d8eb37aed46866f71a258bd27) +- and more linting [`b201bcf`](https://github.com/Terradue/DotNetStac/commit/b201bcff3f655766b7903d4d4e603a5e95496566) +- Prefix local calls with this [`ac186ea`](https://github.com/Terradue/DotNetStac/commit/ac186ea9d87b39724aff5b627e499b4553e60e12) +- Elements must appear in the correct order [`6505476`](https://github.com/Terradue/DotNetStac/commit/6505476b85d2bfba412f00bff32edb20d4883716) +- fields [`5d6219d`](https://github.com/Terradue/DotNetStac/commit/5d6219d6ad37562f0c97295cc1d130deb3d4671f) +- more styling [`d47db36`](https://github.com/Terradue/DotNetStac/commit/d47db36bf8c0ee60a361497d5e661a93a049ce61) +- more style [`596b5e1`](https://github.com/Terradue/DotNetStac/commit/596b5e11ea5c37cdcf7e083d7a568bde596b9a5b) +- SA1513 [`b7ac0bd`](https://github.com/Terradue/DotNetStac/commit/b7ac0bd271bf95e0fca8a91ffac63956944a7ee7) +- Element documentation header must be preceded by blank line [`0a08850`](https://github.com/Terradue/DotNetStac/commit/0a0885044f5e320a1e5fae0096ecf7b21cfd8d13) +- styling [`e95db31`](https://github.com/Terradue/DotNetStac/commit/e95db311f5ceb41c6542e257b7aa62859deead5f) +- no warinings [`da591b0`](https://github.com/Terradue/DotNetStac/commit/da591b098397fe44d098153a5fcbd1c1301f2595) +- Do not use placeholders in summaries [`466baaf`](https://github.com/Terradue/DotNetStac/commit/466baaf763bb32c377dc4b0742699d9cb180184e) +- remove blank lines [`7ccb21a`](https://github.com/Terradue/DotNetStac/commit/7ccb21ab1d379d242e8f04567ddc45bb56019483) +- removed empty values [`d6d6cba`](https://github.com/Terradue/DotNetStac/commit/d6d6cba7e081978030f248b4f7ea1851653a9cbc) +- more linting [`6b6d074`](https://github.com/Terradue/DotNetStac/commit/6b6d0749103bde3e4be4e817f52c2f15c5810d9c) +- SA1115 [`4ab4544`](https://github.com/Terradue/DotNetStac/commit/4ab454479fc8bbf9f4263b6d94e64af39a143d1c) +- removed empty return [`a0cb741`](https://github.com/Terradue/DotNetStac/commit/a0cb74141c0f0d864b0b85be91c5b562f9c833aa) +- Do not use regions [`ebce9c3`](https://github.com/Terradue/DotNetStac/commit/ebce9c3f241dead6710be6a19bd50d8bb7d7e69b) +- Statement must not use unnecessary parenthesis [`87c4fb6`](https://github.com/Terradue/DotNetStac/commit/87c4fb6bb835838511331866aa83424bcfb52ada) +- remove static [`b0b16e0`](https://github.com/Terradue/DotNetStac/commit/b0b16e075b96e0d5b3e5d6b3f1f4f5c3f018a882) +- linting [`664ce61`](https://github.com/Terradue/DotNetStac/commit/664ce612c8c35e79e95d3f058cb9566d17497eb5) +- severity warning for code liniting [`6f2ddfd`](https://github.com/Terradue/DotNetStac/commit/6f2ddfd5ae1995eada15d8a2cf111946a0dc015e) + +## [1.6.6](https://github.com/Terradue/DotNetStac/compare/1.6.5...1.6.6) - 2023-02-03 ### Commits diff --git a/README.md b/README.md index 8779aebc..7b3020cb 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@

-![Build Status](https://github.com/Terradue/DotNetStac/actions/workflows/build.yaml/badge.svg?branch=hotfix/1.6.6) +![Build Status](https://github.com/Terradue/DotNetStac/actions/workflows/build.yaml/badge.svg?branch=release/1.7.0) [![NuGet](https://img.shields.io/nuget/vpre/DotNetStac)](https://www.nuget.org/packages/DotNetStac/) -[![codecov](https://codecov.io/gh/Terradue/DotNetStac/branch/hotfix/1.6.6/graph/badge.svg)](https://codecov.io/gh/Terradue/DotNetStac) +[![codecov](https://codecov.io/gh/Terradue/DotNetStac/branch/release/1.7.0/graph/badge.svg)](https://codecov.io/gh/Terradue/DotNetStac) [![Gitter](https://img.shields.io/gitter/room/SpatioTemporal-Asset-Catalog/Lobby?color=yellow)](https://gitter.im/SpatioTemporal-Asset-Catalog/Lobby) [![License](https://img.shields.io/badge/license-AGPL3-blue.svg)](LICENSE) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Terradue/DotNetStac/master?filepath=example.ipynb) diff --git a/omnisharp.json b/omnisharp.json new file mode 100644 index 00000000..a984c924 --- /dev/null +++ b/omnisharp.json @@ -0,0 +1,18 @@ +{ + "RoslynExtensionsOptions": { + "enableAnalyzersSupport": true + }, + "FormattingOptions": { + "enableEditorConfigSupport": true, + "OrganizeImports": true + }, + "RenameOptions": { + "RenameInComments": true, + "RenameOverloads": true, + "RenameInStrings": true + }, + "ImplementTypeOptions": { + "PropertyGenerationBehavior": "PreferAutoProperties", + "InsertionBehavior": "WithOtherMembersOfTheSameKind" + } +} \ No newline at end of file diff --git a/src/.editorconfig b/src/.editorconfig index 5d7c8f7d..a2a6773f 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -88,7 +88,7 @@ dotnet_naming_rule.constants_must_be_pascal_cased.style dotnet_naming_rule.constants_must_be_pascal_cased.severity = warning dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.symbols = private_static_field_symbols -dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.style = camel_case_and_prefix_with_s_underscore_style +dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.style = pascal_case_style dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.severity = warning dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.symbols = private_field_symbols @@ -370,6 +370,7 @@ dotnet_diagnostic.RS0018.severity = warning dotnet_diagnostic.RS0010.severity = warning # Microsoft.CodeAnalysis.CSharp.Features +# Prefix local calls with this # Name: Before: After: dotnet_diagnostic.IDE0001.severity = warning # Simplify names System.Version version; Version version; dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) System.Version.Equals("1", "2"); Version.Equals("1", "2"); @@ -396,6 +397,54 @@ dotnet_diagnostic.VSTHRD111.severity = none # Use ConfigureAwait(true). dotnet_diagnostic.VSSDK006.severity = none # Check whether the result of GetService calls is null # Microsoft.CodeAnalysis.VisualBasic.CodeStyle/Microsoft.CodeAnalysis.CSharp.CodeStyle -dotnet_diagnostic.IDE0073.severity = warning # Enforce file header -file_header_template = Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information. - +dotnet_diagnostic.IDE0073.severity = warning # Enforce file header + +file_header_template = Copyright (c) by Terradue Srl. All Rights Reserved.\nLicense under the AGPL, Version 3.0.\nFile Name: {fileName} + +# Microsoft.CodeAnalysis.CSharp.CodeStyle +dotnet_diagnostic.SA1005.severity = warning # Single line comments should begin with single space +dotnet_diagnostic.SA1028.severity = warning # Code should not contain trailing whitespace +dotnet_diagnostic.SA1101.severity = warning # Prefix local calls with this +dotnet_diagnostic.SA1107.severity = warning # Code should not contain multiple statements on one line +dotnet_diagnostic.SA1111.severity = warning # Closing parenthesis should be on line of last parameter +dotnet_diagnostic.SA1115.severity = warning # Parameter should follow comma +dotnet_diagnostic.SA1116.severity = warning # Split parameters should start on line after declaration +dotnet_diagnostic.SA1119.severity = warning # Statement must not use unnecessary parenthesis +dotnet_diagnostic.SA1122.severity = warning # Use string.Empty for empty strings +dotnet_diagnostic.SA1124.severity = warning # Do not use regions +dotnet_diagnostic.SA1127.severity = warning # Generic type constraints must be on their own line or share line with previous +dotnet_diagnostic.SA1128.severity = warning # Put constructor initializers on their own line +dotnet_diagnostic.SA1129.severity = warning # Do not use default value type constructor +dotnet_diagnostic.SA1132.severity = warning # Do not combine fields +dotnet_diagnostic.SA1137.severity = warning # Elements should have the same indentation +dotnet_diagnostic.SA1201.severity = warning # Elements must appear in the correct order +dotnet_diagnostic.SA1202.severity = warning # Elements must be ordered by access +dotnet_diagnostic.SA1204.severity = warning # Static elements must appear before instance elements +dotnet_diagnostic.SA1214.severity = warning # Readonly fields must appear before non-readonly fields +dotnet_diagnostic.SA1306.severity = none # Field names must begin with lower-case letter +dotnet_diagnostic.SA1311.severity = warning # Static readonly fields must begin with upper-case letter +dotnet_diagnostic.SA1407.severity = warning # Arithmetic expressions must declare precedence +dotnet_diagnostic.SA1412.severity = warning # Store files as UTF-8 with byte order mark +dotnet_diagnostic.SA1413.severity = warning # Use trailing comma in multi-line initializers +dotnet_diagnostic.SA1500.severity = warning # Braces for multi-line statements must not share line +dotnet_diagnostic.SA1501.severity = warning # Braces must not be omitted +dotnet_diagnostic.SA1503.severity = warning # Braces must not be omitted +dotnet_diagnostic.SA1504.severity = warning # All accessors must be single-line or multi-line +dotnet_diagnostic.SA1505.severity = warning # An opening brace must not be followed by a blank line +dotnet_diagnostic.SA1506.severity = warning # Element documentation header must not be preceded by blank line +dotnet_diagnostic.SA1507.severity = warning # Code should not contain multiple blank lines in a row +dotnet_diagnostic.SA1508.severity = warning # A closing brace must not be preceded by a blank line +dotnet_diagnostic.SA1513.severity = warning # Closing brace must be followed by blank line +dotnet_diagnostic.SA1514.severity = warning # Element documentation header must be preceded by blank line +dotnet_diagnostic.SA1515.severity = warning # Single-line comment must be preceded by blank line +dotnet_diagnostic.SA1516.severity = warning # Elements must be separated by blank line +dotnet_diagnostic.SA1518.severity = warning # Code should end with a newline +dotnet_diagnostic.SA1519.severity = warning # Braces should not be omitted from multi-line child statement +dotnet_diagnostic.SA1520.severity = warning # Use braces consistently +dotnet_diagnostic.SA1623.severity = warning # Property summary documentation must match accessors +dotnet_diagnostic.SA1626.severity = warning # Single-line comments must not use documentation style slashes +dotnet_diagnostic.SA1636.severity = none # Disable file header matching +dotnet_diagnostic.SA1642.severity = warning # Constructor summary documentation must begin with standard text +dotnet_diagnostic.SA1649.severity = warning # File name must match first type name +dotnet_diagnostic.SA1651.severity = warning # Do not use placeholders in summaries +dotnet_diagnostic.SX1309.severity = warning # Field names should begin with underscore diff --git a/src/DotNetStac.Test/Catalog/CatalogTests.cs b/src/DotNetStac.Test/Catalog/CatalogTests.cs index f035f774..283f0147 100644 --- a/src/DotNetStac.Test/Catalog/CatalogTests.cs +++ b/src/DotNetStac.Test/Catalog/CatalogTests.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: CatalogTests.cs + +using System; using Newtonsoft.Json; using Xunit; diff --git a/src/DotNetStac.Test/Catalog/StacRepositoryCatalogTests.cs b/src/DotNetStac.Test/Catalog/StacRepositoryCatalogTests.cs index 567fb4db..f8c619bf 100644 --- a/src/DotNetStac.Test/Catalog/StacRepositoryCatalogTests.cs +++ b/src/DotNetStac.Test/Catalog/StacRepositoryCatalogTests.cs @@ -1,6 +1,7 @@ -using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacRepositoryCatalogTests.cs + using Xunit; namespace Stac.Test.Catalog @@ -10,7 +11,7 @@ public class StacRepositoryCatalogTests : TestBase [Fact] public void CanDeserializeBaseCatalogExample() { - var json = httpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/catalog.json").GetAwaiter().GetResult(); + var json = HttpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/catalog.json").GetAwaiter().GetResult(); StacCatalog catalog = StacConvert.Deserialize(json); diff --git a/src/DotNetStac.Test/Collection/CollectionTests.cs b/src/DotNetStac.Test/Collection/CollectionTests.cs index c0d22712..ac66fe1d 100644 --- a/src/DotNetStac.Test/Collection/CollectionTests.cs +++ b/src/DotNetStac.Test/Collection/CollectionTests.cs @@ -1,11 +1,12 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: CollectionTests.cs + +using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using System.Text; -using GeoJSON.Net; -using GeoJSON.Net.Geometry; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stac.Collection; @@ -45,10 +46,10 @@ public void CanDeserializeSentinel2Sample() Assert.IsType>(item.Summaries["datetime"]); - Assert.Equal(DateTime.Parse("2015-06-23T00:00:00Z").ToUniversalTime(), (item.Summaries["datetime"] as StacSummaryRangeObject).Min); + Assert.Equal(DateTime.Parse("2015-06-23T00:00:00Z").ToUniversalTime(), (item.Summaries["datetime"] as StacSummaryRangeObject).Min); - Assert.Equal(32601, (item.Summaries["proj:epsg"] as StacSummaryValueSet).Min()); - Assert.Equal(32660, (item.Summaries["proj:epsg"] as StacSummaryValueSet).Max()); + Assert.Equal(32601, (item.Summaries["proj:epsg"] as StacSummaryValueSet).Min()); + Assert.Equal(32660, (item.Summaries["proj:epsg"] as StacSummaryValueSet).Max()); Assert.Equal(60, (item.Summaries["proj:epsg"] as StacSummaryValueSet).Count); Assert.Equal(13, item.Summaries["eo:bands"].LongCount()); diff --git a/src/DotNetStac.Test/Collection/StacRepositoryCollectionTests.cs b/src/DotNetStac.Test/Collection/StacRepositoryCollectionTests.cs index 3e2a03ae..a34d59e6 100644 --- a/src/DotNetStac.Test/Collection/StacRepositoryCollectionTests.cs +++ b/src/DotNetStac.Test/Collection/StacRepositoryCollectionTests.cs @@ -1,9 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacRepositoryCollectionTests.cs + +using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Xunit; namespace Stac.Test.Catalog @@ -14,7 +15,7 @@ public class StacRepositoryCollectionTests : TestBase [Fact] public void CanDeserializeBaseCollectionExample() { - var json = httpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/collection.json").GetAwaiter().GetResult(); + var json = HttpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/collection.json").GetAwaiter().GetResult(); ValidateJson(json); @@ -34,7 +35,7 @@ public void CanDeserializeBaseCollectionExample() [Fact] public void CanCreateBaseCollectionExample() { - var expectedJson = httpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/collection.json").GetAwaiter().GetResult(); + var expectedJson = HttpClient.GetStringAsync($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/collection.json").GetAwaiter().GetResult(); //TMP expectedJson = expectedJson.Replace("\"proj:epsg\": {\n \"minimum\": 32659,\n \"maximum\": 32659\n }", "\"proj:epsg\":[32659]"); @@ -42,14 +43,14 @@ public void CanCreateBaseCollectionExample() Dictionary items = new Dictionary(); Uri simpleItemUri = new Uri($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/simple-item.json"); - items.Add(simpleItemUri, StacConvert.Deserialize(httpClient.GetStringAsync(simpleItemUri).GetAwaiter().GetResult())); + items.Add(simpleItemUri, StacConvert.Deserialize(HttpClient.GetStringAsync(simpleItemUri).GetAwaiter().GetResult())); items[simpleItemUri].Title = "Simple Item"; Uri coreItemUri = new Uri($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/core-item.json"); - string coreItemJson = httpClient.GetStringAsync(coreItemUri).GetAwaiter().GetResult(); + string coreItemJson = HttpClient.GetStringAsync(coreItemUri).GetAwaiter().GetResult(); coreItemJson = coreItemJson.Replace("cool_sat2", "cool_sat1"); items.Add(coreItemUri, StacConvert.Deserialize(coreItemJson)); Uri extendedItemUri = new Uri($"https://raw.githubusercontent.com/radiantearth/stac-spec/v{Versions.StacVersionList.Current}/examples/extended-item.json"); - string extendedItemJson = httpClient.GetStringAsync(extendedItemUri).GetAwaiter().GetResult(); + string extendedItemJson = HttpClient.GetStringAsync(extendedItemUri).GetAwaiter().GetResult(); extendedItemJson = extendedItemJson.Replace("cool_sensor_v1", "cool_sensor_v2"); items.Add(extendedItemUri, StacConvert.Deserialize(extendedItemJson)); StacCollection collection = StacCollection.Create("simple-collection", diff --git a/src/DotNetStac.Test/Common/PatchHelpersTests.cs b/src/DotNetStac.Test/Common/PatchHelpersTests.cs index 8ca024d9..b3605259 100644 --- a/src/DotNetStac.Test/Common/PatchHelpersTests.cs +++ b/src/DotNetStac.Test/Common/PatchHelpersTests.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; -using GeoJSON.Net.Geometry; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: PatchHelpersTests.cs + using Newtonsoft.Json; -using Stac.Collection; using Stac.Common; using Xunit; @@ -16,7 +17,7 @@ public void PatchStacItemTest() StacItem patchItem = StacConvert.Deserialize(GetJson("Common", "Patch")); - StacItem patchedItem = baseItem.Patch(patchItem); + StacItem patchedItem = baseItem.Patch(patchItem); JsonAssert.AreEqual(GetJson("Common", "PatchedItem"), StacConvert.Serialize(patchedItem)); } @@ -28,7 +29,7 @@ public void PatchStacItemTest2() Patch patchItem = JsonConvert.DeserializeObject(GetJson("Common", "Patch2")); - StacItem patchedItem = baseItem.Patch(patchItem); + StacItem patchedItem = baseItem.Patch(patchItem); JsonAssert.AreEqual(GetJson("Common", "PatchedItem2"), StacConvert.Serialize(patchedItem)); } diff --git a/src/DotNetStac.Test/Common/StacAccessorsHelpersTests.cs b/src/DotNetStac.Test/Common/StacAccessorsHelpersTests.cs index 4eefbe32..a0db1e5b 100644 --- a/src/DotNetStac.Test/Common/StacAccessorsHelpersTests.cs +++ b/src/DotNetStac.Test/Common/StacAccessorsHelpersTests.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacAccessorsHelpersTests.cs + +using System.Collections.Generic; using GeoJSON.Net.Geometry; using Stac.Collection; using Stac.Common; @@ -54,7 +58,7 @@ public void GetPropertyTest() item.SetProperty("summary", summaryItemType); - Assert.NotNull(item.GetProperty("summary")); + Assert.NotNull(item.GetProperty("summary")); summaryItemType = SummaryItemType.RangeObject; diff --git a/src/DotNetStac.Test/Examples/Example1Test.cs b/src/DotNetStac.Test/Examples/Example1Test.cs index 3d36c28c..d9039102 100644 --- a/src/DotNetStac.Test/Examples/Example1Test.cs +++ b/src/DotNetStac.Test/Examples/Example1Test.cs @@ -1,7 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Example1Test.cs + +using System; using System.Collections.Generic; using System.Linq; -using System.Net; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stac.Collection; @@ -12,19 +15,19 @@ namespace Stac.Test.Example public class Example1Test : TestBase { //[Fact] - public void Deserialize() - { - Uri catalogUri = new Uri("https://landsat-stac.s3.amazonaws.com/catalog.json"); - StacCatalog catalog = StacConvert.Deserialize(httpClient.GetStringAsync(catalogUri).GetAwaiter().GetResult()); + // public void Deserialize() + // { + // Uri catalogUri = new Uri("https://landsat-stac.s3.amazonaws.com/catalog.json"); + // StacCatalog catalog = StacConvert.Deserialize(httpClient.GetStringAsync(catalogUri).GetAwaiter().GetResult()); - Console.Out.WriteLine(catalog.Id); - Console.Out.WriteLine(catalog.StacVersion); + // Console.Out.WriteLine(catalog.Id); + // Console.Out.WriteLine(catalog.StacVersion); - ListChildrensItemsAndAssets(catalog, catalogUri); + // ListChildrensItemsAndAssets(catalog, catalogUri); - } + // } - void ListChildrensItemsAndAssets(IStacParent catalog, Uri baseUri, string prefix = "", int limit = 2) + private void ListChildrensItemsAndAssets(IStacParent catalog, Uri baseUri, string prefix = "", int limit = 2) { // Get children first (sub catalogs and collections) foreach (var childLink in catalog.GetChildrenLinks().Concat(catalog.GetItemLinks())) @@ -32,7 +35,7 @@ void ListChildrensItemsAndAssets(IStacParent catalog, Uri baseUri, string prefix Uri childUri = childLink.Uri; if (!childUri.IsAbsoluteUri) childUri = new Uri(baseUri, childUri.ToString()); - IStacObject child = StacConvert.Deserialize(httpClient.GetStringAsync(childUri).GetAwaiter().GetResult()); + IStacObject child = StacConvert.Deserialize(HttpClient.GetStringAsync(childUri).GetAwaiter().GetResult()); Console.Out.WriteLine(prefix + child.Id + ": " + child.Title); if (child is StacCatalog || child is StacCollection) diff --git a/src/DotNetStac.Test/Exceptions/ExceptionsTests.cs b/src/DotNetStac.Test/Exceptions/ExceptionsTests.cs index b9fa2e08..f2f88078 100644 --- a/src/DotNetStac.Test/Exceptions/ExceptionsTests.cs +++ b/src/DotNetStac.Test/Exceptions/ExceptionsTests.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ExceptionsTests.cs + +using System; using Stac.Exceptions; using Xunit; diff --git a/src/DotNetStac.Test/Extensions/AlternateExtensionTests.cs b/src/DotNetStac.Test/Extensions/AlternateExtensionTests.cs index a5082146..11de46d4 100644 --- a/src/DotNetStac.Test/Extensions/AlternateExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/AlternateExtensionTests.cs @@ -1,5 +1,8 @@ -using System; -using System.IO; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: AlternateExtensionTests.cs + +using System; using Newtonsoft.Json; using Stac.Extensions.Alternate; using Xunit; @@ -9,7 +12,7 @@ namespace Stac.Test.Extensions public class AlternateExtensionTests : TestBase { [Fact] - public async System.Threading.Tasks.Task SetAlternateAsset() + public System.Threading.Tasks.Task SetAlternateAsset() { var simpleJson = GetJson("Extensions", "MinimalSample"); ValidateJson(simpleJson); @@ -32,10 +35,11 @@ public async System.Threading.Tasks.Task SetAlternateAsset() JsonAssert.AreEqual(expectedJson, actualJson); Assert.Equal("s3://bucket/key/srid.csv", simpleitem.Assets["srid"].AlternateExtension().AlternateAssets["s3"].Uri.ToString()); + return System.Threading.Tasks.Task.CompletedTask; } [Fact] - public async System.Threading.Tasks.Task LS9Alternates() + public System.Threading.Tasks.Task LS9Alternates() { var simpleJson = GetJson("Extensions", "LS9Sample"); ValidateJson(simpleJson); @@ -43,7 +47,7 @@ public async System.Threading.Tasks.Task LS9Alternates() StacItem ls9item = StacConvert.Deserialize(simpleJson); Assert.Equal("s3://usgs-landsat/collection02/level-2/standard/oli-tirs/2022/088/084/LC09_L2SP_088084_20220405_20220407_02_T2/LC09_L2SP_088084_20220405_20220407_02_T2_thumb_small.jpeg", ls9item.Assets["thumbnail"].AlternateExtension().AlternateAssets["s3"].Uri.ToString()); + return System.Threading.Tasks.Task.CompletedTask; } - } } diff --git a/src/DotNetStac.Test/Extensions/DatacubeExtensionTests.cs b/src/DotNetStac.Test/Extensions/DatacubeExtensionTests.cs index 8a08e2e7..972b9eea 100644 --- a/src/DotNetStac.Test/Extensions/DatacubeExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/DatacubeExtensionTests.cs @@ -1,12 +1,12 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeExtensionTests.cs + +using System; using System.Collections.Generic; -using System.Linq; using System.Net.Mime; using GeoJSON.Net.Geometry; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Stac.Extensions.Datacube; -using Stac.Extensions.Eo; using Xunit; namespace Stac.Test.Extensions @@ -106,7 +106,7 @@ public void CanSerializeDatacube123() item.DatacubeStacExtension().Variables.Add("temp", tempVar); var colorVar = new DatacubeVariable(); - colorVar.Dimensions = new string[] { }; + colorVar.Dimensions = Array.Empty(); colorVar.Type = DatacubeVariableType.auxiliary; colorVar.Values = new string[] { "red", "green", "blue" }; item.DatacubeStacExtension().Variables.Add("color", colorVar); diff --git a/src/DotNetStac.Test/Extensions/EoExtensionTests.cs b/src/DotNetStac.Test/Extensions/EoExtensionTests.cs index 2f74082c..e7ebc4a5 100644 --- a/src/DotNetStac.Test/Extensions/EoExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/EoExtensionTests.cs @@ -1,9 +1,12 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: EoExtensionTests.cs + +using System; using System.Collections.Generic; using System.Linq; using GeoJSON.Net.Geometry; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Stac.Extensions.Eo; using Xunit; @@ -109,8 +112,8 @@ public void CreateEoExtension() EoStacExtension eo = item.EoExtension(); eo.CloudCover = 0; - Assert.Equal(0.0, eo.CloudCover.Value); - Assert.Equal(0.0, double.Parse(asset.Properties["eo:cloud_cover"].ToString())); + Assert.Equal(0.0, eo.CloudCover.Value); + Assert.Equal(0.0, double.Parse(asset.Properties["eo:cloud_cover"].ToString())); var actualJson = StacConvert.Serialize(item); diff --git a/src/DotNetStac.Test/Extensions/FileExtensionTests.cs b/src/DotNetStac.Test/Extensions/FileExtensionTests.cs index fb539bec..2168adce 100644 --- a/src/DotNetStac.Test/Extensions/FileExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/FileExtensionTests.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: FileExtensionTests.cs + +using System; using System.IO; -using System.Linq; -using GeoJSON.Net.Geometry; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Stac.Extensions.File; using Xunit; @@ -24,7 +24,7 @@ public async System.Threading.Tasks.Task SetPropertiesFromFileInfo() new Uri("file:///srid.csv"), new System.Net.Mime.ContentType("text/csv"), "System reference Ids"); - await stacAsset.FileExtension().SetFileExtensionProperties(new System.IO.FileInfo("SRID.csv")); + await stacAsset.FileExtension().SetFileExtensionProperties(new FileInfo("SRID.csv")); simpleitem.Assets.Add("srid", stacAsset); Assert.Equal(1536937, stacAsset.FileExtension().Size.Value); diff --git a/src/DotNetStac.Test/Extensions/ItemCollectionTests.cs b/src/DotNetStac.Test/Extensions/ItemCollectionTests.cs deleted file mode 100644 index c62dbe45..00000000 --- a/src/DotNetStac.Test/Extensions/ItemCollectionTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; -using Stac.Extensions.ItemCollections; -using Xunit; - -namespace Stac.Test.Extensions -{ - public class ItemCollectionTests : TestBase - { - // [Fact] - public void CanDeserializeResto() - { - var json = GetJson("Extensions"); - - ValidateJson(json); - - var stacObject = StacConvert.Deserialize(json); - - Assert.IsAssignableFrom(stacObject); - - ItemCollection itemCollection = stacObject as ItemCollection; - - Assert.Equal("1.0.0", itemCollection.StacVersion); - - Assert.NotEmpty(itemCollection.Features); - - } - - } -} diff --git a/src/DotNetStac.Test/Extensions/RasterExtensionTests.cs b/src/DotNetStac.Test/Extensions/RasterExtensionTests.cs index edb66f34..ceb40bde 100644 --- a/src/DotNetStac.Test/Extensions/RasterExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/RasterExtensionTests.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GeoJSON.Net.Geometry; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Stac.Extensions.Eo; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterExtensionTests.cs + using Xunit; namespace Stac.Test.Extensions diff --git a/src/DotNetStac.Test/Extensions/StorageExtensionTests.cs b/src/DotNetStac.Test/Extensions/StorageExtensionTests.cs index bdb04562..de834c7b 100644 --- a/src/DotNetStac.Test/Extensions/StorageExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/StorageExtensionTests.cs @@ -1,5 +1,8 @@ -using System; -using System.IO; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StorageExtensionTests.cs + +using System; using Newtonsoft.Json; using Stac.Extensions.Alternate; using Xunit; @@ -9,7 +12,7 @@ namespace Stac.Test.Extensions public class StorageExtensionTests : TestBase { [Fact] - public async System.Threading.Tasks.Task SetAlternateStorageAsset() + public System.Threading.Tasks.Task SetAlternateStorageAsset() { var simpleJson = GetJson("Extensions", "MinimalSample"); ValidateJson(simpleJson); @@ -37,7 +40,7 @@ public async System.Threading.Tasks.Task SetAlternateStorageAsset() Assert.Equal("s3://bucket/key/srid.csv", simpleitem.Assets["srid"].AlternateExtension().AlternateAssets["s3"].Uri.ToString()); Assert.Equal("fr-par", simpleitem.Assets["srid"].AlternateExtension().AlternateAssets["s3"].StorageExtension().Region); + return System.Threading.Tasks.Task.CompletedTask; } - } } diff --git a/src/DotNetStac.Test/Extensions/VersionExtensionTests.cs b/src/DotNetStac.Test/Extensions/VersionExtensionTests.cs index e65d0e7b..e0ca8827 100644 --- a/src/DotNetStac.Test/Extensions/VersionExtensionTests.cs +++ b/src/DotNetStac.Test/Extensions/VersionExtensionTests.cs @@ -1,4 +1,8 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VersionExtensionTests.cs + +using Newtonsoft.Json; using Stac.Extensions.Version; using Xunit; diff --git a/src/DotNetStac.Test/Item/ItemTests.cs b/src/DotNetStac.Test/Item/ItemTests.cs index 7141dd74..3ba8d22e 100644 --- a/src/DotNetStac.Test/Item/ItemTests.cs +++ b/src/DotNetStac.Test/Item/ItemTests.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ItemTests.cs + +using System; using System.Collections.Generic; using System.Linq; using GeoJSON.Net; @@ -42,9 +46,9 @@ public void CanDeserializeMinimalSample() Assert.Equal(DateTime.Parse("2016-05-03T13:21:30.040Z").ToUniversalTime(), item.Properties["datetime"]); - Assert.Contains(item.Links, l => l.RelationshipType == "self" && l.Uri.ToString() == "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.json"); + Assert.Contains(item.Links, l => l.RelationshipType == "self" && l.Uri.ToString() == "http://cool-sat.com/catalog/CS3-20160503_132130_04/CS3-20160503_132130_04.json"); - Assert.Contains(item.Links, l => l.RelationshipType == "collection" && l.Uri.ToString() == "http://cool-sat.com/catalog.json"); + Assert.Contains(item.Links, l => l.RelationshipType == "collection" && l.Uri.ToString() == "http://cool-sat.com/catalog.json"); Assert.Equal("relative-path/to/analytic.tif", item.Assets["analytic"].Uri.ToString()); Assert.Equal("4-Band Analytic", item.Assets["analytic"].Title); @@ -320,7 +324,7 @@ public void Geometry() Point point = new Point(coordinates[0][0]); var extent = StacGeometryHelpers.GetBoundingBox(point); Assert.Equal(pextentCheck.First().ToArray(), extent); - MultiPoint mpoint = new MultiPoint(Array.ConvertAll(coordinates[0].ToArray(), p => new Point(p))); + MultiPoint mpoint = new MultiPoint(Array.ConvertAll(coordinates[0].ToArray(), p => new Point(p))); extent = StacGeometryHelpers.GetBoundingBox(mpoint); Assert.Equal(extentCheck.First().ToArray(), extent); var lineString = new LineString(coordinates[0]); @@ -373,11 +377,11 @@ public void ItemProviders() simpleItem.Providers.Add(new StacProvider("ESA", new StacProviderRole[] { StacProviderRole.licensor })); - Assert.Contains("providers", simpleItem.Properties); + Assert.Contains("providers", simpleItem.Properties); simpleItem.Providers.RemoveAt(0); - Assert.DoesNotContain("providers", simpleItem.Properties); + Assert.DoesNotContain("providers", simpleItem.Properties); var newJson = StacConvert.Serialize(simpleItem); ValidateJson(newJson); diff --git a/src/DotNetStac.Test/Item/ProcessingExtensionTests.cs b/src/DotNetStac.Test/Item/ProcessingExtensionTests.cs index 76b0d296..ee7db320 100644 --- a/src/DotNetStac.Test/Item/ProcessingExtensionTests.cs +++ b/src/DotNetStac.Test/Item/ProcessingExtensionTests.cs @@ -1,4 +1,7 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProcessingExtensionTests.cs + using Stac.Extensions.Processing; using Xunit; diff --git a/src/DotNetStac.Test/Item/ProjExtensionTests.cs b/src/DotNetStac.Test/Item/ProjExtensionTests.cs index 24f8831e..6bee3f58 100644 --- a/src/DotNetStac.Test/Item/ProjExtensionTests.cs +++ b/src/DotNetStac.Test/Item/ProjExtensionTests.cs @@ -1,4 +1,7 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProjExtensionTests.cs + using Stac.Extensions.Projection; using Xunit; diff --git a/src/DotNetStac.Test/Item/SarExtensionTests.cs b/src/DotNetStac.Test/Item/SarExtensionTests.cs index 62624fc4..fa39eb46 100644 --- a/src/DotNetStac.Test/Item/SarExtensionTests.cs +++ b/src/DotNetStac.Test/Item/SarExtensionTests.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SarExtensionTests.cs + +using System; using System.Collections.Generic; using GeoJSON.Net.Geometry; using Stac.Extensions.Sar; diff --git a/src/DotNetStac.Test/Item/SatExtensionTests.cs b/src/DotNetStac.Test/Item/SatExtensionTests.cs index 6ec49f12..28ecb4ca 100644 --- a/src/DotNetStac.Test/Item/SatExtensionTests.cs +++ b/src/DotNetStac.Test/Item/SatExtensionTests.cs @@ -1,4 +1,7 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SatExtensionTests.cs + using Stac.Extensions.Sat; using Xunit; diff --git a/src/DotNetStac.Test/JsonAssert.cs b/src/DotNetStac.Test/JsonAssert.cs index 2e7e30e4..5b5c65d9 100644 --- a/src/DotNetStac.Test/JsonAssert.cs +++ b/src/DotNetStac.Test/JsonAssert.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: JsonAssert.cs + using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/src/DotNetStac.Test/PriorityOrderer.cs b/src/DotNetStac.Test/PriorityOrderer.cs index 155a45a3..6b9184b7 100644 --- a/src/DotNetStac.Test/PriorityOrderer.cs +++ b/src/DotNetStac.Test/PriorityOrderer.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: PriorityOrderer.cs + +using System; using System.Collections.Generic; using System.Linq; using Xunit.Abstractions; @@ -30,7 +34,7 @@ public IEnumerable OrderTestCases(IEnumerable t } } - static TValue GetOrCreate(IDictionary dictionary, TKey key) + private static TValue GetOrCreate(IDictionary dictionary, TKey key) where TValue : new() { diff --git a/src/DotNetStac.Test/Resources/Extensions/ItemCollectionTests_CanDeserializeResto.json b/src/DotNetStac.Test/Resources/Extensions/ItemCollectionTests_CanDeserializeResto.json deleted file mode 100644 index 22cc64d6..00000000 --- a/src/DotNetStac.Test/Resources/Extensions/ItemCollectionTests_CanDeserializeResto.json +++ /dev/null @@ -1,6939 +0,0 @@ -{ - "type": "FeatureCollection", - "id": "b083c1b2-75b9-59a0-bd76-ce0955f1467c", - "stac_version": "1.0.0", - "context": { - "returned": 20, - "limit": 20, - "matched": 440000, - "exactCount": false, - "startIndex": 1, - "query": { - "inputFilters": { - "q": "#month:01" - }, - "appliedFilters": { - "q": "#month:01" - }, - "processingTime": 32.56619095802307 - } - }, - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/catalogs/classifications/temporal/month/month:01.json?&fields=_all" - }, - { - "rel": "search", - "type": "application/opensearchdescription+xml", - "href": "https://tamn.snapplanet.io/services/osdd" - }, - { - "rel": "next", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/catalogs/classifications/temporal/month/month:01.json?&fields=_all&next=211306015173002329" - } - ], - "features": [ - { - "type": "Feature", - "id": "32d4808b-627a-5888-b05a-e31bc02cb87b", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 172.608145, - 52.338619 - ], - [ - 172.993108, - 52.332663 - ], - [ - 172.952793, - 52.257366 - ], - [ - 172.611713, - 52.338205 - ], - [ - 172.608145, - 52.338619 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UPT_20210201T011827", - "datetime": "2021-01-31T23:51:46.690000Z", - "start_datetime": "2021-01-31T23:51:46.690000Z", - "end_datetime": "2021-01-31T23:51:46.690000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UPT", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 27.03, - "coverage": 0.92, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/PT/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:09.907Z", - "s3Ingestion": "2021-02-01T02:17:07.849Z", - "eo:sun_elevation": 69.7446064532251, - "eo:sun_azimuth": 167.619997914823, - "viewZenith": 11.0439323553914, - "view:azimuth": 297.676437469211, - "updated": "2021-02-01T02:17:08.884763Z", - "published": "2021-02-01T02:17:08.884763Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 109.93555, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 172.851992, - 52.30954 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/32d4808b-627a-5888-b05a-e31bc02cb87b" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/32d4808b-627a-5888-b05a-e31bc02cb87b/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/32d4808b-627a-5888-b05a-e31bc02cb87b/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PT/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 172.608145212924, - 52.2573660798308, - 172.993108056175, - 52.3386191897609 - ] - }, - { - "type": "Feature", - "id": "441579b1-15a9-5063-9413-59e718387f68", - "geometry": null, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T58UGD_20210201T011827", - "datetime": "2021-01-31T23:51:46.336000Z", - "start_datetime": "2021-01-31T23:51:46.336000Z", - "end_datetime": "2021-01-31T23:51:46.336000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "58UGD", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 11.35, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/58/U/GD/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:11.806Z", - "s3Ingestion": "2021-02-01T02:16:43.973Z", - "eo:sun_elevation": 71.2688448525249, - "eo:sun_azimuth": 163.205909231337, - "viewZenith": 9.66188157061808, - "view:azimuth": 105.593914657734, - "updated": "2021-02-01T02:16:45.771858Z", - "published": "2021-02-01T02:16:45.771858Z", - "keywords": [ - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1 - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/441579b1-15a9-5063-9413-59e718387f68" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/441579b1-15a9-5063-9413-59e718387f68/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/441579b1-15a9-5063-9413-59e718387f68/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GD/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ] - }, - { - "type": "Feature", - "id": "bcdce118-b082-5b4e-acde-e10c4db4d134", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 168.863983, - 53.230477 - ], - [ - 169.648327, - 53.241954 - ], - [ - 169.659341, - 52.888738 - ], - [ - 169.658543, - 52.889548 - ], - [ - 169.506406, - 52.912827 - ], - [ - 168.810779, - 53.007014 - ], - [ - 168.7938, - 53.010522 - ], - [ - 168.769257, - 53.012774 - ], - [ - 168.863983, - 53.230477 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59ULU_20210201T011827", - "datetime": "2021-01-31T23:51:45.837000Z", - "start_datetime": "2021-01-31T23:51:45.837000Z", - "end_datetime": "2021-01-31T23:51:45.837000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59ULU", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 12.22, - "coverage": 14.85, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/LU/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:10.816Z", - "s3Ingestion": "2021-02-01T02:16:58.145Z", - "eo:sun_elevation": 71.294555053769, - "eo:sun_azimuth": 163.284834906908, - "viewZenith": 9.53533124456668, - "view:azimuth": 105.711509832165, - "updated": "2021-02-01T02:17:00.041303Z", - "published": "2021-02-01T02:17:00.041303Z", - "keywords": [ - { - "id": "ocean:NorthPacificOcean:4030875", - "name": "North Pacific Ocean", - "type": "ocean", - "value": 93.06, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23ocean%3ANorthPacificOcean%3A4030875" - }, - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 6.83, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 1783.50706, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "ocean:NorthPacificOcean:4030875", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 169.265475, - 53.088661 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/bcdce118-b082-5b4e-acde-e10c4db4d134" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/bcdce118-b082-5b4e-acde-e10c4db4d134/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/bcdce118-b082-5b4e-acde-e10c4db4d134/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LU/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 168.769256545929, - 52.8887382170239, - 169.659341170422, - 53.2419543907225 - ] - }, - { - "type": "Feature", - "id": "e9c45bb5-8ffb-55c3-810f-b4be9f591ebd", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 169.500956, - 53.240192 - ], - [ - 171.146262, - 53.249528 - ], - [ - 171.14422, - 52.63991 - ], - [ - 171.139523, - 52.640642 - ], - [ - 171.139528, - 52.642042 - ], - [ - 171.132349, - 52.64205 - ], - [ - 170.908712, - 52.684124 - ], - [ - 170.274018, - 52.793596 - ], - [ - 169.52327, - 52.910191 - ], - [ - 169.51238, - 52.910055 - ], - [ - 169.500956, - 53.240192 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UMU_20210201T011827", - "datetime": "2021-01-31T23:51:44.308000Z", - "start_datetime": "2021-01-31T23:51:44.308000Z", - "end_datetime": "2021-01-31T23:51:44.308000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UMU", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 50.89, - "coverage": 47.19, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/MU/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:25.726Z", - "s3Ingestion": "2021-02-01T02:15:31.322Z", - "eo:sun_elevation": 71.0671977054969, - "eo:sun_azimuth": 164.743250184417, - "viewZenith": 4.16172109583659, - "view:azimuth": 108.977400948379, - "updated": "2021-02-01T02:15:35.639375Z", - "published": "2021-02-01T02:15:35.639375Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 78.52, - "gcover": 0.2, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "ocean:NorthPacificOcean:4030875", - "name": "North Pacific Ocean", - "type": "ocean", - "value": 21.48, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23ocean%3ANorthPacificOcean%3A4030875" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 5684.69081, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "ocean:NorthPacificOcean:4030875", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 170.408579, - 53.006683 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/e9c45bb5-8ffb-55c3-810f-b4be9f591ebd" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/e9c45bb5-8ffb-55c3-810f-b4be9f591ebd/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/e9c45bb5-8ffb-55c3-810f-b4be9f591ebd/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MU/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 169.500955705136, - 52.6399099302, - 171.146261854414, - 53.2495277635177 - ] - }, - { - "type": "Feature", - "id": "3cea4878-d3d8-5558-903f-02a065c25dd7", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 170.999715, - 53.249617 - ], - [ - 172.492848, - 53.24027 - ], - [ - 172.643759, - 53.207671 - ], - [ - 172.611326, - 52.338288 - ], - [ - 171.922968, - 52.487266 - ], - [ - 171.223517, - 52.626231 - ], - [ - 171.008295, - 52.665035 - ], - [ - 171.008296, - 52.666397 - ], - [ - 170.999719, - 52.666397 - ], - [ - 170.999715, - 53.249617 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UNU_20210201T011827", - "datetime": "2021-01-31T23:51:42.270000Z", - "start_datetime": "2021-01-31T23:51:42.270000Z", - "end_datetime": "2021-01-31T23:51:42.270000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UNU", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 39.29, - "coverage": 74.65, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/NU/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:31.142Z", - "s3Ingestion": "2021-02-01T02:14:50.558Z", - "eo:sun_elevation": 70.8436703859328, - "eo:sun_azimuth": 166.207492787993, - "viewZenith": 5.1314947372972, - "view:azimuth": 268.501062464515, - "updated": "2021-02-01T02:14:56.559895Z", - "published": "2021-02-01T02:14:56.559895Z", - "keywords": [ - { - "id": "continent:NorthAmerica:6255149", - "name": "North America", - "type": "continent", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23continent%3ANorthAmerica%3A6255149" - }, - { - "id": "country:UnitedStatesOfAmerica:6252001", - "name": "United States of America", - "type": "country", - "parentId": "continent:NorthAmerica:6255149", - "value": 0.58, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23country%3AUnitedStatesOfAmerica%3A6252001" - }, - { - "id": "region:West:11887751", - "name": "West", - "type": "region", - "parentId": "country:UnitedStatesOfAmerica:6252001", - "value": 0.57, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23region%3AWest%3A11887751" - }, - { - "id": "state:Alaska:5879092", - "name": "Alaska", - "type": "state", - "parentId": "region:West:11887751", - "value": 0.58, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23state%3AAlaska%3A5879092" - }, - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 99.46, - "gcover": 0.4, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 8933.57992, - "value": 99.59, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "landcover:herbaceous", - "name": "Herbaceous", - "type": "landcover:herbaceous", - "area": 61.72668, - "value": 0.68, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Aherbaceous" - }, - { - "id": "landcover:desert", - "name": "Desert", - "type": "landcover:desert", - "area": 15.62816, - "value": 0.17, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Adesert" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "location:coastal", - "name": "Coastal", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Acoastal" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "continent:NorthAmerica:6255149", - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "location:coastal", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 171.871912, - 52.870142 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3cea4878-d3d8-5558-903f-02a065c25dd7" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3cea4878-d3d8-5558-903f-02a065c25dd7/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3cea4878-d3d8-5558-903f-02a065c25dd7/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NU/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 170.999715239247, - 52.3382882629184, - 172.643759075872, - 53.2496174782598 - ] - }, - { - "type": "Feature", - "id": "566e68c3-edf8-5bb8-9380-31b519e26bb4", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 169.69675, - 53.729373 - ], - [ - 169.624678, - 53.071266 - ], - [ - 168.806983, - 53.100282 - ], - [ - 169.122016, - 53.806343 - ], - [ - 169.412774, - 53.766658 - ], - [ - 169.69675, - 53.729373 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T58UGE_20210201T011827", - "datetime": "2021-01-31T23:51:40.686000Z", - "start_datetime": "2021-01-31T23:51:40.686000Z", - "end_datetime": "2021-01-31T23:51:40.686000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "58UGE", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 12.43, - "coverage": 29.82, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/58/U/GE/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:20.687Z", - "s3Ingestion": "2021-02-01T02:16:18.681Z", - "eo:sun_elevation": 72.1243419752625, - "eo:sun_azimuth": 163.30922647126, - "viewZenith": 10.0654368612105, - "view:azimuth": 105.644581591674, - "updated": "2021-02-01T02:16:21.807412Z", - "published": "2021-02-01T02:16:21.807412Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 69.3, - "gcover": 0.11, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "ocean:NorthPacificOcean:4030875", - "name": "North Pacific Ocean", - "type": "ocean", - "value": 30.6, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23ocean%3ANorthPacificOcean%3A4030875" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 3575.24064, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "ocean:NorthPacificOcean:4030875", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 169.301825, - 53.40875 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/566e68c3-edf8-5bb8-9380-31b519e26bb4" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/566e68c3-edf8-5bb8-9380-31b519e26bb4/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/566e68c3-edf8-5bb8-9380-31b519e26bb4/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/58/U/GE/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 168.806982582281, - 53.0712660676314, - 169.696750016091, - 53.8063430799066 - ] - }, - { - "type": "Feature", - "id": "02a48642-bce5-5d97-91b9-8b4e611bc00e", - "geometry": null, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UPU_20210201T011827", - "datetime": "2021-01-31T23:51:40.446000Z", - "start_datetime": "2021-01-31T23:51:40.446000Z", - "end_datetime": "2021-01-31T23:51:40.446000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UPU", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 32.14, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/PU/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:23.635Z", - "s3Ingestion": "2021-02-01T02:16:12.348Z", - "eo:sun_elevation": 70.624235432197, - "eo:sun_azimuth": 167.674990748947, - "viewZenith": 9.85074071979077, - "view:azimuth": 288.855492854153, - "updated": "2021-02-01T02:16:15.527344Z", - "published": "2021-02-01T02:16:15.527344Z", - "keywords": [ - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1 - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/02a48642-bce5-5d97-91b9-8b4e611bc00e" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/02a48642-bce5-5d97-91b9-8b4e611bc00e/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/02a48642-bce5-5d97-91b9-8b4e611bc00e/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/PU/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ] - }, - { - "type": "Feature", - "id": "77cac508-6a47-56ba-a27b-81c2caa78c38", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 169.632461, - 53.737967 - ], - [ - 169.651106, - 53.153544 - ], - [ - 168.824759, - 53.141314 - ], - [ - 169.121629, - 53.806218 - ], - [ - 169.499597, - 53.754944 - ], - [ - 169.632461, - 53.737967 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59ULV_20210201T011827", - "datetime": "2021-01-31T23:51:40.297000Z", - "start_datetime": "2021-01-31T23:51:40.297000Z", - "end_datetime": "2021-01-31T23:51:40.297000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59ULV", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 11.74, - "coverage": 25.85, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/LV/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:24.436Z", - "s3Ingestion": "2021-02-01T02:15:48.861Z", - "eo:sun_elevation": 72.1727746740516, - "eo:sun_azimuth": 163.265392355451, - "viewZenith": 10.1566282124261, - "view:azimuth": 106.150186796944, - "updated": "2021-02-01T02:15:51.302810Z", - "published": "2021-02-01T02:15:51.302810Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 76.53, - "gcover": 0.1, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "ocean:NorthPacificOcean:4030875", - "name": "North Pacific Ocean", - "type": "ocean", - "value": 23.4, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23ocean%3ANorthPacificOcean%3A4030875" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 3104.88928, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "ocean:NorthPacificOcean:4030875", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 169.294038, - 53.436997 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/77cac508-6a47-56ba-a27b-81c2caa78c38" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/77cac508-6a47-56ba-a27b-81c2caa78c38/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/77cac508-6a47-56ba-a27b-81c2caa78c38/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/LV/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 168.824759448456, - 53.1413140116774, - 169.651105539306, - 53.8062175914836 - ] - }, - { - "type": "Feature", - "id": "9ce77bfd-296d-54cc-980f-02f2bd717620", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 171.147122, - 53.499923 - ], - [ - 171.145961, - 53.161093 - ], - [ - 169.504037, - 53.151787 - ], - [ - 169.482598, - 53.757371 - ], - [ - 169.880821, - 53.703685 - ], - [ - 170.553239, - 53.600628 - ], - [ - 171.147122, - 53.499923 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UMV_20210201T011827", - "datetime": "2021-01-31T23:51:38.267000Z", - "start_datetime": "2021-01-31T23:51:38.267000Z", - "end_datetime": "2021-01-31T23:51:38.267000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UMV", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 28.33, - "coverage": 48.26, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/MV/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:26.422Z", - "s3Ingestion": "2021-02-01T02:15:17.600Z", - "eo:sun_elevation": 71.9458141124601, - "eo:sun_azimuth": 164.748318031396, - "viewZenith": 5.61760409900246, - "view:azimuth": 102.586954355881, - "updated": "2021-02-01T02:15:21.413892Z", - "published": "2021-02-01T02:15:21.413892Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 99.89, - "gcover": 0.26, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "ocean:NorthPacificOcean:4030875", - "name": "North Pacific Ocean", - "type": "ocean", - "value": 0.16, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23ocean%3ANorthPacificOcean%3A4030875" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 5846.75686, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 170.243035, - 53.40172 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/9ce77bfd-296d-54cc-980f-02f2bd717620" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/9ce77bfd-296d-54cc-980f-02f2bd717620/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/9ce77bfd-296d-54cc-980f-02f2bd717620/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/MV/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 169.482597719027, - 53.1517871616411, - 171.147122207848, - 53.757371210086 - ] - }, - { - "type": "Feature", - "id": "5242f7e0-44c6-5123-bbdb-ae5160f734da", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 172.643759, - 53.207672 - ], - [ - 172.64155, - 53.149869 - ], - [ - 170.999716, - 53.161183 - ], - [ - 170.999713, - 53.525535 - ], - [ - 171.288571, - 53.475184 - ], - [ - 171.313764, - 53.46948 - ], - [ - 171.606867, - 53.415477 - ], - [ - 171.632085, - 53.412112 - ], - [ - 172.327039, - 53.274998 - ], - [ - 172.643759, - 53.207672 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T235129_N0209_R073_T59UNV_20210201T011827", - "datetime": "2021-01-31T23:51:36.377000Z", - "start_datetime": "2021-01-31T23:51:36.377000Z", - "end_datetime": "2021-01-31T23:51:36.377000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59UNV", - "dataTakeId": "GS2B_20210131T235129_020405_N02.09", - "eo:cloud_cover": 17.3, - "coverage": 21.73, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011827_S20210131T235130_N02.09", - "path": "tiles/59/U/NV/2021/1/31/0", - "sciHubIngestion": "2021-02-01T01:58:19.269Z", - "s3Ingestion": "2021-02-01T02:16:34.757Z", - "eo:sun_elevation": 71.7224663414524, - "eo:sun_azimuth": 166.23705737965, - "viewZenith": 3.43186496736798, - "view:azimuth": 219.56672015587, - "updated": "2021-02-01T02:16:37.203538Z", - "published": "2021-02-01T02:16:37.203538Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.11, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 2638.29249, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 171.627856, - 53.283216 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/5242f7e0-44c6-5123-bbdb-ae5160f734da" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/5242f7e0-44c6-5123-bbdb-ae5160f734da/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/5242f7e0-44c6-5123-bbdb-ae5160f734da/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/U/NV/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 170.999713392047, - 53.1498690808361, - 172.643759120848, - 53.5255348747255 - ] - }, - { - "type": "Feature", - "id": "c06d5164-ebf5-5ba7-8d5f-d2bed31b5b38", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 174.310511, - 60.395296 - ], - [ - 174.806733, - 60.382017 - ], - [ - 174.799207, - 60.317462 - ], - [ - 174.787225, - 60.320874 - ], - [ - 174.507019, - 60.366343 - ], - [ - 174.310511, - 60.395296 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T59VPG_20210201T011900", - "datetime": "2021-01-31T23:49:36.867000Z", - "start_datetime": "2021-01-31T23:49:36.867000Z", - "end_datetime": "2021-01-31T23:49:36.867000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59VPG", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.81, - "coverage": 0.78, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/59/V/PG/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:38:09.558Z", - "s3Ingestion": "2021-02-01T02:54:28.949Z", - "eo:sun_elevation": 77.6464281057125, - "eo:sun_azimuth": 168.09720264101, - "viewZenith": 3.78879480183961, - "view:azimuth": 129.400745351259, - "updated": "2021-02-01T02:54:30.183538Z", - "published": "2021-02-01T02:54:30.183538Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 93.79916, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 174.641767, - 60.365525 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/c06d5164-ebf5-5ba7-8d5f-d2bed31b5b38" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/c06d5164-ebf5-5ba7-8d5f-d2bed31b5b38/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/c06d5164-ebf5-5ba7-8d5f-d2bed31b5b38/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PG/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 174.310510609492, - 60.3174621691917, - 174.806732571519, - 60.3952957318506 - ] - }, - { - "type": "Feature", - "id": "b7f02914-0522-5659-b7fc-e1010591c8da", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 174.229619, - 60.407637 - ], - [ - 175.361607, - 60.426376 - ], - [ - 175.37187, - 60.220928 - ], - [ - 174.873021, - 60.306618 - ], - [ - 174.544196, - 60.360238 - ], - [ - 174.229619, - 60.407637 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VUM_20210201T011900", - "datetime": "2021-01-31T23:49:35.159000Z", - "start_datetime": "2021-01-31T23:49:35.159000Z", - "end_datetime": "2021-01-31T23:49:35.159000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VUM", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.91, - "coverage": 5.82, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/UM/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:38:11.726Z", - "s3Ingestion": "2021-02-01T03:02:51.230Z", - "eo:sun_elevation": 77.5867141237258, - "eo:sun_azimuth": 168.708457972102, - "viewZenith": 2.58570365478071, - "view:azimuth": 93.9644000472411, - "updated": "2021-02-01T03:02:52.482509Z", - "published": "2021-02-01T03:02:52.482509Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.03, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 698.03382, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 174.993583, - 60.352445 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/b7f02914-0522-5659-b7fc-e1010591c8da" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/b7f02914-0522-5659-b7fc-e1010591c8da/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/b7f02914-0522-5659-b7fc-e1010591c8da/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UM/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 174.229618751865, - 60.2209283291489, - 175.371869921259, - 60.4263758354072 - ] - }, - { - "type": "Feature", - "id": "3a3f9c13-4ed9-5062-b73f-69a2d1600f0a", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 173.037947, - 61.124807 - ], - [ - 173.003579, - 60.580732 - ], - [ - 173.000535, - 60.580777 - ], - [ - 172.73194, - 60.616858 - ], - [ - 172.721971, - 60.616987 - ], - [ - 172.717156, - 60.618383 - ], - [ - 173.037947, - 61.124807 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T59VNH_20210201T011900", - "datetime": "2021-01-31T23:49:34.478000Z", - "start_datetime": "2021-01-31T23:49:34.478000Z", - "end_datetime": "2021-01-31T23:49:34.478000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59VNH", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.94, - "coverage": 3.97, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/59/V/NH/2021/1/31/1", - "sciHubIngestion": "2021-02-01T02:38:10.699Z", - "s3Ingestion": "2021-02-01T03:03:17.263Z", - "eo:sun_elevation": 78.7442639199439, - "eo:sun_azimuth": 166.386424562141, - "viewZenith": 11.4881355706039, - "view:azimuth": 115.969937772772, - "updated": "2021-02-01T03:03:18.269398Z", - "published": "2021-02-01T03:03:18.269398Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.02, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 476.55944, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 172.919617, - 60.774644 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3a3f9c13-4ed9-5062-b73f-69a2d1600f0a" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3a3f9c13-4ed9-5062-b73f-69a2d1600f0a/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/3a3f9c13-4ed9-5062-b73f-69a2d1600f0a/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/NH/2021/1/31/1/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 172.717155926524, - 60.5807318460504, - 173.037947297857, - 61.1248073595987 - ] - }, - { - "type": "Feature", - "id": "48081d72-3dce-595e-b8bb-429629726582", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 175.184827, - 60.424084 - ], - [ - 177.177303, - 60.43633 - ], - [ - 177.174274, - 59.869063 - ], - [ - 177.165521, - 59.872014 - ], - [ - 177.025004, - 59.901782 - ], - [ - 176.348736, - 60.039722 - ], - [ - 175.693221, - 60.164726 - ], - [ - 175.310161, - 60.232611 - ], - [ - 175.196279, - 60.249862 - ], - [ - 175.184827, - 60.424084 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VVM_20210201T011900", - "datetime": "2021-01-31T23:49:33.328000Z", - "start_datetime": "2021-01-31T23:49:33.328000Z", - "end_datetime": "2021-01-31T23:49:33.328000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VVM", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.97, - "coverage": 37.02, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/VM/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:40:53.762Z", - "s3Ingestion": "2021-02-01T02:58:24.315Z", - "eo:sun_elevation": 77.4490227013943, - "eo:sun_azimuth": 170.432314772807, - "viewZenith": 5.02430045816962, - "view:azimuth": 269.654848941782, - "updated": "2021-02-01T02:58:27.948703Z", - "published": "2021-02-01T02:58:27.948703Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.19, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 4473.90948, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 176.364104, - 60.232313 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/48081d72-3dce-595e-b8bb-429629726582" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/48081d72-3dce-595e-b8bb-429629726582/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/48081d72-3dce-595e-b8bb-429629726582/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VM/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 175.18482667129, - 59.8690633280913, - 177.177302514332, - 60.4363298650668 - ] - }, - { - "type": "Feature", - "id": "75d4ff03-5c8c-5eed-91eb-688f4dfcae64", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 176.999655, - 60.436448 - ], - [ - 178.303759, - 60.430071 - ], - [ - 177.753973, - 59.740285 - ], - [ - 177.314027, - 59.840525 - ], - [ - 177.040005, - 59.898548 - ], - [ - 177.00754, - 59.905078 - ], - [ - 176.99966, - 59.905267 - ], - [ - 176.999655, - 60.436448 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VWM_20210201T011900", - "datetime": "2021-01-31T23:49:30.759000Z", - "start_datetime": "2021-01-31T23:49:30.759000Z", - "end_datetime": "2021-01-31T23:49:30.759000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VWM", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.99, - "coverage": 33.34, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/WM/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:41:19.079Z", - "s3Ingestion": "2021-02-01T02:57:21.201Z", - "eo:sun_elevation": 77.3136490306663, - "eo:sun_azimuth": 172.16094476235, - "viewZenith": 9.6958957731721, - "view:azimuth": 292.869393016292, - "updated": "2021-02-01T02:57:24.105845Z", - "published": "2021-02-01T02:57:24.105845Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.17, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 4076.17079, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 177.552843, - 60.149362 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/75d4ff03-5c8c-5eed-91eb-688f4dfcae64" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/75d4ff03-5c8c-5eed-91eb-688f4dfcae64/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/75d4ff03-5c8c-5eed-91eb-688f4dfcae64/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WM/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 176.999654805081, - 59.740285160489, - 178.303759110149, - 60.4364477889322 - ] - }, - { - "type": "Feature", - "id": "86afd2ed-429d-5d6c-a4cb-ae1749c31884", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 173.162256, - 61.317227 - ], - [ - 174.914883, - 61.277972 - ], - [ - 174.79926, - 60.317924 - ], - [ - 174.485604, - 60.369601 - ], - [ - 173.625012, - 60.498254 - ], - [ - 172.898596, - 60.595176 - ], - [ - 172.826368, - 60.603405 - ], - [ - 172.838274, - 60.812523 - ], - [ - 173.162256, - 61.317227 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T59VPH_20210201T011900", - "datetime": "2021-01-31T23:49:29.809000Z", - "start_datetime": "2021-01-31T23:49:29.809000Z", - "end_datetime": "2021-01-31T23:49:29.809000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59VPH", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.99, - "coverage": 81.13, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/59/V/PH/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:41:21.851Z", - "s3Ingestion": "2021-02-01T02:57:05.268Z", - "eo:sun_elevation": 78.5225660890856, - "eo:sun_azimuth": 168.15225103844, - "viewZenith": 7.62396262569761, - "view:azimuth": 109.293965023931, - "updated": "2021-02-01T02:57:10.773109Z", - "published": "2021-02-01T02:57:10.773109Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.43, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 9760.61095, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 173.945654, - 60.869128 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/86afd2ed-429d-5d6c-a4cb-ae1749c31884" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/86afd2ed-429d-5d6c-a4cb-ae1749c31884/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/86afd2ed-429d-5d6c-a4cb-ae1749c31884/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PH/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 172.826367549834, - 60.3179237691473, - 174.914883247728, - 61.3172265906898 - ] - }, - { - "type": "Feature", - "id": "1e11fd5d-74ef-5931-9909-f6e6e3c49468", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 173.269379, - 61.283169 - ], - [ - 175.314943, - 61.323985 - ], - [ - 175.365964, - 60.339515 - ], - [ - 174.716996, - 60.330673 - ], - [ - 174.707299, - 60.333472 - ], - [ - 174.485827, - 60.369388 - ], - [ - 173.720948, - 60.48429 - ], - [ - 173.358041, - 60.532188 - ], - [ - 173.269379, - 61.283169 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VUN_20210201T011900", - "datetime": "2021-01-31T23:49:28.971000Z", - "start_datetime": "2021-01-31T23:49:28.971000Z", - "end_datetime": "2021-01-31T23:49:28.971000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VUN", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 99.99, - "coverage": 91.6, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/UN/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:40:50.692Z", - "s3Ingestion": "2021-02-01T02:59:03.946Z", - "eo:sun_elevation": 78.479141016071, - "eo:sun_azimuth": 168.61806421064, - "viewZenith": 5.99238323768834, - "view:azimuth": 108.467323496316, - "updated": "2021-02-01T02:59:09.754632Z", - "published": "2021-02-01T02:59:09.754632Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.49, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 11008.30831, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 174.378009, - 60.852967 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/1e11fd5d-74ef-5931-9909-f6e6e3c49468" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/1e11fd5d-74ef-5931-9909-f6e6e3c49468/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/1e11fd5d-74ef-5931-9909-f6e6e3c49468/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/UN/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 173.269379265337, - 60.3306732080145, - 175.365964263997, - 61.3239852349243 - ] - }, - { - "type": "Feature", - "id": "57e5aaa9-da89-50e9-b75f-87973286bd71", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 175.131267, - 61.321583 - ], - [ - 177.182355, - 61.334311 - ], - [ - 177.176826, - 60.348536 - ], - [ - 175.187893, - 60.33631 - ], - [ - 175.131267, - 61.321583 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VVN_20210201T011900", - "datetime": "2021-01-31T23:49:24.541000Z", - "start_datetime": "2021-01-31T23:49:24.541000Z", - "end_datetime": "2021-01-31T23:49:24.541000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VVN", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 100, - "coverage": 100, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/VN/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:40:49.534Z", - "s3Ingestion": "2021-02-01T03:00:06.321Z", - "eo:sun_elevation": 78.341190001131, - "eo:sun_azimuth": 170.384966767179, - "viewZenith": 3.37800372524829, - "view:azimuth": 217.406677699259, - "updated": "2021-02-01T03:00:12.564179Z", - "published": "2021-02-01T03:00:12.564179Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.53, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 12047.30663, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 176.16954, - 60.837712 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/57e5aaa9-da89-50e9-b75f-87973286bd71" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/57e5aaa9-da89-50e9-b75f-87973286bd71/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/57e5aaa9-da89-50e9-b75f-87973286bd71/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/VN/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 175.131267437273, - 60.3363095373745, - 177.182355205504, - 61.3343111743704 - ] - }, - { - "type": "Feature", - "id": "0b4b4978-a770-5b3c-8222-84898ab9116e", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 176.999645, - 61.334434 - ], - [ - 179.043129, - 61.319071 - ], - [ - 178.233259, - 60.342937 - ], - [ - 176.999656, - 60.348654 - ], - [ - 176.999645, - 61.334434 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T60VWN_20210201T011900", - "datetime": "2021-01-31T23:49:18.766000Z", - "start_datetime": "2021-01-31T23:49:18.766000Z", - "end_datetime": "2021-01-31T23:49:18.766000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "60VWN", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 100, - "coverage": 80.82, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/60/V/WN/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:40:39.104Z", - "s3Ingestion": "2021-02-01T03:01:09.085Z", - "eo:sun_elevation": 78.2053385773221, - "eo:sun_azimuth": 172.156768852476, - "viewZenith": 8.5358099067339, - "view:azimuth": 292.024826714413, - "updated": "2021-02-01T03:01:14.083317Z", - "published": "2021-02-01T03:01:14.083317Z", - "keywords": [ - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 100, - "gcover": 0.43, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 9728.48801, - "value": 100, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "sea:BeringSea:4031788", - "landcover:water", - "location:northern", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 177.835023, - 60.876774 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/0b4b4978-a770-5b3c-8222-84898ab9116e" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/0b4b4978-a770-5b3c-8222-84898ab9116e/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/0b4b4978-a770-5b3c-8222-84898ab9116e/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/60/V/WN/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 176.999644967798, - 60.3429372090535, - 179.043129470076, - 61.3344335056374 - ] - }, - { - "type": "Feature", - "id": "d215dc30-1f65-5233-8867-4f66d179dc37", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 173.752767, - 62.204441 - ], - [ - 175.030291, - 62.173151 - ], - [ - 174.903932, - 61.189856 - ], - [ - 173.105584, - 61.229764 - ], - [ - 173.517797, - 61.8505 - ], - [ - 173.752767, - 62.204441 - ] - ] - ] - }, - "properties": { - "productIdentifier": "S2B_MSIL1C_20210131T234819_N0209_R073_T59VPJ_20210201T011900", - "datetime": "2021-01-31T23:49:16.581000Z", - "start_datetime": "2021-01-31T23:49:16.581000Z", - "end_datetime": "2021-01-31T23:49:16.581000Z", - "authority": "ESA", - "productType": "REFLECTANCE", - "processingLevel": "LEVEL1C", - "platform": "S2B", - "instruments": [ - "MSI" - ], - "tileId": "59VPJ", - "dataTakeId": "GS2B_20210131T234819_020405_N02.09", - "eo:cloud_cover": 100, - "coverage": 74.27, - "datastripId": "S2B_OPER_MSI_L1C_DS_EPAE_20210201T011900_S20210131T234846_N02.09", - "path": "tiles/59/V/PJ/2021/1/31/0", - "sciHubIngestion": "2021-02-01T02:40:44.153Z", - "s3Ingestion": "2021-02-01T03:00:31.289Z", - "eo:sun_elevation": 79.3977319993627, - "eo:sun_azimuth": 168.209039531188, - "viewZenith": 8.78970674020856, - "view:azimuth": 110.376479994125, - "updated": "2021-02-01T03:00:36.835204Z", - "published": "2021-02-01T03:00:36.835204Z", - "keywords": [ - { - "id": "continent:Europe:6255148", - "name": "Europe", - "type": "continent", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23continent%3AEurope%3A6255148" - }, - { - "id": "country:Russia:2017370", - "name": "Russia", - "type": "country", - "parentId": "continent:Europe:6255148", - "value": 35.51, - "gcover": 0.01, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23country%3ARussia%3A2017370" - }, - { - "id": "region:FarEastern:11961349", - "name": "Far Eastern", - "type": "region", - "parentId": "country:Russia:2017370", - "value": 35.58, - "gcover": 0.05, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23region%3AFarEastern%3A11961349" - }, - { - "id": "state:Kamchatka:553817", - "name": "Kamchatka", - "type": "state", - "parentId": "region:FarEastern:11961349", - "value": 22.7, - "gcover": 0.43, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23state%3AKamchatka%3A553817" - }, - { - "id": "sea:BeringSea:4031788", - "name": "Bering Sea", - "type": "sea", - "value": 63.7, - "gcover": 0.25, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23sea%3ABeringSea%3A4031788" - }, - { - "id": "landcover:water", - "name": "Water", - "type": "landcover:water", - "area": 5850.97119, - "value": 65.72, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Awater" - }, - { - "id": "landcover:herbaceous", - "name": "Herbaceous", - "type": "landcover:herbaceous", - "area": 2301.18382, - "value": 25.84, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Aherbaceous" - }, - { - "id": "landcover:desert", - "name": "Desert", - "type": "landcover:desert", - "area": 788.83221, - "value": 8.86, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Adesert" - }, - { - "id": "landcover:cultivated", - "name": "Cultivated", - "type": "landcover:cultivated", - "area": 40.74199, - "value": 0.45, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Acultivated" - }, - { - "id": "landcover:forest", - "name": "Forest", - "type": "landcover:forest", - "area": 7.12332, - "value": 0.08, - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23landcover%3Aforest" - }, - { - "id": "location:northern", - "name": "Northern", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Anorthern" - }, - { - "id": "location:coastal", - "name": "Coastal", - "type": "location", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23location%3Acoastal" - }, - { - "id": "season:winter", - "name": "Winter", - "type": "season", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23season%3Awinter" - }, - { - "id": "collection:S2", - "name": "S2", - "type": "collection", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23collection%3AS2" - }, - { - "id": "productType:REFLECTANCE", - "name": "REFLECTANCE", - "type": "productType", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23productType%3AREFLECTANCE" - }, - { - "id": "processingLevel:LEVEL1C", - "name": "LEVEL1C", - "type": "processingLevel", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23processingLevel%3ALEVEL1C" - }, - { - "id": "platform:S2B", - "name": "S2B", - "type": "platform", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23platform%3AS2B" - }, - { - "id": "instrument:MSI", - "name": "MSI", - "type": "instrument", - "parentId": "platform:S2B", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23instrument%3AMSI" - }, - { - "id": "year:2021", - "name": "2021", - "type": "year", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23year%3A2021" - }, - { - "id": "month:01", - "name": "01", - "type": "month", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23month%3A01" - }, - { - "id": "day:31", - "name": "31", - "type": "day", - "href": "https://tamn.snapplanet.io/collections/S2/items?&lang=en&q=%23day%3A31" - } - ], - "hashtags": [ - "continent:Europe:6255148", - "country:Russia:2017370", - "region:FarEastern:11961349", - "state:Kamchatka:553817", - "sea:BeringSea:4031788", - "landcover:water", - "landcover:herbaceous", - "location:northern", - "location:coastal", - "season:winter", - "collection:S2", - "productType:REFLECTANCE", - "processingLevel:LEVEL1C", - "platform:S2B", - "instrument:MSI", - "year:2021", - "month:01", - "day:31" - ], - "likes": 0, - "comments": 0, - "status": 1, - "centroid": [ - 174.186821, - 61.671755 - ] - }, - "collection": "S2", - "links": [ - { - "rel": "self", - "type": "application/geo+json", - "href": "https://tamn.snapplanet.io/collections/S2/items/d215dc30-1f65-5233-8867-4f66d179dc37" - }, - { - "rel": "parent", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "collection", - "type": "application/json", - "title": "S2", - "href": "https://tamn.snapplanet.io/collections/S2" - }, - { - "rel": "root", - "type": "application/json", - "href": "https://tamn.snapplanet.io" - }, - { - "rel": "child", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/d215dc30-1f65-5233-8867-4f66d179dc37/hasSample" - }, - { - "rel": "isSampleOf", - "type": "application/json", - "href": "https://tamn.snapplanet.io/collections/S2/items/d215dc30-1f65-5233-8867-4f66d179dc37/isSampleOf" - }, - { - "rel": "preview", - "type": "image/jpeg", - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/preview.jpg" - } - ], - "assets": { - "thumbnail": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/preview.jpg", - "type": "image/jpeg", - "role": "thumbnail" - }, - "metadata": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/metadata.xml", - "type": "text/xml", - "role": "metadata" - }, - "tileInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/tileInfo.json", - "type": "application/json" - }, - "productInfo": { - "href": "https://roda.sentinel-hub.com/sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/productInfo.json", - "type": "application/json" - }, - "B1": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B1.jp2", - "title": "B1 60m (coastal)", - "type": "image/jp2", - "eo:bands": [ - 0 - ] - }, - "B2": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B2.jp2", - "title": "B2 10m (blue)", - "type": "image/jp2", - "eo:bands": [ - 1 - ] - }, - "B3": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B3.jp2", - "title": "B3 10m (green)", - "type": "image/jp2", - "eo:bands": [ - 2 - ] - }, - "B4": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B4.jp2", - "title": "B4 10m (red)", - "type": "image/jp2", - "eo:bands": [ - 3 - ] - }, - "B5": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B5.jp2", - "title": "B5 20m", - "type": "image/jp2", - "eo:bands": [ - 4 - ] - }, - "B6": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B6.jp2", - "title": "B6 20m", - "type": "image/jp2", - "eo:bands": [ - 5 - ] - }, - "B7": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B7.jp2", - "title": "B7 20m", - "type": "image/jp2", - "eo:bands": [ - 6 - ] - }, - "B8": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B8.jp2", - "title": "B8 10m (nir)", - "type": "image/jp2", - "eo:bands": [ - 7 - ] - }, - "B8A": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B8A.jp2", - "title": "B8A 20m", - "type": "image/jp2", - "eo:bands": [ - 8 - ] - }, - "B9": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B9.jp2", - "title": "B9 60m", - "type": "image/jp2", - "eo:bands": [ - 9 - ] - }, - "B10": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B10.jp2", - "title": "B10 60m", - "type": "image/jp2", - "eo:bands": [ - 10 - ] - }, - "B11": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B11.jp2", - "title": "B11 20m (swir16)", - "type": "image/jp2", - "eo:bands": [ - 11 - ] - }, - "B12": { - "href": "s3://sentinel-s2-l1c/tiles/59/V/PJ/2021/1/31/0/B12.jp2", - "title": "B12 20m (swir22)", - "type": "image/jp2", - "eo:bands": [ - 12 - ] - } - }, - "stac_version": "1.0.0", - "stac_extensions": [ - "https://stac-extensions.github.io/sat/v1.0.0/schema.json", - "https://stac-extensions.github.io/view/v1.0.0/schema.json", - "https://stac-extensions.github.io/eo/v1.0.0/schema.json" - ], - "bbox": [ - 173.105584055056, - 61.1898559661554, - 175.030290738886, - 62.2044408288778 - ] - } - ] -} \ No newline at end of file diff --git a/src/DotNetStac.Test/Schemas/SchemaLoaderTests.cs b/src/DotNetStac.Test/Schemas/SchemaLoaderTests.cs index ceab0735..f9f15570 100644 --- a/src/DotNetStac.Test/Schemas/SchemaLoaderTests.cs +++ b/src/DotNetStac.Test/Schemas/SchemaLoaderTests.cs @@ -1,7 +1,9 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SchemaLoaderTests.cs + using Stac.Exceptions; using Stac.Extensions; -using Stac.Extensions.Sat; using Xunit; namespace Stac.Test.Item diff --git a/src/DotNetStac.Test/StacLink/StacLinkTests.cs b/src/DotNetStac.Test/StacLink/StacLinkTests.cs index f066a129..4956d4bb 100644 --- a/src/DotNetStac.Test/StacLink/StacLinkTests.cs +++ b/src/DotNetStac.Test/StacLink/StacLinkTests.cs @@ -1,9 +1,8 @@ -using System; -using System.Collections.Generic; -using GeoJSON.Net; -using GeoJSON.Net.Geometry; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacLinkTests.cs + +using System; using Xunit; namespace Stac.Test.Item @@ -20,7 +19,7 @@ public void CreateHelpers() var stacLink = StacLink.CreateItemLink(new Uri("file:///test"), "text/plain"); stacLink.Title = "test"; var cloned = new StacLink(stacLink); - cloned = stacLink.Clone(); + cloned = stacLink.Clone() as StacLink; } } } diff --git a/src/DotNetStac.Test/TestBase.cs b/src/DotNetStac.Test/TestBase.cs index e5a0e311..7a530a18 100644 --- a/src/DotNetStac.Test/TestBase.cs +++ b/src/DotNetStac.Test/TestBase.cs @@ -1,16 +1,13 @@ -using System; -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: TestBase.cs + +using System; using System.IO; -using System.Linq; -using System.Net; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; -using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; -using Stac.Extensions; using Stac.Schemas; namespace Stac.Test @@ -24,9 +21,17 @@ public abstract class TestBase .Assembly; private static readonly string AssemblyName = ThisAssembly.GetName().Name; - private static StacValidator stacValidator = new StacValidator(new JSchemaUrlResolver()); + private static readonly StacValidator StacValidator = new(new JSchemaUrlResolver()); + + private readonly HttpClient _httpClient = new(); - protected HttpClient httpClient = new HttpClient(); + public HttpClient HttpClient + { + get + { + return _httpClient; + } + } protected TestBase() { @@ -36,10 +41,8 @@ public static string AssemblyDirectory { get { - string codeBase = ThisAssembly.CodeBase; - UriBuilder uri = new UriBuilder(codeBase); - string path = Uri.UnescapeDataString(uri.Path); - return Path.GetDirectoryName(path); + string codeBase = ThisAssembly.Location; + return Path.GetDirectoryName(codeBase); } } @@ -97,7 +100,7 @@ protected string GetUseCaseJson(string name) public bool ValidateJson(string jsonstr) { - return stacValidator.ValidateJson(jsonstr); + return StacValidator.ValidateJson(jsonstr); } } diff --git a/src/DotNetStac.Test/TestPriorityAttribute.cs b/src/DotNetStac.Test/TestPriorityAttribute.cs index b2480a82..0cc87f66 100644 --- a/src/DotNetStac.Test/TestPriorityAttribute.cs +++ b/src/DotNetStac.Test/TestPriorityAttribute.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: TestPriorityAttribute.cs + +using System; namespace Stac.Test { diff --git a/src/DotNetStac.Test/UseCases/Sentinel2.cs b/src/DotNetStac.Test/UseCases/Sentinel2.cs index 2b82fd60..4a40e447 100644 --- a/src/DotNetStac.Test/UseCases/Sentinel2.cs +++ b/src/DotNetStac.Test/UseCases/Sentinel2.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Sentinel2.cs + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -9,7 +13,7 @@ namespace Stac.Test.UseCases [TestCaseOrderer("Stac.Test.PriorityOrderer", "DotNetStac.Test")] public class Sentinel2 : TestBase { - private static StacCatalog catalog; + private static StacCatalog Catalog; [Fact, TestPriority(1)] public void LoadRootCatalog() @@ -17,17 +21,17 @@ public void LoadRootCatalog() var json = GetUseCaseJson("catalog.json"); ValidateJson(json); - catalog = StacConvert.Deserialize(json); + Catalog = StacConvert.Deserialize(json); - Assert.NotNull(catalog); - Assert.Equal("sentinel-stac", catalog.Id); + Assert.NotNull(Catalog); + Assert.Equal("sentinel-stac", Catalog.Id); } [Fact, TestPriority(2)] public void LoadRootChildren() { - IEnumerable children = catalog.GetChildrenLinks() + IEnumerable children = Catalog.GetChildrenLinks() .Select(l => { Uri childUri = new Uri(GetUseCaseFileUri("catalog.json"), l.Uri.OriginalString); @@ -36,7 +40,7 @@ public void LoadRootChildren() return StacConvert.Deserialize(childJson); }); - Assert.Equal(1, children.Count()); + Assert.Single(children); Assert.IsAssignableFrom(children.First()); } diff --git a/src/DotNetStac/Collection/IStacSummaryItem.cs b/src/DotNetStac/Collection/IStacSummaryItem.cs index 36681be4..43ca8591 100644 --- a/src/DotNetStac/Collection/IStacSummaryItem.cs +++ b/src/DotNetStac/Collection/IStacSummaryItem.cs @@ -1,28 +1,46 @@ -using System; -using System.Collections; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacSummaryItem.cs + using System.Collections.Generic; using Newtonsoft.Json.Linq; namespace Stac.Collection { + /// + /// Delegate for creating a summary item + /// + /// The argument. + /// The type of the argument + /// The summary item + public delegate IStacSummaryItem CreateSummary(IEnumerable arg); + /// /// Provides the summary item interface for Collections /// public interface IStacSummaryItem : IEnumerable { + /// + /// Gets the summary item as a JToken + /// + /// + /// The summary item as a JToken + /// + JToken AsJToken { get; } + /// /// Gets or sets the summary value with the specified fields (for objects only) /// - /// + /// + /// The . + /// + /// The key. JToken this[object key] { get; } /// - /// Gets or sets the summary item as a JToken + /// Gets the summary item as a JToken /// - /// - JToken AsJToken { get; } - + /// The summary item as a JToken IEnumerable Enumerate(); - } } diff --git a/src/DotNetStac/Collection/StacExtent.cs b/src/DotNetStac/Collection/StacExtent.cs index b8e1bfab..70fa22e2 100644 --- a/src/DotNetStac/Collection/StacExtent.cs +++ b/src/DotNetStac/Collection/StacExtent.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacExtent.cs + +using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; @@ -13,7 +17,7 @@ namespace Stac.Collection public class StacExtent : ICloneable { /// - /// Initialise a new instance of the class. + /// Initializes a new instance of the class. /// /// Spatial Extent. /// Temporal Extent. @@ -25,9 +29,10 @@ public StacExtent(StacSpatialExtent spatial, StacTemporalExtent temporal) } /// + /// Initializes a new instance of the class. /// Initialize a new Stac Extent from an existing one (clone). /// - /// + /// The extent. public StacExtent(StacExtent extent) { this.Spatial = new StacSpatialExtent(extent.Spatial); @@ -60,15 +65,15 @@ public static StacExtent Create(IEnumerable items) minDate = minDate == DateTime.MinValue ? null : minDate; maxDate = maxDate == DateTime.MaxValue ? null : maxDate; return new StacExtent( - new StacSpatialExtent(items.Min(i => i.GetBoundingBoxFromGeometryExtent()[0]), - items.Min(i => i.GetBoundingBoxFromGeometryExtent()[1]), - items.Max(i => i.GetBoundingBoxFromGeometryExtent()[2]), - items.Max(i => i.GetBoundingBoxFromGeometryExtent()[3])), - - new StacTemporalExtent(minDate, maxDate) - ); + new StacSpatialExtent( + items.Min(i => i.GetBoundingBoxFromGeometryExtent()[0]), + items.Min(i => i.GetBoundingBoxFromGeometryExtent()[1]), + items.Max(i => i.GetBoundingBoxFromGeometryExtent()[2]), + items.Max(i => i.GetBoundingBoxFromGeometryExtent()[3])), + new StacTemporalExtent(minDate, maxDate)); } + /// public object Clone() { return new StacExtent(this); @@ -76,22 +81,24 @@ public object Clone() internal void Update(ICollection items) { - Spatial = new StacSpatialExtent(items.Select(i => i.GetBoundingBoxFromGeometryExtent()[0]) + this.Spatial = new StacSpatialExtent( + items.Select(i => i.GetBoundingBoxFromGeometryExtent()[0]) .Concat(new double[] { this.Spatial.BoundingBoxes[0][0] }) .Min(), - items.Select(i => i.GetBoundingBoxFromGeometryExtent()[1]) + items.Select(i => i.GetBoundingBoxFromGeometryExtent()[1]) .Concat(new double[] { this.Spatial.BoundingBoxes[0][1] }) .Min(), - items.Select(i => i.GetBoundingBoxFromGeometryExtent()[2]) + items.Select(i => i.GetBoundingBoxFromGeometryExtent()[2]) .Concat(new double[] { this.Spatial.BoundingBoxes[0][2] }) .Max(), - items.Select(i => i.GetBoundingBoxFromGeometryExtent()[3]) + items.Select(i => i.GetBoundingBoxFromGeometryExtent()[3]) .Concat(new double[] { this.Spatial.BoundingBoxes[0][3] }) .Max()); - Temporal = new StacTemporalExtent(items.Select(i => i.DateTime.Start) + this.Temporal = new StacTemporalExtent( + items.Select(i => i.DateTime.Start) .Concat(new DateTime[] { this.Temporal.Interval[0][0].GetValueOrDefault() }) .Min(), - items.Select(i => i.DateTime.End) + items.Select(i => i.DateTime.End) .Concat(new DateTime[] { this.Temporal.Interval[0][1].GetValueOrDefault() }) .Max()); } diff --git a/src/DotNetStac/Collection/StacSpatialExtent.cs b/src/DotNetStac/Collection/StacSpatialExtent.cs index dee4025f..27e62341 100644 --- a/src/DotNetStac/Collection/StacSpatialExtent.cs +++ b/src/DotNetStac/Collection/StacSpatialExtent.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSpatialExtent.cs + +using System; using Newtonsoft.Json; namespace Stac.Collection @@ -11,7 +15,7 @@ namespace Stac.Collection public class StacSpatialExtent : ICloneable { /// - /// Initialize a new instance of the class with a single extent. + /// Initializes a new instance of the class. /// /// Minimum X bound /// Minimum Y bound @@ -20,20 +24,21 @@ public class StacSpatialExtent : ICloneable [JsonConstructor] public StacSpatialExtent(double minX, double minY, double maxX, double maxY) { - BoundingBoxes = new double[1][] { new double[4] { minX, minY, maxX, maxY } }; + this.BoundingBoxes = new double[1][] { new double[4] { minX, minY, maxX, maxY } }; } /// + /// Initializes a new instance of the class. /// Initialize a new Stac Spatial extent from an existing one (clone) /// - /// + /// The spatial extent. public StacSpatialExtent(StacSpatialExtent spatial) { this.BoundingBoxes = (double[][])spatial.BoundingBoxes.Clone(); } /// - /// Potential spatial extents. + /// Gets or sets potential spatial extents. /// /// Gets/sets double entry array of coordinates [JsonProperty("bbox")] @@ -42,7 +47,7 @@ public StacSpatialExtent(StacSpatialExtent spatial) /// /// Clone this Extent /// - /// + /// A new that is a clone of this instance. public object Clone() { return new StacSpatialExtent(this); diff --git a/src/DotNetStac/Collection/StacSummaryItem.cs b/src/DotNetStac/Collection/StacSummaryItem.cs index f75d894c..bc3e2fd3 100644 --- a/src/DotNetStac/Collection/StacSummaryItem.cs +++ b/src/DotNetStac/Collection/StacSummaryItem.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSummaryItem.cs + using System.Collections; using System.Collections.Generic; using Newtonsoft.Json.Linq; @@ -13,49 +16,52 @@ public abstract class StacSummaryItem : IStacSummaryItem /// /// Json Object /// - protected readonly JToken summary; + private readonly JToken _summary; /// - /// Initialize a new summary item with a JSON object + /// Initializes a new instance of the class. /// - /// + /// The summary. protected StacSummaryItem(JToken summary) { - this.summary = summary; + this._summary = summary; } + /// + /// Gets jToken transformer + /// + /// + /// JToken transformer + /// + public JToken AsJToken => this._summary; + /// /// accessor of fields in the object /// - /// + /// key of the field public JToken this[object key] { get { - return summary[key]; + return this._summary[key]; } } - /// - /// JToken transformer - /// - public JToken AsJToken => summary; - + /// public abstract IEnumerable Enumerate(); /// /// Get Enumerator of object children /// - /// + /// Enumerator of object children public IEnumerator GetEnumerator() { - return summary.Children().GetEnumerator(); + return this._summary.Children().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return summary.Children().GetEnumerator(); + return this._summary.Children().GetEnumerator(); } - } } diff --git a/src/DotNetStac/Collection/StacSummaryRangeObject.cs b/src/DotNetStac/Collection/StacSummaryRangeObject.cs index ef65d35c..d0620c05 100644 --- a/src/DotNetStac/Collection/StacSummaryRangeObject.cs +++ b/src/DotNetStac/Collection/StacSummaryRangeObject.cs @@ -1,9 +1,14 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSummaryRangeObject.cs + +using System; using System.Collections.Generic; using Newtonsoft.Json.Linq; namespace Stac.Collection { +#pragma warning disable SA1649 // File name should match first type name /// /// Class representing a summary Range Object. /// @@ -11,44 +16,49 @@ namespace Stac.Collection public class StacSummaryRangeObject : StacSummaryItem { /// - /// Initialize a Summary Range Object with a JSON object. + /// Initializes a new instance of the class. /// /// JSON Range object - /// Thrown when neither "minimum" nor "maximum" fields are present in the range object. - /// - public StacSummaryRangeObject(JObject summary) : base(summary) + /// Thrown when neither "minimum" nor "maximum" fields are present in the range object. + public StacSummaryRangeObject(JObject summary) + : base(summary) { if (!summary.ContainsKey("minimum") || !summary.ContainsKey("maximum")) + { throw new ArgumentException("summary stats must contains minimum and maximum fields"); + } } /// + /// Initializes a new instance of the class. /// Initialize a Summary Range Object with a minimum and a maximum value /// - /// - /// - /// - public StacSummaryRangeObject(T min, T max) : base(new JObject()) + /// The minimum value + /// The maximum value + public StacSummaryRangeObject(T min, T max) + : base(new JObject()) { - Min = min; - Max = max; + this.Min = min; + this.Max = max; } /// - /// Minimum of the range + /// Gets or sets minimum of the range /// /// Minimum of the range - public T Min { get => summary["minimum"].Value(); set => summary["minimum"] = new JValue(value); } + public T Min { get => this.AsJToken["minimum"].Value(); set => this.AsJToken["minimum"] = new JValue(value); } /// - /// Maximum of the range + /// Gets or sets maximum of the range /// /// Maximum of the range - public T Max { get => summary["maximum"].Value(); set => summary["maximum"] = new JValue(value); } + public T Max { get => this.AsJToken["maximum"].Value(); set => this.AsJToken["maximum"] = new JValue(value); } + /// public override IEnumerable Enumerate() { - return new object[2] { Min, Max }; + return new object[2] { this.Min, this.Max }; } } +#pragma warning restore SA1649 // File name should match first type name } diff --git a/src/DotNetStac/Collection/StacSummaryValueSet.cs b/src/DotNetStac/Collection/StacSummaryValueSet.cs index e5b7aae5..4431e2b9 100644 --- a/src/DotNetStac/Collection/StacSummaryValueSet.cs +++ b/src/DotNetStac/Collection/StacSummaryValueSet.cs @@ -1,13 +1,15 @@ -using System; -using System.Collections; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSummaryValueSet.cs + using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Stac.Collection; namespace Stac.Collection { +#pragma warning disable SA1649 // File name should match first type name + /// /// Class representing a summary value set /// @@ -15,56 +17,73 @@ namespace Stac.Collection public class StacSummaryValueSet : StacSummaryItem, IEnumerable { /// - /// Initialize an empty Summary Value Set + /// Initializes a new instance of the class. /// - public StacSummaryValueSet() : base(new JArray()) + public StacSummaryValueSet() + : base(new JArray()) { } /// + /// Initializes a new instance of the class. /// Initialize a Summary Value Set with a JSON array /// /// JSON Array - public StacSummaryValueSet(JArray summarySet) : base(summarySet) + public StacSummaryValueSet(JArray summarySet) + : base(summarySet) { } /// + /// Initializes a new instance of the class. /// Initialize a Summary Value Set with a set of values /// /// set of values - public StacSummaryValueSet(IEnumerable summarySet) : base(new JArray(summarySet)) + public StacSummaryValueSet(IEnumerable summarySet) + : base(new JArray(summarySet)) { } /// - /// Add a value item in the Summary Value Set + /// Gets summary Value Set total of items /// - /// value item - public void Add(T item) - { - ((JArray)summary).Add(item); - } + /// + /// Summary Value Set total of items + /// - /// + /// /// Summary Value Set total of items - /// - /// - public int Count => summary.Count(); + /// + public int Count => this.AsJToken.Count(); /// + /// Gets get the Summary Value Set as an enumerable + /// + /// /// Get the Summary Value Set as an enumerable + /// + public IEnumerable SummarySet { get => this.AsJToken.ToObject>(); } + + /// + /// Add a value item in the Summary Value Set /// - public IEnumerable SummarySet { get => summary.ToObject>(); } + /// value item + public void Add(T item) + { + ((JArray)this.AsJToken).Add(item); + } IEnumerator IEnumerable.GetEnumerator() { - return SummarySet.GetEnumerator(); + return this.SummarySet.GetEnumerator(); } + /// public override IEnumerable Enumerate() { return this; } } + +#pragma warning restore SA1649 // File name should match first type name } diff --git a/src/DotNetStac/Collection/StacTemporalExtent.cs b/src/DotNetStac/Collection/StacTemporalExtent.cs index 228d7f91..3668490b 100644 --- a/src/DotNetStac/Collection/StacTemporalExtent.cs +++ b/src/DotNetStac/Collection/StacTemporalExtent.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacTemporalExtent.cs + +using System; using Newtonsoft.Json; namespace Stac.Collection @@ -10,32 +14,31 @@ namespace Stac.Collection [JsonObject] public class StacTemporalExtent { - - /// - /// Initialize a new instance of the class with a single extent. + /// Initializes a new instance of the class. /// - /// - /// + /// Start time + /// End time [JsonConstructor] public StacTemporalExtent(DateTime? start, DateTime? end) { - Interval = new DateTime?[1][] { new DateTime?[2] { start, end } }; + this.Interval = new DateTime?[1][] { new DateTime?[2] { start, end } }; } /// + /// Initializes a new instance of the class. /// Intialize a new Stac Temporal Extent from an exisiting one (clone) /// - /// + /// The temporal extent to clone public StacTemporalExtent(StacTemporalExtent temporal) { - this.Interval = (System.DateTime?[][])temporal.Interval.Clone(); + this.Interval = (DateTime?[][])temporal.Interval.Clone(); } /// - /// Potential temporal extents. + /// Gets or sets potential temporal extents. /// - /// + /// Potential temporal extents. [JsonProperty("interval")] public DateTime?[][] Interval { get; set; } } diff --git a/src/DotNetStac/Collection/SummaryItemType.cs b/src/DotNetStac/Collection/SummaryItemType.cs index f47e8044..45e24b07 100644 --- a/src/DotNetStac/Collection/SummaryItemType.cs +++ b/src/DotNetStac/Collection/SummaryItemType.cs @@ -1,14 +1,24 @@ -namespace Stac.Collection +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SummaryItemType.cs + +namespace Stac.Collection { /// /// Summary types /// public enum SummaryItemType { +#pragma warning disable SA1300 // Element should begin with upper-case letter + /// /// Summary Value Set + /// ValueSet, + /// /// Summary Range Object - RangeObject + /// + RangeObject, +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Common/DataType.cs b/src/DotNetStac/Common/DataType.cs index 2865b94d..ebafef34 100644 --- a/src/DotNetStac/Common/DataType.cs +++ b/src/DotNetStac/Common/DataType.cs @@ -1,4 +1,8 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DataType.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Common @@ -9,38 +13,61 @@ namespace Stac.Common [JsonConverter(typeof(StringEnumConverter))] public enum DataType { - /// 8-bit integer +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + + // 8-bit integer int8, - /// 16-bit integer + + // 16-bit integer int16, - /// 32-bit integer + + // 32-bit integer int32, - /// 64-bit integer + + // 64-bit integer int64, - /// unsigned 8-bit integer (common for 8-bit RGB PNG's) + + // unsigned 8-bit integer (common for 8-bit RGB PNG's) uint8, - /// unsigned 16-bit integer + + // unsigned 16-bit integer uint16, - /// unsigned 32-bit integer + + // unsigned 32-bit integer uint32, - /// unsigned 64-bit integer + + // unsigned 64-bit integer uint64, - /// 16-bit float + + // 16-bit float float16, - /// 32-bit float + + // 32-bit float float32, - /// 64-big float + + // 64-big float float64, - /// 16-bit complex integer + + // 16-bit complex integer cint16, - /// 32-bit complex integer + + // 32-bit complex integer cint32, - /// 32-bit complex float + + // 32-bit complex float cfloat32, - /// 64-bit complex float + + // 64-bit complex float cfloat64, - /// Other data type than the ones listed above (e.g. boolean, string, higher precision numbers) - other + + // Other data type than the ones listed above (e.g. boolean, string, higher precision numbers) + other, + +#pragma warning restore SA1300 // Element should begin with upper-case letter +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } } diff --git a/src/DotNetStac/Common/JsonMergeUtils.cs b/src/DotNetStac/Common/JsonMergeUtils.cs index 46501846..5c7d2e2c 100644 --- a/src/DotNetStac/Common/JsonMergeUtils.cs +++ b/src/DotNetStac/Common/JsonMergeUtils.cs @@ -1,5 +1,8 @@ -using System; -using System.Buffers; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: JsonMergeUtils.cs + +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -11,15 +14,17 @@ namespace Stac.Common { + /// + /// Utility class for merging JSON documents. + /// public class JsonMergeUtils { - /// /// Return the result of merging the original JSON document with the JSON Merge patch document - /// according to https://tools.ietf.org/html/rfc7386 + /// according to https://tools.ietf.org/html/rfc7386 /// - /// - /// + /// Original JSON document to merge new content into. + /// JSON Merge patch document. /// Writer options used to write the merge result. /// The document that represents the merge result. public static string Merge(string original, string patch, JsonWriterOptions? writerOptions = null) @@ -30,7 +35,6 @@ public static string Merge(string original, string patch, JsonWriterOptions? wri using (var patchDoc = JsonDocument.Parse(patch)) using (var jsonWriter = new Utf8JsonWriter(memStream, writerOptions ?? new JsonWriterOptions { Indented = true })) { - var originalKind = originalDoc.RootElement.ValueKind; var patchKind = patchDoc.RootElement.ValueKind; @@ -52,21 +56,22 @@ public static string Merge(string original, string patch, JsonWriterOptions? wri MergeObjects(jsonWriter, originalDoc.RootElement, patchDoc.RootElement); } - return Encoding.UTF8.GetString(memStream.ToArray()); } /// /// Return the result of merging the original JSON document with the JSON Merge patch document - /// according to https://tools.ietf.org/html/rfc7386 + /// according to https://tools.ietf.org/html/rfc7386 /// - /// - /// + /// Original JSON document to merge new content into. + /// JSON Merge patch document. + /// Cancellation token. /// Writer options used to write the merge result. - public static async Task MergeAsync(string original, System.IO.Stream patch, CancellationToken token = default, JsonWriterOptions? writerOptions = null) + /// The document that represents the merge result. + public static async Task MergeAsync(string original, Stream patch, CancellationToken token = default, JsonWriterOptions? writerOptions = null) { var outputBuffer = new MemoryStream(); - var jsonDocumentOptions = new JsonDocumentOptions(); + var jsonDocumentOptions = default(JsonDocumentOptions); using (var originalDoc = JsonDocument.Parse(original, jsonDocumentOptions)) using (var patchDoc = await JsonDocument.ParseAsync(patch, jsonDocumentOptions, token)) using (var jsonWriter = new Utf8JsonWriter(outputBuffer, writerOptions ?? new JsonWriterOptions { Indented = true })) @@ -100,12 +105,10 @@ public static async Task MergeAsync(string original, System.IO.Stream pa /// /// Extract property names with a null value. /// - /// Nested field names are returned joined by "." + /// Nested field names are returned joined by "." /// Array items are ignored. /// - /// - /// - /// Writer options used to write the merge result. + /// JSON Merge patch document. /// The list of null properties. public static List ExtractNullProperties(string patch) { @@ -121,17 +124,15 @@ public static List ExtractNullProperties(string patch) /// /// Extract property names with a null value. /// - /// Nested field names are returned joined by "." + /// Nested field names are returned joined by "." /// Array items are ignored. /// - /// - /// - /// Writer options used to write the merge result. + /// JSON Merge patch document. /// Cancellation token. /// The list of null properties. - public static async Task> ExtractNullPropertiesAsync(System.IO.Stream patch, CancellationToken token = default) + public static async Task> ExtractNullPropertiesAsync(Stream patch, CancellationToken token = default) { - var patchDoc = await JsonDocument.ParseAsync(patch, new JsonDocumentOptions(), token); + var patchDoc = await JsonDocument.ParseAsync(patch, default(JsonDocumentOptions), token); if (patchDoc.RootElement.ValueKind != JsonValueKind.Object) { throw new InvalidOperationException($"The patch JSON document must be an object type. Instead it is {patchDoc.RootElement.ValueKind}."); @@ -145,8 +146,8 @@ public static async Task> ExtractNullPropertiesAsync(System.IO.Stre /// to serialize and deserialize the model. /// /// the model type - /// - /// + /// Original model to merge new content into. + /// JSON Merge patch document. /// JSON serialization options /// A new model representing the patched instance. public static T MergeModel(T original, string patch, JsonSerializerOptions options = null) @@ -159,14 +160,13 @@ public static T MergeModel(T original, string patch, JsonSerializerOptions op /// Apply the result of a JSON merge patch to the given model, using System.Text.Json serializer /// to serialize and deserialize the model. /// - /// /// the model type - /// - /// + /// Original model to merge new content into. + /// JSON Merge patch document. /// JSON serialization options /// Cancellation token /// A task that returns a new model representing the patched instance. - public static async Task MergeModelAsync(T original, System.IO.Stream patch, JsonSerializerOptions options = null, CancellationToken token = default) + public static async Task MergeModelAsync(T original, Stream patch, JsonSerializerOptions options = null, CancellationToken token = default) { var originalJson = JsonSerializer.Serialize(original, options); return JsonSerializer.Deserialize(await MergeAsync(originalJson, patch, token), options); @@ -174,7 +174,7 @@ public static async Task MergeModelAsync(T original, System.IO.Stream patc private static IEnumerable ExtractNullPropertiesFromObject(JsonElement patch) { - Debug.Assert(patch.ValueKind == JsonValueKind.Object); + Debug.Assert(patch.ValueKind == JsonValueKind.Object, "The patch JSON document must be an object type."); foreach (var property in patch.EnumerateObject()) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -193,8 +193,8 @@ private static IEnumerable ExtractNullPropertiesFromObject(JsonElement p private static void MergeObjects(Utf8JsonWriter jsonWriter, JsonElement original, JsonElement patch) { - Debug.Assert(original.ValueKind == JsonValueKind.Object); - Debug.Assert(patch.ValueKind == JsonValueKind.Object); + Debug.Assert(original.ValueKind == JsonValueKind.Object, "The original JSON document to merge new content into must be an object type."); + Debug.Assert(patch.ValueKind == JsonValueKind.Object, "The patch JSON document must be an object type."); jsonWriter.WriteStartObject(); diff --git a/src/DotNetStac/Common/Patch.cs b/src/DotNetStac/Common/Patch.cs new file mode 100644 index 00000000..f6cdd42a --- /dev/null +++ b/src/DotNetStac/Common/Patch.cs @@ -0,0 +1,15 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Patch.cs + +using System.Collections.Generic; + +namespace Stac.Common +{ + /// + /// Patch Object + /// + public class Patch : Dictionary + { + } +} diff --git a/src/DotNetStac/Common/PatchHelpers.cs b/src/DotNetStac/Common/PatchHelpers.cs index 89ca9bd8..fa6cdaa1 100644 --- a/src/DotNetStac/Common/PatchHelpers.cs +++ b/src/DotNetStac/Common/PatchHelpers.cs @@ -1,13 +1,27 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: PatchHelpers.cs + +using System.Collections.Generic; using System.Linq; -using GeoJSON.Net.Geometry; using Newtonsoft.Json; namespace Stac.Common { + /// + /// Patch helpers + /// public static class PatchHelpers { - public static T Patch(this T stacObject, IDictionary patch) where T : IStacObject + /// + /// Patches the specified stac object with a dictionary. + /// + /// The type of the stac object. + /// The stac object. + /// The patch. + /// The patched stac object. + public static T Patch(this T stacObject, IDictionary patch) + where T : IStacObject { var itemJson = StacConvert.Serialize(stacObject); var patchJson = JsonConvert.SerializeObject(patch); @@ -15,7 +29,15 @@ public static T Patch(this T stacObject, IDictionary patch) w return StacConvert.Deserialize(patchedJson); } - public static T Patch(this T stacObject, IStacObject patch) where T : IStacObject + /// + /// Patches the specified stac object with another stac object. + /// + /// The type of the stac object. + /// The stac object. + /// The patch. + /// The patched stac object. + public static T Patch(this T stacObject, IStacObject patch) + where T : IStacObject { var itemJson = StacConvert.Serialize(stacObject); var patchJson = StacConvert.Serialize(patch); @@ -25,6 +47,7 @@ public static T Patch(this T stacObject, IStacObject patch) where T : IStacOb { patchdic.Remove("links"); } + return Patch(stacObject, patchdic); } } diff --git a/src/DotNetStac/Common/PatchStacItem.cs b/src/DotNetStac/Common/PatchStacItem.cs deleted file mode 100644 index e450a3bf..00000000 --- a/src/DotNetStac/Common/PatchStacItem.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Collections.Generic; - -namespace Stac.Common -{ - public class Patch : Dictionary - { - } -} diff --git a/src/DotNetStac/Common/PropertyObservableCollection.cs b/src/DotNetStac/Common/PropertyObservableCollection.cs index 76855cee..924c801e 100644 --- a/src/DotNetStac/Common/PropertyObservableCollection.cs +++ b/src/DotNetStac/Common/PropertyObservableCollection.cs @@ -1,27 +1,61 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: PropertyObservableCollection.cs + using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; namespace Stac.Common { +#pragma warning disable SA1649 // File name should match first type name + + /// + /// A collection that is observable and that is also stored in a as a property. + /// + /// The type of the elements in the collection. public class PropertyObservableCollection : ObservableCollection { - public PropertyObservableCollection(IStacPropertiesContainer propertiesContainer, string key) : base() + /// + /// Initializes a new instance of the class. + /// + /// The properties container. + /// The property key. + public PropertyObservableCollection(IStacPropertiesContainer propertiesContainer, string key) + : base() { - PropertiesContainer = propertiesContainer; - Key = key; - this.CollectionChanged += ObservableCollectionInPropertiesChanged; + this.PropertiesContainer = propertiesContainer; + this.Key = key; + this.CollectionChanged += this.ObservableCollectionInPropertiesChanged; } + /// + /// Gets the properties container. + /// + /// + /// The properties container. + /// public IStacPropertiesContainer PropertiesContainer { get; } + + /// + /// Gets the property key. + /// + /// + /// The property key. + /// public string Key { get; } private void ObservableCollectionInPropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) { - PropertiesContainer.RemoveProperty(Key); - if (this.Count == 0) return; - PropertiesContainer.SetProperty(Key, this.ToList()); + this.PropertiesContainer.RemoveProperty(this.Key); + if (this.Count == 0) + { + return; + } + + this.PropertiesContainer.SetProperty(this.Key, this.ToList()); } } + +#pragma warning restore SA1649 // File name should match first type name } diff --git a/src/DotNetStac/Common/Statistics.cs b/src/DotNetStac/Common/Statistics.cs index e3b49be5..1518280f 100644 --- a/src/DotNetStac/Common/Statistics.cs +++ b/src/DotNetStac/Common/Statistics.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Statistics.cs + +using System.Collections.Generic; using Newtonsoft.Json; namespace Stac.Common @@ -9,63 +13,79 @@ namespace Stac.Common [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class Statistics { - private IDictionary properties; + private IDictionary _properties; /// - /// Initialize a new statistics object + /// Initializes a new instance of the class. /// + /// minimum value + /// maximum value + /// mean value + /// standard deviation + /// valid percentage [JsonConstructor] public Statistics(double? minimum, double? maximum, double? mean, double? stdev, double? validPercent) { - Mean = mean; - Minimum = minimum; - Maximum = maximum; - Stdev = stdev; - ValidPercent = validPercent; - properties = new Dictionary(); + this.Mean = mean; + this.Minimum = minimum; + this.Maximum = maximum; + this.Stdev = stdev; + this.ValidPercent = validPercent; + this._properties = new Dictionary(); } /// - /// mean value + /// Gets or sets mean value /// - /// + /// + /// Mean value + /// [JsonProperty("mean")] public double? Mean { get; set; } /// - /// minimum value + /// Gets or sets minimum value /// - /// + /// + /// Minimum value + /// [JsonProperty("minimum")] public double? Minimum { get; set; } /// - /// maximum value + /// Gets or sets maximum value /// - /// + /// + /// Maximum value + /// [JsonProperty("maximum")] public double? Maximum { get; set; } /// - /// Standard Deviation + /// Gets or sets standard Deviation /// - /// + /// + /// Standard Deviation + /// [JsonProperty("stdev")] public double? Stdev { get; set; } /// - /// valid percentage + /// Gets or sets valid percentage /// - /// + /// + /// Valid percentage + /// [JsonProperty("valid_percent")] public double? ValidPercent { get; set; } /// - /// Additional fields + /// Gets or sets additional fields /// - /// + /// + /// Additional fields + /// [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } - + public IDictionary Properties { get => this._properties; set => this._properties = value; } } } diff --git a/src/DotNetStac/Common/TolerantEnumConverter.cs b/src/DotNetStac/Common/TolerantEnumConverter.cs index a037f3da..3d359c97 100644 --- a/src/DotNetStac/Common/TolerantEnumConverter.cs +++ b/src/DotNetStac/Common/TolerantEnumConverter.cs @@ -1,21 +1,24 @@ - +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: TolerantEnumConverter.cs + using System; using System.Linq; using Newtonsoft.Json; namespace Stac.Common { - class TolerantEnumConverter : JsonConverter + internal class TolerantEnumConverter : JsonConverter { public override bool CanConvert(Type objectType) { - Type type = IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType; + Type type = this.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType; return type.IsEnum; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - bool isNullable = IsNullableType(objectType); + bool isNullable = this.IsNullableType(objectType); Type enumType = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; string[] names = Enum.GetNames(enumType); @@ -70,7 +73,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s private bool IsNullableType(Type t) { - return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)); + return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>); } } } diff --git a/src/DotNetStac/Converters/CollectionConverter.cs b/src/DotNetStac/Converters/CollectionConverter.cs index a1d09e50..76d546d3 100644 --- a/src/DotNetStac/Converters/CollectionConverter.cs +++ b/src/DotNetStac/Converters/CollectionConverter.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: CollectionConverter.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Newtonsoft.Json; @@ -6,13 +10,26 @@ namespace Stac.Converters { +#pragma warning disable SA1649 // File name should match first type name + /// + /// Converter for Collection + /// + /// Type of the collection public class CollectionConverter : JsonConverter { + /// + public override bool CanRead => true; + + /// + public override bool CanWrite => true; + + /// public override bool CanConvert(Type objectType) { - return (objectType == typeof(Collection)); + return objectType == typeof(Collection); } + /// public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); @@ -20,13 +37,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { return new Collection(token.ToObject>()); } + return new Collection(); } - public override bool CanRead => true; - - public override bool CanWrite => true; - + /// public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Collection collection = (Collection)value; @@ -35,7 +50,9 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s { serializer.Serialize(writer, item); } + writer.WriteEndArray(); } } +#pragma warning restore SA1649 // File name should match first type name } diff --git a/src/DotNetStac/Converters/ContentTypeConverter.cs b/src/DotNetStac/Converters/ContentTypeConverter.cs index 8679419a..14421ab1 100644 --- a/src/DotNetStac/Converters/ContentTypeConverter.cs +++ b/src/DotNetStac/Converters/ContentTypeConverter.cs @@ -1,6 +1,9 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ContentTypeConverter.cs + +using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Linq; using System.Net.Mime; using Newtonsoft.Json; @@ -11,7 +14,7 @@ internal class ContentTypeConverter : JsonConverter { public override bool CanConvert(Type objectType) { - return (objectType == typeof(ContentType)); + return objectType == typeof(ContentType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) diff --git a/src/DotNetStac/Converters/SemVersionConverter.cs b/src/DotNetStac/Converters/SemVersionConverter.cs index b73ec9aa..a5d210fe 100644 --- a/src/DotNetStac/Converters/SemVersionConverter.cs +++ b/src/DotNetStac/Converters/SemVersionConverter.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SemVersionConverter.cs + +using System; using Newtonsoft.Json; using Semver; @@ -8,7 +12,7 @@ internal class SemVersionConverter : JsonConverter { public override bool CanConvert(Type objectType) { - return (objectType == typeof(SemVersion)); + return objectType == typeof(SemVersion); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) diff --git a/src/DotNetStac/Converters/StacSummariesConverter.cs b/src/DotNetStac/Converters/StacSummariesConverter.cs index c59de98c..642b3c09 100644 --- a/src/DotNetStac/Converters/StacSummariesConverter.cs +++ b/src/DotNetStac/Converters/StacSummariesConverter.cs @@ -1,8 +1,10 @@ -using System; -using System.Collections; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSummariesConverter.cs + +using System; using System.Collections.Generic; using System.Linq; -using System.Net.Mime; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stac.Collection; @@ -13,7 +15,7 @@ internal class StacSummariesConverter : JsonConverter { public override bool CanConvert(Type objectType) { - return (objectType == typeof(Dictionary)); + return objectType == typeof(Dictionary); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) @@ -25,7 +27,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist { if (objDic[key] is JArray) { - JArray enumerable = (objDic[key] as JArray); + JArray enumerable = objDic[key] as JArray; switch (enumerable.First().Type) { case JTokenType.Boolean: @@ -48,9 +50,10 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist break; } } + if (objDic[key] is JObject) { - JObject obj = (objDic[key] as JObject); + JObject obj = objDic[key] as JObject; if (obj.ContainsKey("minimum") && obj.ContainsKey("maximum")) { switch (obj["minimum"].Type) diff --git a/src/DotNetStac/DotNetStac.csproj b/src/DotNetStac/DotNetStac.csproj index a66a326f..d2ea776d 100644 --- a/src/DotNetStac/DotNetStac.csproj +++ b/src/DotNetStac/DotNetStac.csproj @@ -4,7 +4,7 @@ DotNetStac Terradue .Net library for working with any SpatioTemporal Asset Catalog LICENSE - 1.6.6 + 1.7.0 Emmanuel Mathot emmanuelmathot Terradue @@ -12,11 +12,12 @@ true STAC;Terradue;Geo;Json stac_logo_128.png - Copyright (c) 2010-2021 by Terradue + Copyright (c) by Terradue Srl. All Rights Reserved.\nLicense under the AGPL, Version 3.0. $(ProjectDir)StyleCop.ruleset true full true + 1636;1200;1629;1309 diff --git a/src/DotNetStac/Exceptions/InvalidStacDataException.cs b/src/DotNetStac/Exceptions/InvalidStacDataException.cs index f9ddc91d..bb64f279 100644 --- a/src/DotNetStac/Exceptions/InvalidStacDataException.cs +++ b/src/DotNetStac/Exceptions/InvalidStacDataException.cs @@ -1,24 +1,51 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: InvalidStacDataException.cs + +using System; using System.Runtime.Serialization; namespace Stac.Exceptions { + /// + /// Exception thrown when the STAC data is invalid + /// [Serializable] public class InvalidStacDataException : Exception { + /// + /// Initializes a new instance of the class. + /// public InvalidStacDataException() { } - public InvalidStacDataException(string message) : base(message) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public InvalidStacDataException(string message) + : base(message) { } - public InvalidStacDataException(string message, Exception innerException) : base(message, innerException) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public InvalidStacDataException(string message, Exception innerException) + : base(message, innerException) { } - protected InvalidStacDataException(SerializationInfo info, StreamingContext context) : base(info, context) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + protected InvalidStacDataException(SerializationInfo info, StreamingContext context) + : base(info, context) { } } diff --git a/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs b/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs index 862c86e7..2fd9dfdc 100644 --- a/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs +++ b/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs @@ -1,24 +1,51 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: InvalidStacSchemaException.cs + +using System; using System.Runtime.Serialization; namespace Stac.Exceptions { + /// + /// Exception thrown when the STAC schema is invalid + /// [Serializable] public class InvalidStacSchemaException : Exception { + /// + /// Initializes a new instance of the class. + /// public InvalidStacSchemaException() { } - public InvalidStacSchemaException(string message) : base(message) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + public InvalidStacSchemaException(string message) + : base(message) { } - public InvalidStacSchemaException(string message, Exception innerException) : base(message, innerException) + /// + /// Initializes a new instance of the class. + /// + /// The message that describes the error. + /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + public InvalidStacSchemaException(string message, Exception innerException) + : base(message, innerException) { } - protected InvalidStacSchemaException(SerializationInfo info, StreamingContext context) : base(info, context) + /// + /// Initializes a new instance of the class. + /// + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. + protected InvalidStacSchemaException(SerializationInfo info, StreamingContext context) + : base(info, context) { } } diff --git a/src/DotNetStac/Extensions/Alternate/AlternateAssetObject.cs b/src/DotNetStac/Extensions/Alternate/AlternateAssetObject.cs index f1a0f64f..98f7cf43 100644 --- a/src/DotNetStac/Extensions/Alternate/AlternateAssetObject.cs +++ b/src/DotNetStac/Extensions/Alternate/AlternateAssetObject.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: AlternateAssetObject.cs + +using System; using System.Collections.Generic; using Newtonsoft.Json; @@ -11,16 +15,15 @@ namespace Stac.Extensions.Alternate [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class AlternateAssetObject : IStacPropertiesContainer { - private string href; private readonly IStacObject _parent; - private string title; - - private string description; + private string _href; + private string _title; - IDictionary properties; + private string _description; + private IDictionary _properties; /// - /// Initialize a new Band Object + /// Initializes a new instance of the class. /// /// URI to the asset object /// Parent object @@ -28,51 +31,74 @@ public class AlternateAssetObject : IStacPropertiesContainer /// A description of the Asset providing additional details, such as how it was processed or created. CommonMark 0.29 syntax MAY be used for rich text representation. public AlternateAssetObject(string href, IStacObject parent = null, string title = null, string description = null) { - this.href = href; - _parent = parent; - this.title = title; - this.description = description; - properties = new Dictionary(); + this._href = href; + this._parent = parent; + this._title = title; + this._description = description; + this._properties = new Dictionary(); } /// - /// REQUIRED. URI to the asset object. Relative and absolute URI are both allowed. + /// Gets or sets rEQUIRED. URI to the asset object. Relative and absolute URI are both allowed. /// + /// + /// REQUIRED. URI to the asset object. Relative and absolute URI are both allowed. + /// [JsonProperty("href")] [JsonRequired] - public string Href { get => href; set => href = value; } + public string Href { get => this._href; set => this._href = value; } /// - /// The displayed title for clients and users. + /// Gets or sets the displayed title for clients and users. /// + /// + /// The displayed title for clients and users. + /// [JsonProperty("title")] - public string Title { get => title; set => title = value; } + public string Title { get => this._title; set => this._title = value; } /// - /// A description of the Asset providing additional details, such as how it was processed or created. CommonMark 0.29 syntax MAY be used for rich text representation. + /// Gets or sets a description of the Asset providing additional details, such as how it was processed or created. CommonMark 0.29 syntax MAY be used for rich text representation. /// + /// + /// A description of the Asset providing additional details, such as how it was processed or created. CommonMark 0.29 syntax MAY be used for rich text representation. + /// [JsonProperty("description")] - public string Description { get => description; set => description = value; } + public string Description { get => this._description; set => this._description = value; } /// - /// Additional fields + /// Gets or sets additional fields /// - /// + /// + /// Additional fields + /// [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } + public IDictionary Properties { get => this._properties; set => this._properties = value; } /// - /// Parent Stac Object + /// Gets parent Stac Object /// - /// + /// + /// Parent Stac Object + /// + + /// + /// Parent Stac Object + /// [JsonIgnore] - public IStacObject StacObjectContainer => _parent; + public IStacObject StacObjectContainer => this._parent; /// - /// Uri + /// Gets uri /// - /// + /// + /// Uri + /// + + /// + /// Uri + /// [JsonIgnore] - public Uri Uri => new Uri(href); + public Uri Uri => new Uri(this._href); } } diff --git a/src/DotNetStac/Extensions/Alternate/AlternateStacExtension.cs b/src/DotNetStac/Extensions/Alternate/AlternateStacExtension.cs index 55fd35c7..0231b33a 100644 --- a/src/DotNetStac/Extensions/Alternate/AlternateStacExtension.cs +++ b/src/DotNetStac/Extensions/Alternate/AlternateStacExtension.cs @@ -1,7 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: AlternateStacExtension.cs + +using System; using System.Collections.Generic; using System.Linq; -using Stac.Extensions.Storage; namespace Stac.Extensions.Alternate { @@ -10,83 +13,81 @@ namespace Stac.Extensions.Alternate /// public class AlternateStacExtension : StacPropertiesContainerExtension, IStacAssetExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/alternate-assets/v1.1.0/schema.json"; private const string AlternateField = "alternate"; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member - private static IDictionary assetFields; + private readonly IDictionary _assetFields; - internal AlternateStacExtension(StacAsset stacAsset) : base(JsonSchemaUrl, stacAsset) + internal AlternateStacExtension(StacAsset stacAsset) + : base(JsonSchemaUrl, stacAsset) { - assetFields = new Dictionary(); - assetFields.Add(AlternateField, typeof(AlternateAssetObject[])); + this._assetFields = new Dictionary(); + this._assetFields.Add(AlternateField, typeof(AlternateAssetObject[])); } /// - /// A dictionary of alternate location information for an asset. + /// Gets or sets a dictionary of alternate location information for an asset. /// + /// + /// A dictionary of alternate location information for an asset. + /// public IDictionary AlternateAssets { - get { return StacPropertiesContainer.GetProperty>(AlternateField); } + get + { + return this.StacPropertiesContainer.GetProperty>(AlternateField); + } + set { if (value == null || value.Count() == 0) - StacPropertiesContainer.RemoveProperty(AlternateField); + { + this.StacPropertiesContainer.RemoveProperty(AlternateField); + } else { - StacPropertiesContainer.SetProperty(AlternateField, value); - DeclareStacExtension(); + this.StacPropertiesContainer.SetProperty(AlternateField, value); + this.DeclareStacExtension(); } } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => assetFields; + /// + /// Potential fields and their types + /// + public override IDictionary ItemFields => this._assetFields; - public StacAsset StacAsset => StacPropertiesContainer as StacAsset; + /// + public StacAsset StacAsset => this.StacPropertiesContainer as StacAsset; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } + /// + /// Adds an alternate asset to the AlternateAssets dictionary + /// + /// The key of the alternate asset + /// The uri of the alternate asset + /// The title of the alternate asset + /// The description of the alternate asset + /// The alternate asset object public AlternateAssetObject AddAlternate(string key, Uri uri, string title = null, string description = null) { - AlternateAssetObject alternateAssetObject = new AlternateAssetObject(uri.ToString(), StacAsset.ParentStacObject, title, description); - var alternateAssets = AlternateAssets ?? new Dictionary(); + AlternateAssetObject alternateAssetObject = new AlternateAssetObject(uri.ToString(), this.StacAsset.ParentStacObject, title, description); + var alternateAssets = this.AlternateAssets ?? new Dictionary(); alternateAssets.Add(key, alternateAssetObject); - AlternateAssets = alternateAssets; + this.AlternateAssets = alternateAssets; return alternateAssetObject; } - - - - } - - /// - /// Extension methods for accessing Alternate extension - /// - public static class AlternateStacExtensionExtensions - { - - /// - /// Initilize a AlternateStacExtension class from a STAC asset - /// - public static AlternateStacExtension AlternateExtension(this StacAsset stacAsset) - { - return new AlternateStacExtension(stacAsset); - } - - /// - /// Initilize a AlternateStacExtension class from an alternate asset - /// - public static StorageStacExtension StorageExtension(this AlternateAssetObject alternateAssetObject) - { - return new StorageStacExtension(alternateAssetObject); - } } } diff --git a/src/DotNetStac/Extensions/Alternate/AlternateStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Alternate/AlternateStacExtensionExtensions.cs new file mode 100644 index 00000000..fe425a23 --- /dev/null +++ b/src/DotNetStac/Extensions/Alternate/AlternateStacExtensionExtensions.cs @@ -0,0 +1,34 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: AlternateStacExtensionExtensions.cs + +using Stac.Extensions.Storage; + +namespace Stac.Extensions.Alternate +{ + /// + /// Extension methods for accessing Alternate extension + /// + public static class AlternateStacExtensionExtensions + { + /// + /// Initilize a AlternateStacExtension class from a STAC asset + /// + /// The STAC asset. + /// The AlternateStacExtension class + public static AlternateStacExtension AlternateExtension(this StacAsset stacAsset) + { + return new AlternateStacExtension(stacAsset); + } + + /// + /// Initilize a AlternateStacExtension class from an alternate asset + /// + /// The alternate asset. + /// The AlternateStacExtension class + public static StorageStacExtension StorageExtension(this AlternateAssetObject alternateAssetObject) + { + return new StorageStacExtension(alternateAssetObject); + } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeAxis.cs b/src/DotNetStac/Extensions/Datacube/DatacubeAxis.cs index 6d45a126..d25d99d2 100644 --- a/src/DotNetStac/Extensions/Datacube/DatacubeAxis.cs +++ b/src/DotNetStac/Extensions/Datacube/DatacubeAxis.cs @@ -1,15 +1,28 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeAxis.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Extensions.Datacube { + /// + /// Datacube axis + /// [JsonConverter(typeof(StringEnumConverter))] public enum DatacubeAxis { +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member x, y, - z + z, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimension.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimension.cs new file mode 100644 index 00000000..91feecd0 --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimension.cs @@ -0,0 +1,90 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimension.cs + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Stac.Extensions.Datacube +{ + /// + /// Represents the Dimension Object + /// of the Datacube extension + /// + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public class DatacubeDimension : IStacPropertiesContainer + { + private string _type; + private string _description; + private double[] _extent; + private object _values; + private double? _step; + private IDictionary _properties; + + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimension() + { + this._properties = new Dictionary(); + } + + /// + /// Gets or sets type of the dimension. + /// + /// + /// Type of the dimension. + /// + [JsonProperty("type")] + public string Type { get => this._type; set => this._type = value; } + + /// + /// Gets or sets detailed multi-line description to explain the dimension. CommonMark 0.29 syntax MAY be used for rich text representation. + /// + /// + /// Detailed multi-line description to explain the dimension. CommonMark 0.29 syntax MAY be used for rich text representation. + /// + [JsonProperty("description")] + public string Description { get => this._description; set => this._description = value; } + + /// + /// Gets or sets extent (lower and upper bounds) of the dimension as two-element array. Open intervals with null are not allowed. + /// + /// + /// Extent (lower and upper bounds) of the dimension as two-element array. Open intervals with null are not allowed. + /// + [JsonProperty("extent")] + public double[] Extent { get => this._extent; set => this._extent = value; } + + /// + /// Gets or sets optionally, an ordered list of all values. + /// + /// + /// Optionally, an ordered list of all values. + /// + [JsonProperty("values")] + public object Values { get => this._values; set => this._values = value; } + + /// + /// Gets or sets the space between the values. Use null for irregularly spaced steps. + /// + /// + /// The space between the values. Use null for irregularly spaced steps. + /// + [JsonProperty("step")] + public double? Step { get => this._step; set => this._step = value; } + + /// + /// Gets or sets additional fields + /// + /// + /// Additional fields + /// + [JsonExtensionData] + public IDictionary Properties { get => this._properties; set => this._properties = value; } + + /// + [JsonIgnore] + public IStacObject StacObjectContainer => null; + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionAdditional.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionAdditional.cs new file mode 100644 index 00000000..34c0caa4 --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionAdditional.cs @@ -0,0 +1,37 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionAdditional.cs + +using Newtonsoft.Json; + +namespace Stac.Extensions.Datacube +{ + /// + /// Datacube additional dimension + /// + public class DatacubeDimensionAdditional : DatacubeDimension + { + private object _reference_system; + private string _unit; + + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimensionAdditional() + : base() + { + } + + /// + /// Gets or sets the unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). + /// + [JsonProperty("unit")] + public string Unit { get => this._unit; set => this._unit = value; } + + /// + /// Gets or sets the spatial reference system for the data, specified as numerical EPSG code, WKT2 (ISO 19162) string or PROJJSON object. Defaults to EPSG code 4326. + /// + [JsonProperty("reference_system")] + public object ReferenceSystem { get => this._reference_system; set => this._reference_system = value; } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionObject.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionObject.cs deleted file mode 100644 index 9c74794f..00000000 --- a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionObject.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Stac.Common; - -namespace Stac.Extensions.Datacube -{ - /// - /// Represents the Dimension Object - /// of the Datacube extension - /// - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] - public class DatacubeDimension : IStacPropertiesContainer - { - IDictionary properties; - protected string type; - protected string description; - protected double[] extent; - protected object values; - protected double? step; - - /// - /// Type of the dimension. - /// - [JsonProperty("type")] - public string Type { get => type; set => type = value; } - - /// - /// Detailed multi-line description to explain the dimension. CommonMark 0.29 syntax MAY be used for rich text representation. - /// - [JsonProperty("description")] - public string Description { get => description; set => description = value; } - - /// - /// Extent (lower and upper bounds) of the dimension as two-element array. Open intervals with null are not allowed. - /// - [JsonProperty("extent")] - public double[] Extent { get => extent; set => extent = value; } - - /// - /// Optionally, an ordered list of all values. - /// - [JsonProperty("values")] - public object Values { get => values; set => values = value; } - - /// - /// The space between the values. Use null for irregularly spaced steps. - /// - [JsonProperty("step")] - public double? Step { get => step; set => step = value; } - - /// - /// Additional fields - /// - /// - [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } - - [JsonIgnore] - public IStacObject StacObjectContainer => null; - - - public DatacubeDimension() - { - properties = new Dictionary(); - } - } - - public class DatacubeDimensionSpatial : DatacubeDimension - { - protected DatacubeAxis? axis; - protected object reference_system; - - /// - /// Axis of the spatial dimension. - /// - [JsonProperty("axis")] - public DatacubeAxis? Axis { get => axis; set => axis = value; } - - /// - /// The spatial reference system for the data, specified as numerical EPSG code, WKT2 (ISO 19162) string or PROJJSON object. Defaults to EPSG code 4326. - /// - [JsonProperty("reference_system")] - public object ReferenceSystem { get => reference_system; set => reference_system = value; } - - public DatacubeDimensionSpatial() : base() - { - } - } - - public class DatacubeDimensionSpatialHorizontal : DatacubeDimensionSpatial - { - public DatacubeDimensionSpatialHorizontal() : base() - { - base.axis = DatacubeAxis.x; - } - } - - public class DatacubeDimensionSpatialVertical : DatacubeDimensionSpatial - { - private string unit; - - /// - /// The unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). - /// - [JsonProperty("unit")] - public string Unit { get => unit; set => unit = value; } - - public DatacubeDimensionSpatialVertical() : base() - { - base.axis = DatacubeAxis.z; - } - } - - public class DatacubeDimensionTemporal : DatacubeDimension - { - - public DatacubeDimensionTemporal() : base() - { - - } - } - - public class DatacubeDimensionAdditional : DatacubeDimension - { - - private string unit; - protected object reference_system; - - /// - /// The unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). - /// - [JsonProperty("unit")] - public string Unit { get => unit; set => unit = value; } - - /// - /// The spatial reference system for the data, specified as numerical EPSG code, WKT2 (ISO 19162) string or PROJJSON object. Defaults to EPSG code 4326. - /// - [JsonProperty("reference_system")] - public object ReferenceSystem { get => reference_system; set => reference_system = value; } - - public DatacubeDimensionAdditional() : base() - { - - } - } -} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatial.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatial.cs new file mode 100644 index 00000000..d7547663 --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatial.cs @@ -0,0 +1,43 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionSpatial.cs + +using Newtonsoft.Json; + +namespace Stac.Extensions.Datacube +{ + /// + /// Datacube spatial dimension + /// + public class DatacubeDimensionSpatial : DatacubeDimension + { + private DatacubeAxis? _axis; + private object _reference_system; + + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimensionSpatial() + : base() + { + } + + /// + /// Gets or sets axis of the spatial dimension. + /// + /// + /// Axis of the spatial dimension. + /// + [JsonProperty("axis")] + public DatacubeAxis? Axis { get => this._axis; set => this._axis = value; } + + /// + /// Gets or sets the spatial reference system for the data, specified as numerical EPSG code, WKT2 (ISO 19162) string or PROJJSON object. Defaults to EPSG code 4326. + /// + /// + /// The spatial reference system for the data, specified as numerical EPSG code, WKT2 (ISO 19162) string or PROJJSON object. Defaults to EPSG code 4326. + /// + [JsonProperty("reference_system")] + public object ReferenceSystem { get => this._reference_system; set => this._reference_system = value; } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialHorizontal.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialHorizontal.cs new file mode 100644 index 00000000..8ee25ea4 --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialHorizontal.cs @@ -0,0 +1,21 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionSpatialHorizontal.cs + +namespace Stac.Extensions.Datacube +{ + /// + /// Datacube horizontal spatial dimension + /// + public class DatacubeDimensionSpatialHorizontal : DatacubeDimensionSpatial + { + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimensionSpatialHorizontal() + : base() + { + this.Axis = DatacubeAxis.x; + } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialVertical.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialVertical.cs new file mode 100644 index 00000000..d943d21c --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionSpatialVertical.cs @@ -0,0 +1,34 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionSpatialVertical.cs + +using Newtonsoft.Json; + +namespace Stac.Extensions.Datacube +{ + /// + /// Datacube vertical spatial dimension + /// + public class DatacubeDimensionSpatialVertical : DatacubeDimensionSpatial + { + private string _unit; + + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimensionSpatialVertical() + : base() + { + this.Axis = DatacubeAxis.z; + } + + /// + /// Gets or sets the unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). + /// + /// + /// The unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). + /// + [JsonProperty("unit")] + public string Unit { get => this._unit; set => this._unit = value; } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionTemporal.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionTemporal.cs new file mode 100644 index 00000000..769cb54e --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionTemporal.cs @@ -0,0 +1,20 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionTemporal.cs + +namespace Stac.Extensions.Datacube +{ + /// + /// Datacube temporal dimension + /// + public class DatacubeDimensionTemporal : DatacubeDimension + { + /// + /// Initializes a new instance of the class. + /// + public DatacubeDimensionTemporal() + : base() + { + } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionType.cs b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionType.cs index f017ad81..80fe57a4 100644 --- a/src/DotNetStac/Extensions/Datacube/DatacubeDimensionType.cs +++ b/src/DotNetStac/Extensions/Datacube/DatacubeDimensionType.cs @@ -1,13 +1,26 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeDimensionType.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Extensions.Datacube { + /// + /// Datacube dimension type + /// [JsonConverter(typeof(StringEnumConverter))] public enum DatacubeDimensionType { +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member spatial, - temporal + temporal, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeStacExtension.cs b/src/DotNetStac/Extensions/Datacube/DatacubeStacExtension.cs index f2eb589b..d5de6e16 100644 --- a/src/DotNetStac/Extensions/Datacube/DatacubeStacExtension.cs +++ b/src/DotNetStac/Extensions/Datacube/DatacubeStacExtension.cs @@ -1,7 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeStacExtension.cs + +using System; using System.Collections.Generic; using System.Collections.Specialized; -using System.Linq; using Stac.Model; namespace Stac.Extensions.Datacube @@ -11,120 +14,131 @@ namespace Stac.Extensions.Datacube /// public class DatacubeStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extensions identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/datacube/v2.1.0/schema.json"; - private static IDictionary itemFields; private const string DimensionField = "cube:dimensions"; private const string VariableField = "cube:variables"; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + private readonly IDictionary _itemFields; - private DatacubeStacExtension(IStacPropertiesContainer stacPropertiesContainer) : base(JsonSchemaUrl, stacPropertiesContainer) + /// + /// Initializes a new instance of the class. + /// + /// The stac collection. + internal DatacubeStacExtension(StacCollection stacCollection) + : this((IStacPropertiesContainer)stacCollection) { - itemFields = new Dictionary(); - itemFields.Add(DimensionField, typeof(IDictionary)); - itemFields.Add(VariableField, typeof(IDictionary)); } - internal DatacubeStacExtension(StacCollection stacCollection) : this((IStacPropertiesContainer)stacCollection) + /// + /// Initializes a new instance of the class. + /// + /// The stac asset. + internal DatacubeStacExtension(StacAsset stacAsset) + : this((IStacPropertiesContainer)stacAsset) { } - internal DatacubeStacExtension(StacAsset stacAsset) : this((IStacPropertiesContainer)stacAsset) + /// + /// Initializes a new instance of the class. + /// + /// The stac item. + internal DatacubeStacExtension(StacItem stacItem) + : this((IStacPropertiesContainer)stacItem) { } - internal DatacubeStacExtension(StacItem stacItem) : this((IStacPropertiesContainer)stacItem) + /// + /// Initializes a new instance of the class. + /// + /// The stac properties container. + private DatacubeStacExtension(IStacPropertiesContainer stacPropertiesContainer) + : base(JsonSchemaUrl, stacPropertiesContainer) { + this._itemFields = new Dictionary(); + this._itemFields.Add(DimensionField, typeof(IDictionary)); + this._itemFields.Add(VariableField, typeof(IDictionary)); } /// - /// A dictionary of available dimensions where each object is a DatacubeDimension Object. + /// Gets a dictionary of available dimensions where each object is a DatacubeDimension Object. /// + /// + /// A dictionary of available dimensions where each object is a DatacubeDimension Object. + /// public IDictionary Dimensions { get { - Dictionary existingDimensions = StacPropertiesContainer.GetProperty>(DimensionField); + Dictionary existingDimensions = this.StacPropertiesContainer.GetProperty>(DimensionField); ObservableDictionary dimensions = null; if (existingDimensions == null) + { dimensions = new ObservableDictionary(); + } else + { dimensions = new ObservableDictionary(existingDimensions); - dimensions.CollectionChanged += UpdateDimensionField; + } + + dimensions.CollectionChanged += this.UpdateDimensionField; return dimensions; } } - private void UpdateDimensionField(object sender, NotifyCollectionChangedEventArgs e) - { - StacPropertiesContainer.SetProperty(DimensionField, new Dictionary(sender as IDictionary)); - DeclareStacExtension(); - } - /// - /// A dictionary of available variables where each object is a DatacubeVariable Object. + /// Gets a dictionary of available variables where each object is a DatacubeVariable Object. /// + /// + /// A dictionary of available variables where each object is a DatacubeVariable Object. + /// public IDictionary Variables { get { - Dictionary existingVariables = StacPropertiesContainer.GetProperty>(VariableField); + Dictionary existingVariables = this.StacPropertiesContainer.GetProperty>(VariableField); ObservableDictionary variables = null; if (existingVariables == null) + { variables = new ObservableDictionary(); + } else + { variables = new ObservableDictionary(existingVariables); - variables.CollectionChanged += UpdateVariableField; + } + + variables.CollectionChanged += this.UpdateVariableField; return variables; } } - private void UpdateVariableField(object sender, NotifyCollectionChangedEventArgs e) - { - StacPropertiesContainer.SetProperty(VariableField, new Dictionary(sender as IDictionary)); - DeclareStacExtension(); - } - /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; + /// + /// Potential fields and their types + /// + public override IDictionary ItemFields => this._itemFields; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } - } - /// - /// Extension methods for accessing EO extension - /// - public static class DatacubeStacExtensionExtensions - { - - /// - /// Initilize a DatacubeStacExtension class from a STAC asset - /// - public static DatacubeStacExtension DatacubeStacExtension(this StacAsset stacAsset) - { - return new DatacubeStacExtension(stacAsset); - } - - /// - /// Initilize a DatacubeStacExtension class from a STAC item - /// - public static DatacubeStacExtension DatacubeStacExtension(this StacItem stacItem) + private void UpdateDimensionField(object sender, NotifyCollectionChangedEventArgs e) { - return new DatacubeStacExtension(stacItem); + this.StacPropertiesContainer.SetProperty(DimensionField, new Dictionary(sender as IDictionary)); + this.DeclareStacExtension(); } - /// - /// Initilize a DatacubeStacExtension class from a STAC collection - /// - public static DatacubeStacExtension DatacubeStacExtension(this StacCollection stacCollection) + private void UpdateVariableField(object sender, NotifyCollectionChangedEventArgs e) { - return new DatacubeStacExtension(stacCollection); + this.StacPropertiesContainer.SetProperty(VariableField, new Dictionary(sender as IDictionary)); + this.DeclareStacExtension(); } } } diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Datacube/DatacubeStacExtensionExtensions.cs new file mode 100644 index 00000000..f38b0a7b --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeStacExtensionExtensions.cs @@ -0,0 +1,42 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeStacExtensionExtensions.cs + +namespace Stac.Extensions.Datacube +{ + /// + /// Extension methods for accessing EO extension + /// + public static class DatacubeStacExtensionExtensions + { + /// + /// Initilize a DatacubeStacExtension class from a STAC asset + /// + /// The STAC asset. + /// The DatacubeStacExtension class + public static DatacubeStacExtension DatacubeStacExtension(this StacAsset stacAsset) + { + return new DatacubeStacExtension(stacAsset); + } + + /// + /// Initilize a DatacubeStacExtension class from a STAC item + /// + /// The STAC item. + /// The DatacubeStacExtension class + public static DatacubeStacExtension DatacubeStacExtension(this StacItem stacItem) + { + return new DatacubeStacExtension(stacItem); + } + + /// + /// Initilize a DatacubeStacExtension class from a STAC collection + /// + /// The STAC collection. + /// The DatacubeStacExtension class + public static DatacubeStacExtension DatacubeStacExtension(this StacCollection stacCollection) + { + return new DatacubeStacExtension(stacCollection); + } + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeVariable.cs b/src/DotNetStac/Extensions/Datacube/DatacubeVariable.cs new file mode 100644 index 00000000..565cb2a6 --- /dev/null +++ b/src/DotNetStac/Extensions/Datacube/DatacubeVariable.cs @@ -0,0 +1,79 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeVariable.cs + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Stac.Extensions.Datacube +{ + /// + /// Represents the Variable Object + /// of the Datacube extension + /// + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public class DatacubeVariable : IStacPropertiesContainer + { + private string[] _dimensions; + private DatacubeVariableType? _type; + private string _description; + private double[] _extent; + private string[] _values; + private IDictionary _properties; + private string _unit; + + /// + /// Initializes a new instance of the class. + /// + public DatacubeVariable() + { + this._properties = new Dictionary(); + } + + /// + /// Gets or sets the dimensions of the variable. This should refer to keys in the cube:dimensions object or be an empty list if the variable has no dimensions. + /// + [JsonProperty("dimensions")] + public string[] Dimensions { get => this._dimensions; set => this._dimensions = value; } + + /// + /// Gets or sets type of the variable. + /// + [JsonProperty("type")] + public DatacubeVariableType? Type { get => this._type; set => this._type = value; } + + /// + /// Gets or sets detailed multi-line description to explain the variable. CommonMark 0.29 syntax MAY be used for rich text representation. + /// + [JsonProperty("description")] + public string Description { get => this._description; set => this._description = value; } + + /// + /// Gets or sets if the variable consists of ordinal values, the extent (lower and upper bounds) of the values as two-element array. Use null for open intervals. + /// + [JsonProperty("extent")] + public double[] Extent { get => this._extent; set => this._extent = value; } + + /// + /// Gets or sets an (ordered) list of all values, especially useful for nominal values. + /// + [JsonProperty("values")] + public string[] Values { get => this._values; set => this._values = value; } + + /// + /// Gets or sets the unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). + /// + [JsonProperty("unit")] + public string Unit { get => this._unit; set => this._unit = value; } + + /// + /// Gets or sets additional fields + /// + [JsonExtensionData] + public IDictionary Properties { get => this._properties; set => this._properties = value; } + + /// + [JsonIgnore] + public IStacObject StacObjectContainer => null; + } +} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeVariableObject.cs b/src/DotNetStac/Extensions/Datacube/DatacubeVariableObject.cs deleted file mode 100644 index 7ffa573f..00000000 --- a/src/DotNetStac/Extensions/Datacube/DatacubeVariableObject.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Stac.Common; - -namespace Stac.Extensions.Datacube -{ - /// - /// Represents the Variable Object - /// of the Datacube extension - /// - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] - public class DatacubeVariable : IStacPropertiesContainer - { - IDictionary properties; - protected string[] dimensions; - protected DatacubeVariableType? type; - protected string description; - protected double[] extent; - protected string[] values; - private string unit; - - /// - /// The dimensions of the variable. This should refer to keys in the cube:dimensions object or be an empty list if the variable has no dimensions. - /// - [JsonProperty("dimensions")] - public string[] Dimensions { get => dimensions; set => dimensions = value; } - - /// - /// Type of the variable. - /// - [JsonProperty("type")] - public DatacubeVariableType? Type { get => type; set => type = value; } - - /// - /// Detailed multi-line description to explain the variable. CommonMark 0.29 syntax MAY be used for rich text representation. - /// - [JsonProperty("description")] - public string Description { get => description; set => description = value; } - - /// - /// If the variable consists of ordinal values, the extent (lower and upper bounds) of the values as two-element array. Use null for open intervals. - /// - [JsonProperty("extent")] - public double[] Extent { get => extent; set => extent = value; } - - /// - /// An (ordered) list of all values, especially useful for nominal values. - /// - [JsonProperty("values")] - public string[] Values { get => values; set => values = value; } - - /// - /// The unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular). - /// - [JsonProperty("unit")] - public string Unit { get => unit; set => unit = value; } - - /// - /// Additional fields - /// - /// - [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } - - [JsonIgnore] - public IStacObject StacObjectContainer => null; - - - public DatacubeVariable() - { - properties = new Dictionary(); - } - } -} diff --git a/src/DotNetStac/Extensions/Datacube/DatacubeVariableType.cs b/src/DotNetStac/Extensions/Datacube/DatacubeVariableType.cs index f10f67aa..662e4113 100644 --- a/src/DotNetStac/Extensions/Datacube/DatacubeVariableType.cs +++ b/src/DotNetStac/Extensions/Datacube/DatacubeVariableType.cs @@ -1,13 +1,30 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: DatacubeVariableType.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Extensions.Datacube { + /// + /// Datacube variable type + /// [JsonConverter(typeof(StringEnumConverter))] public enum DatacubeVariableType { - data, //a variable indicating some measured value, for example "precipitation", "temperature", etc. +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented + /// + /// a variable indicating some measured value, for example "precipitation", "temperature", etc. + /// + data, - auxiliary //a variable that contains coordinate data, but isn't a dimension in cube:dimensions. For example, the values of the datacube might be provided in the projected coordinate reference system, but the datacube could have a variable lon with dimensions (y, x), giving the longitude at each point. + /// + /// a variable that contains coordinate data, but isn't a dimension in cube:dimensions. For example, the values of the datacube might be provided in the projected coordinate reference system, but the datacube could have a variable lon with dimensions (y, x), giving the longitude at each point. + /// + auxiliary, +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Eo/EoBandCommonName.cs b/src/DotNetStac/Extensions/Eo/EoBandCommonName.cs index d03180ac..6c350138 100644 --- a/src/DotNetStac/Extensions/Eo/EoBandCommonName.cs +++ b/src/DotNetStac/Extensions/Eo/EoBandCommonName.cs @@ -1,5 +1,8 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: EoBandCommonName.cs + +using Newtonsoft.Json; using Stac.Common; namespace Stac.Extensions.Eo @@ -10,6 +13,9 @@ namespace Stac.Extensions.Eo [JsonConverter(typeof(TolerantEnumConverter))] public enum EoBandCommonName { +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member coastal, blue, green, @@ -25,6 +31,9 @@ public enum EoBandCommonName swir22, lwir, lwir11, - lwir12 + lwir12, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Eo/EoBandObject.cs b/src/DotNetStac/Extensions/Eo/EoBandObject.cs index 926151f6..685b4782 100644 --- a/src/DotNetStac/Extensions/Eo/EoBandObject.cs +++ b/src/DotNetStac/Extensions/Eo/EoBandObject.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: EoBandObject.cs + +using System.Collections.Generic; using Newtonsoft.Json; namespace Stac.Extensions.Eo @@ -10,72 +14,86 @@ namespace Stac.Extensions.Eo [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class EoBandObject { - private string name; - - private string description; + private string _name; - private EoBandCommonName? commonName; + private string _description; - IDictionary properties; + private EoBandCommonName? _commonName; + private IDictionary _properties; /// - /// Initialize a new Band Object + /// Initializes a new instance of the class. /// /// Name of the band /// Common name of the band public EoBandObject(string name, EoBandCommonName? commonName) { - this.name = name; - this.commonName = commonName; - properties = new Dictionary(); + this._name = name; + this._commonName = commonName; + this._properties = new Dictionary(); } /// - /// The name of the band (e.g., "B01", "B8", "band2", "red"). + /// Gets or sets the name of the band (e.g., "B01", "B8", "band2", "red"). /// + /// + /// The name of the band (e.g., "B01", "B8", "band2", "red"). + /// [JsonProperty("name")] - public string Name { get => name; set => name = value; } + public string Name { get => this._name; set => this._name = value; } /// - /// Description to fully explain the band. CommonMark 0.29 syntax MAY be used for rich text representation. + /// Gets or sets description to fully explain the band. CommonMark 0.29 syntax MAY be used for rich text representation. /// + /// + /// Description to fully explain the band. CommonMark 0.29 syntax MAY be used for rich text representation. + /// [JsonProperty("description")] - public string Description { get => description; set => description = value; } + public string Description { get => this._description; set => this._description = value; } /// - /// The name commonly used to refer to the band to make it easier to search for bands across instruments. + /// Gets or sets the name commonly used to refer to the band to make it easier to search for bands across instruments. /// - /// + /// + /// The name commonly used to refer to the band to make it easier to search for bands across instruments. + /// [JsonProperty("common_name")] - public EoBandCommonName? CommonName { get => commonName; set => commonName = value; } + public EoBandCommonName? CommonName { get => this._commonName; set => this._commonName = value; } /// - /// The center wavelength of the band, in micrometers (μm). + /// Gets or sets the center wavelength of the band, in micrometers (μm). /// - /// + /// + /// The center wavelength of the band, in micrometers (μm). + /// [JsonProperty("center_wavelength")] public double? CenterWavelength { get; set; } /// - /// Full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). + /// Gets or sets full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). /// - /// + /// + /// Full width at half maximum (FWHM). The width of the band, as measured at half the maximum transmission, in micrometers (μm). + /// [JsonProperty("full_width_half_max")] public double? FullWidthHalfMax { get; set; } /// - /// The solar illumination of the band, as measured at half the maximum transmission, in W/m2/micrometers. + /// Gets or sets the solar illumination of the band, as measured at half the maximum transmission, in W/m2/micrometers. /// - /// + /// + /// The solar illumination of the band, as measured at half the maximum transmission, in W/m2/micrometers. + /// [JsonProperty("solar_illumination")] public double? SolarIllumination { get; set; } /// - /// Additional fields + /// Gets or sets additional fields /// - /// + /// + /// Additional fields + /// [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } - + public IDictionary Properties { get => this._properties; set => this._properties = value; } } } diff --git a/src/DotNetStac/Extensions/Eo/EoStacExtension.cs b/src/DotNetStac/Extensions/Eo/EoStacExtension.cs index 438dde66..dcdc702b 100644 --- a/src/DotNetStac/Extensions/Eo/EoStacExtension.cs +++ b/src/DotNetStac/Extensions/Eo/EoStacExtension.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: EoStacExtension.cs + +using System; using System.Collections.Generic; using System.Linq; @@ -9,110 +13,82 @@ namespace Stac.Extensions.Eo /// public class EoStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/eo/v1.0.0/schema.json"; private const string BandsField = "eo:bands"; private const string CloudCoverField = "eo:cloud_cover"; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member - private static IDictionary itemFields; + private readonly IDictionary _itemFields; - internal EoStacExtension(IStacPropertiesContainer stacpropertiesContainer) : base(JsonSchemaUrl, stacpropertiesContainer) + internal EoStacExtension(IStacPropertiesContainer stacpropertiesContainer) + : base(JsonSchemaUrl, stacpropertiesContainer) { - itemFields = new Dictionary(); - itemFields.Add(BandsField, typeof(EoBandObject[])); - itemFields.Add(CloudCoverField, typeof(double)); + this._itemFields = new Dictionary(); + this._itemFields.Add(BandsField, typeof(EoBandObject[])); + this._itemFields.Add(CloudCoverField, typeof(double)); } /// - /// Estimate of cloud cover + /// Gets or sets estimate of cloud cover /// public double? CloudCover { - get { return StacPropertiesContainer.GetProperty(CloudCoverField); } + get + { + return this.StacPropertiesContainer.GetProperty(CloudCoverField); + } + set { if (value == null) - StacPropertiesContainer.RemoveProperty(CloudCoverField); + { + this.StacPropertiesContainer.RemoveProperty(CloudCoverField); + } else { - StacPropertiesContainer.SetProperty(CloudCoverField, value); DeclareStacExtension(); + this.StacPropertiesContainer.SetProperty(CloudCoverField, value); + this.DeclareStacExtension(); } } } /// - /// An array of available bands where each object is a Band Object. + /// Gets or sets an array of available bands where each object is a Band Object. /// public EoBandObject[] Bands { - get { return StacPropertiesContainer.GetProperty(BandsField); } + get + { + return this.StacPropertiesContainer.GetProperty(BandsField); + } + set { if (value == null || value.Count() == 0) - StacPropertiesContainer.RemoveProperty(BandsField); + { + this.StacPropertiesContainer.RemoveProperty(BandsField); + } else { - StacPropertiesContainer.SetProperty(BandsField, value); - DeclareStacExtension(); + this.StacPropertiesContainer.SetProperty(BandsField, value); + this.DeclareStacExtension(); } } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; + public override IDictionary ItemFields => this._itemFields; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); - summaryFunctions.Add(CloudCoverField, new SummaryFunction(this, CloudCoverField, CreateRangeSummaryObject)); + summaryFunctions.Add(CloudCoverField, new SummaryFunction(this, CloudCoverField, CreateRangeSummaryObject)); return summaryFunctions; } } - - /// - /// Extension methods for accessing EO extension - /// - public static class EoStacExtensionExtensions - { - /// - /// Initilize a EoStacExtension class from a STAC item - /// - public static EoStacExtension EoExtension(this StacItem stacItem) - { - return new EoStacExtension(stacItem); - } - - /// - /// Initilize a EoStacExtension class from a STAC asset - /// - public static EoStacExtension EoExtension(this StacAsset stacAsset) - { - return new EoStacExtension(stacAsset); - } - - /// - /// Get a STAC asset from a STAC item by its common name - /// - /// Stac Item - /// common name - /// - public static StacAsset GetAsset(this StacItem stacItem, EoBandCommonName commonName) - { - return stacItem.Assets.Values.Where(a => a.EoExtension().Bands != null).FirstOrDefault(a => a.EoExtension().Bands.Any(b => b.CommonName == commonName)); - } - - /// - /// Get a STAC EO Band object from a STAC item by its common name - /// - /// Stac Item - /// common name - /// - public static EoBandObject GetBandObject(this StacItem stacItem, EoBandCommonName commonName) - { - return stacItem.Assets.Values.Where(a => a.EoExtension().Bands != null).Select(a => a.EoExtension().Bands.FirstOrDefault(b => b.CommonName == commonName)).First(); - } - } } diff --git a/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs new file mode 100644 index 00000000..32ab8035 --- /dev/null +++ b/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs @@ -0,0 +1,56 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: EoStacExtensionExtensions.cs + +using System.Linq; + +namespace Stac.Extensions.Eo +{ + /// + /// Extension methods for accessing EO extension + /// + public static class EoStacExtensionExtensions + { + /// + /// Initilize a EoStacExtension class from a STAC item + /// + /// Stac Item + /// EoStacExtension class + public static EoStacExtension EoExtension(this StacItem stacItem) + { + return new EoStacExtension(stacItem); + } + + /// + /// Initilize a EoStacExtension class from a STAC asset + /// + /// Stac Asset + /// EoStacExtension class + public static EoStacExtension EoExtension(this StacAsset stacAsset) + { + return new EoStacExtension(stacAsset); + } + + /// + /// Get a STAC asset from a STAC item by its common name + /// + /// Stac Item + /// common name + /// Stac Asset + public static StacAsset GetAsset(this StacItem stacItem, EoBandCommonName commonName) + { + return stacItem.Assets.Values.Where(a => a.EoExtension().Bands != null).FirstOrDefault(a => a.EoExtension().Bands.Any(b => b.CommonName == commonName)); + } + + /// + /// Get a STAC EO Band object from a STAC item by its common name + /// + /// Stac Item + /// common name + /// Stac EO Band object + public static EoBandObject GetBandObject(this StacItem stacItem, EoBandCommonName commonName) + { + return stacItem.Assets.Values.Where(a => a.EoExtension().Bands != null).Select(a => a.EoExtension().Bands.FirstOrDefault(b => b.CommonName == commonName)).First(); + } + } +} diff --git a/src/DotNetStac/Extensions/File/ByteOrder.cs b/src/DotNetStac/Extensions/File/ByteOrder.cs index e9c29742..35583008 100644 --- a/src/DotNetStac/Extensions/File/ByteOrder.cs +++ b/src/DotNetStac/Extensions/File/ByteOrder.cs @@ -1,4 +1,8 @@ -using System.Runtime.Serialization; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ByteOrder.cs + +using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -10,13 +14,16 @@ namespace Stac.Extensions.File [JsonConverter(typeof(StringEnumConverter))] public enum ByteOrder { - /// Big Endian +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented + // Big Endian [EnumMember(Value = "big-endian")] BigEndian, - /// Little Endian + // Little Endian [EnumMember(Value = "little-endian")] - LittleEndian - + LittleEndian, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented } } diff --git a/src/DotNetStac/Extensions/File/FileStacExtension.cs b/src/DotNetStac/Extensions/File/FileStacExtension.cs index 621a5b18..eeecf34c 100644 --- a/src/DotNetStac/Extensions/File/FileStacExtension.cs +++ b/src/DotNetStac/Extensions/File/FileStacExtension.cs @@ -1,13 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: FileStacExtension.cs + +using System; using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Security.Cryptography; -using System.Threading.Tasks; -using Multiformats.Base; using Multiformats.Hash; -using Multiformats.Hash.Algorithms; -using Stac.Model; namespace Stac.Extensions.File { @@ -16,145 +13,108 @@ namespace Stac.Extensions.File /// public class FileStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/file/v1.0.0/schema.json"; private const string ByteOrderField = "file:byte_order"; private const string ChecksumField = "file:checksum"; private const string HeaderSizeField = "file:header_size"; private const string SizeField = "file:size"; - private readonly Dictionary itemFields; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + private readonly Dictionary _itemFields; - internal FileStacExtension(StacAsset stacAsset) : base(JsonSchemaUrl, stacAsset) + internal FileStacExtension(StacAsset stacAsset) + : base(JsonSchemaUrl, stacAsset) { - itemFields = new Dictionary(); - itemFields.Add(ByteOrderField, typeof(string)); - itemFields.Add(ChecksumField, typeof(string)); - itemFields.Add(HeaderSizeField, typeof(string)); - itemFields.Add(SizeField, typeof(IDictionary)); + this._itemFields = new Dictionary(); + this._itemFields.Add(ByteOrderField, typeof(string)); + this._itemFields.Add(ChecksumField, typeof(string)); + this._itemFields.Add(HeaderSizeField, typeof(string)); + this._itemFields.Add(SizeField, typeof(IDictionary)); } /// - /// The byte order of integer values in the file. One of big-endian or little-endian. + /// Gets or sets the byte order of integer values in the file. One of big-endian or little-endian. /// - /// public ByteOrder ByteOrder { - get { return StacPropertiesContainer.GetProperty(ByteOrderField); } - set { StacPropertiesContainer.SetProperty(ByteOrderField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ByteOrderField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ByteOrderField, value); + this.DeclareStacExtension(); + } } /// - /// The name commonly used to refer to the processing level to make it easier to search for product level across collections or items. + /// Gets or sets the name commonly used to refer to the processing level to make it easier to search for product level across collections or items. /// - /// - public Multiformats.Hash.Multihash Checksum + public Multihash Checksum { - get { return Multiformats.Hash.Multihash.Parse(StacPropertiesContainer.GetProperty(ChecksumField)); } - set { StacPropertiesContainer.SetProperty(ChecksumField, value.ToString()); DeclareStacExtension(); } + get + { + return Multihash.Parse(this.StacPropertiesContainer.GetProperty(ChecksumField)); + } + + set + { + this.StacPropertiesContainer.SetProperty(ChecksumField, value.ToString()); + this.DeclareStacExtension(); + } } /// - /// The name of the facility that produced the data. + /// Gets or sets the name of the facility that produced the data. /// - /// public uint? HeaderSize { - get { return StacPropertiesContainer.GetProperty(HeaderSizeField); } - set { StacPropertiesContainer.SetProperty(HeaderSizeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(HeaderSizeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(HeaderSizeField, value); + this.DeclareStacExtension(); + } } /// - /// The name of the facility that produced the data. + /// Gets or sets the name of the facility that produced the data. /// - /// public ulong? Size { - get { return StacPropertiesContainer.GetProperty(SizeField); } - set { StacPropertiesContainer.SetProperty(SizeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(SizeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(SizeField, value); + this.DeclareStacExtension(); + } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; + public override IDictionary ItemFields => this._itemFields; /// - /// Get the STAC asset + /// Gets get the STAC asset /// - public StacAsset StacAsset => base.StacPropertiesContainer as StacAsset; + public StacAsset StacAsset => this.StacPropertiesContainer as StacAsset; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } - - } - - /// - /// Extension methods for accessing Processing extension - /// - public static class FileStacExtensionExtensions - { - /// - /// Initilize a EoStacExtension class from a STAC item - /// - public static FileStacExtension FileExtension(this StacAsset stacAsset) - { - return new FileStacExtension(stacAsset); - } - - /// - /// Set possibly file extension properties from a FileInfo object: - /// - size - /// - checksum - /// - /// - public static async Task SetFileExtensionProperties(this FileStacExtension fileStacExtension, - FileInfo file, - HashType hashType = HashType.SHA1, - MultibaseEncoding encoding = MultibaseEncoding.Base16Lower) - { - fileStacExtension.Size = Convert.ToUInt64(file.Length); - await fileStacExtension.SetFileCheckSum(hashType, encoding, uri => file.OpenRead()); - } - - /// - /// Set possibly file extension properties from a FileInfo object: - /// - size - /// - checksum - /// - /// - public static async Task SetFileExtensionProperties(this FileStacExtension fileStacExtension, - Stream stream, - HashType hashType = HashType.SHA1, - MultibaseEncoding encoding = MultibaseEncoding.Base16Lower) - { - await fileStacExtension.SetFileCheckSum(hashType, encoding, uri => stream); - } - - /// - /// Add the checksum property of the file extension - /// - /// - public static async Task SetFileCheckSum(this FileStacExtension fileStacExtension, - HashType hashType, - MultibaseEncoding encoding, - Func uriStreamer) - { - Multihash mh = null; - using (var stream = uriStreamer(fileStacExtension.StacAsset.Uri)) - { - byte[] data = null; - using (var mem = new MemoryStream()) - { - await stream.CopyToAsync(mem); - data = mem.ToArray(); - fileStacExtension.Size = Convert.ToUInt64(mem.Length); - } - mh = Multihash.Sum(hashType, data); - } - fileStacExtension.Checksum = mh; - } } } diff --git a/src/DotNetStac/Extensions/File/FileStacExtensionExtensions.cs b/src/DotNetStac/Extensions/File/FileStacExtensionExtensions.cs new file mode 100644 index 00000000..0940bec7 --- /dev/null +++ b/src/DotNetStac/Extensions/File/FileStacExtensionExtensions.cs @@ -0,0 +1,98 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: FileStacExtensionExtensions.cs + +using System; +using System.IO; +using System.Threading.Tasks; +using Multiformats.Base; +using Multiformats.Hash; + +namespace Stac.Extensions.File +{ + /// + /// Extension methods for accessing Processing extension + /// + public static class FileStacExtensionExtensions + { + /// + /// Initilize a EoStacExtension class from a STAC item + /// + /// The STAC asset. + /// The EoStacExtension class + public static FileStacExtension FileExtension(this StacAsset stacAsset) + { + return new FileStacExtension(stacAsset); + } + + /// + /// Set possibly file extension properties from a FileInfo object: + /// - size + /// - checksum + /// + /// The file extension. + /// The file. + /// Type of the hash. + /// The encoding. + /// No object or value is returned by this method when it completes. + public static async Task SetFileExtensionProperties( + this FileStacExtension fileStacExtension, + FileInfo file, + HashType hashType = HashType.SHA1, + MultibaseEncoding encoding = MultibaseEncoding.Base16Lower) + { + fileStacExtension.Size = Convert.ToUInt64(file.Length); + await fileStacExtension.SetFileCheckSum(hashType, encoding, uri => file.OpenRead()); + } + + /// + /// Set possibly file extension properties from a FileInfo object: + /// - size + /// - checksum + /// + /// The file extension. + /// The stream. + /// Type of the hash. + /// The encoding. + /// No object or value is returned by this method when it completes. + public static async Task SetFileExtensionProperties( + this FileStacExtension fileStacExtension, + Stream stream, + HashType hashType = HashType.SHA1, + MultibaseEncoding encoding = MultibaseEncoding.Base16Lower) + { + await fileStacExtension.SetFileCheckSum(hashType, encoding, uri => stream); + } + + /// + /// Add the checksum property of the file extension + /// + /// The file extension. + /// Type of the hash. + /// The encoding. + /// The URI streamer. + /// No object or value is returned by this method when it completes. + public static async Task SetFileCheckSum( + this FileStacExtension fileStacExtension, + HashType hashType, + MultibaseEncoding encoding, + Func uriStreamer) + { + Multihash mh = null; + using (var stream = uriStreamer(fileStacExtension.StacAsset.Uri)) + { + byte[] data = null; + using (var mem = new MemoryStream()) + { + await stream.CopyToAsync(mem); + data = mem.ToArray(); + fileStacExtension.Size = Convert.ToUInt64(mem.Length); + } + + mh = Multihash.Sum(hashType, data); + } + + fileStacExtension.Checksum = mh; + } + } +} diff --git a/src/DotNetStac/Extensions/IStacAssetExtension.cs b/src/DotNetStac/Extensions/IStacAssetExtension.cs index 492f7400..0d07e15a 100644 --- a/src/DotNetStac/Extensions/IStacAssetExtension.cs +++ b/src/DotNetStac/Extensions/IStacAssetExtension.cs @@ -1,11 +1,17 @@ -using System; -using System.Collections.Generic; -using Stac.Collection; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacAssetExtension.cs namespace Stac.Extensions { + /// + /// Interface for StacAsset extensions + /// public interface IStacAssetExtension { + /// + /// Gets the StacAsset. + /// StacAsset StacAsset { get; } } } diff --git a/src/DotNetStac/Extensions/IStacExtension.cs b/src/DotNetStac/Extensions/IStacExtension.cs index ab2c0fbd..de6044a4 100644 --- a/src/DotNetStac/Extensions/IStacExtension.cs +++ b/src/DotNetStac/Extensions/IStacExtension.cs @@ -1,15 +1,25 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacExtension.cs + using System.Collections.Generic; -using Stac.Collection; namespace Stac.Extensions { + /// + /// Interface for Stac extensions + /// public interface IStacExtension { + /// + /// Gets the Stac Extension identifier. + /// string Identifier { get; } - bool IsDeclared { get; } - + /// + /// Gets the Stac Extension summary functions. + /// + /// The Stac Extension summary functions. IDictionary GetSummaryFunctions(); } } diff --git a/src/DotNetStac/Extensions/ISummaryFunction.cs b/src/DotNetStac/Extensions/ISummaryFunction.cs index 56619d50..7e0f06b8 100644 --- a/src/DotNetStac/Extensions/ISummaryFunction.cs +++ b/src/DotNetStac/Extensions/ISummaryFunction.cs @@ -1,14 +1,32 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ISummaryFunction.cs + +using System.Collections.Generic; using Stac.Collection; namespace Stac.Extensions { + /// + /// Interface for Stac Extension summary functions + /// public interface ISummaryFunction { + /// + /// Gets the Stac Extension associated to the summary function. + /// IStacExtension Extension { get; } + /// + /// Gets the PropertyName of the summary function. + /// string PropertyName { get; } + /// + /// Summarize the items. + /// + /// The items to summarize. + /// The summary item. IStacSummaryItem Summarize(IEnumerable items); } } diff --git a/src/DotNetStac/Extensions/ItemCollection/ItemCollection.cs b/src/DotNetStac/Extensions/ItemCollection/ItemCollection.cs deleted file mode 100644 index f7df30d0..00000000 --- a/src/DotNetStac/Extensions/ItemCollection/ItemCollection.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using Newtonsoft.Json; -using Newtonsoft.Json.Schema; -using Stac.Collection; -using Stac.Model; - -namespace Stac.Extensions.ItemCollections -{ - public class ItemCollection : StacCollection, IStacExtension - { - - public const string JsonSchemaUrl = "https://stac-extensions.github.io/processing/v1.0.0/schema.json"; - - public ItemCollection(string id, - string description, - List stacItems) : base(id, - description, - null) - { - if (stacItems != null) - { - Features = new List(stacItems); - Extent = StacExtent.Create(stacItems); - } - } - - /// - /// STAC type (FeatureCollection) - /// - [JsonProperty("type")] - public override string Type => "FeatureCollection"; - - [JsonProperty(PropertyName = "features", Required = Required.Always)] - public List Features { get; set; } - - public string Identifier => JsonSchemaUrl; - - public bool IsDeclared => true; - - public IDictionary GetSummaryFunctions() - { - return new Dictionary(); - } - - internal static JSchema GenerateJSchema(string version) - { - - JSchema jSchema = new JSchema(); - jSchema.SchemaVersion = new Uri("http://json-schema.org/draft-07/schema#"); - jSchema.Title = "STAC ItemCollection Extension"; - jSchema.Type = JSchemaType.Object; - jSchema.Description = "This object represents the metadata for a set of items in a SpatioTemporal Asset Catalog."; - jSchema.AllowAdditionalProperties = true; - - JSchema featureCollectionRef = new JSchema(); - - featureCollectionRef.Ref = GetSchema(new Uri("https://geojson.org/schema/FeatureCollection.json")); - JSchema fcr = new JSchema(); - fcr.OneOf.Add(featureCollectionRef); - - jSchema.AllOf.Add(fcr); - - JSchema itemSchema = GetSchema(new Uri("https://schemas.stacspec.org/v" + version + "/item-spec/json-schema/item.json")); - JSchema linkSchema = JSchema.Parse(itemSchema.ExtensionData["definitions"]["link"].ToString()); - - jSchema.AllOf.Add(new JSchema() - { - Properties = { - { "stac_version", new JSchema(){ - Title = "STAC version", - Type = JSchemaType.String - }}, - { "stac_extensions", new JSchema(){ - Title = "STAC extensions", - Type = JSchemaType.Array, - UniqueItems = true, - Items = { new JSchema { Type = JSchemaType.String, Format = "uri", Title = "Reference to a JSON Schema" } } - }}, - { "features", new JSchema(){ - Title = "ItemCollection features", - Type = JSchemaType.Array, - Items = { new JSchema { Ref = itemSchema } } - }}, - { "links", new JSchema(){ - Title = "Links", - Type = JSchemaType.Array, - Items = { new JSchema { Ref = linkSchema } } - }}, - } - }); - - return jSchema; - } - - private static JSchema GetSchema(Uri schemaUri) - { - JSchemaUrlResolver jSchemaResolver = new JSchemaUrlResolver(); - Stream stream = null; - try - { - stream = jSchemaResolver.GetSchemaResource(null, new SchemaReference() { BaseUri = schemaUri }); - } - catch (Exception e) - { - throw new Stac.Exceptions.InvalidStacSchemaException(string.Format("Error getting schema at Uri '{0}'", schemaUri), e); - } - var sr = new StreamReader(stream); - return JSchema.Parse(sr.ReadToEnd(), jSchemaResolver); - } - } -} diff --git a/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs b/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs index 70420602..e47e0ee0 100644 --- a/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs +++ b/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProcessingStacExtension.cs + +using System; using System.Collections.Generic; using System.Collections.Specialized; using Stac.Model; @@ -10,110 +14,108 @@ namespace Stac.Extensions.Processing /// public class ProcessingStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/processing/v1.0.0/schema.json"; - private const string LineageField = "processing:lineage"; - private const string LevelField = "processing:level"; - private const string FacilityField = "processing:facility"; - private const string SoftwareField = "processing:software"; - private readonly Dictionary itemFields; + public const string LineageField = "processing:lineage"; + public const string LevelField = "processing:level"; + public const string FacilityField = "processing:facility"; + public const string SoftwareField = "processing:software"; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + private readonly Dictionary _itemFields; - internal ProcessingStacExtension(StacItem stacItem) : base(JsonSchemaUrl, stacItem) + internal ProcessingStacExtension(StacItem stacItem) + : base(JsonSchemaUrl, stacItem) { - itemFields = new Dictionary(); - itemFields.Add(LineageField, typeof(string)); - itemFields.Add(LevelField, typeof(string)); - itemFields.Add(FacilityField, typeof(string)); - itemFields.Add(SoftwareField, typeof(IDictionary)); + this._itemFields = new Dictionary(); + this._itemFields.Add(LineageField, typeof(string)); + this._itemFields.Add(LevelField, typeof(string)); + this._itemFields.Add(FacilityField, typeof(string)); + this._itemFields.Add(SoftwareField, typeof(IDictionary)); } /// - /// Lineage Information provided as free text information about the how observations were processed or models that were used to create the resource being described NASA ISO. + /// Gets or sets lineage Information provided as free text information about the how observations were processed or models that were used to create the resource being described NASA ISO. /// - /// public string Lineage { - get { return StacPropertiesContainer.GetProperty(LineageField); } - set { StacPropertiesContainer.SetProperty(LineageField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(LineageField); + } + + set + { + this.StacPropertiesContainer.SetProperty(LineageField, value); + this.DeclareStacExtension(); + } } /// - /// The name commonly used to refer to the processing level to make it easier to search for product level across collections or items. + /// Gets or sets the name commonly used to refer to the processing level to make it easier to search for product level across collections or items. /// - /// public string Level { - get { return StacPropertiesContainer.GetProperty(LevelField); } - set { StacPropertiesContainer.SetProperty(LevelField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(LevelField); + } + + set + { + this.StacPropertiesContainer.SetProperty(LevelField, value); + this.DeclareStacExtension(); + } } /// - /// The name of the facility that produced the data. + /// Gets or sets the name of the facility that produced the data. /// - /// public string Facility { - get { return StacPropertiesContainer.GetProperty(FacilityField); } - set { StacPropertiesContainer.SetProperty(FacilityField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(FacilityField); + } + + set + { + this.StacPropertiesContainer.SetProperty(FacilityField, value); + this.DeclareStacExtension(); + } } /// - /// A dictionary with name/version for key/value describing one or more softwares that produced the data. + /// Gets a dictionary with name/version for key/value describing one or more softwares that produced the data. /// - /// public IDictionary Software { get { - Dictionary existingSoftware = StacPropertiesContainer.GetProperty>(SoftwareField); + Dictionary existingSoftware = this.StacPropertiesContainer.GetProperty>(SoftwareField); ObservableDictionary software = null; if (existingSoftware == null) + { software = new ObservableDictionary(); + } else + { software = new ObservableDictionary(existingSoftware); - software.CollectionChanged += UpdateSoftwareField; + } + + software.CollectionChanged += this.UpdateSoftwareField; return software; } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; - + public override IDictionary ItemFields => this._itemFields; private void UpdateSoftwareField(object sender, NotifyCollectionChangedEventArgs e) { - StacPropertiesContainer.SetProperty(SoftwareField, new Dictionary(sender as IDictionary)); - DeclareStacExtension(); - } - - } - - /// - /// Extension methods for accessing Processing extension - /// - public static class ProcessingStacExtensionExtensions - { - /// - /// Initilize a EoStacExtension class from a STAC item - /// - public static ProcessingStacExtension ProcessingExtension(this StacItem stacItem) - { - return new ProcessingStacExtension(stacItem); - } - - /// - /// Initialize the major fields of processing extensions - /// - public static void Init(this ProcessingStacExtension processingStacExtension, - string lineage, - string level, - string facility = null) - { - processingStacExtension.Lineage = lineage; - processingStacExtension.Level = level; - processingStacExtension.Facility = facility; + this.StacPropertiesContainer.SetProperty(SoftwareField, new Dictionary(sender as IDictionary)); + this.DeclareStacExtension(); } } } diff --git a/src/DotNetStac/Extensions/Processing/ProcessingStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Processing/ProcessingStacExtensionExtensions.cs new file mode 100644 index 00000000..377c0bac --- /dev/null +++ b/src/DotNetStac/Extensions/Processing/ProcessingStacExtensionExtensions.cs @@ -0,0 +1,40 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProcessingStacExtensionExtensions.cs + +namespace Stac.Extensions.Processing +{ + /// + /// Helper class to access the Processing extension + /// + public static class ProcessingStacExtensionExtensions + { + /// + /// Gets the ProcessingStacExtension class from a StacItem + /// + /// The STAC item + /// The ProcessingStacExtension class + public static ProcessingStacExtension ProcessingExtension(this StacItem stacItem) + { + return new ProcessingStacExtension(stacItem); + } + + /// + /// Initialize the major fields of processing extensions + /// + /// The processing extension + /// The lineage + /// The level + /// The facility + public static void Init( + this ProcessingStacExtension processingStacExtension, + string lineage, + string level, + string facility = null) + { + processingStacExtension.Lineage = lineage; + processingStacExtension.Level = level; + processingStacExtension.Facility = facility; + } + } +} diff --git a/src/DotNetStac/Extensions/Projection/CentroidObject.cs b/src/DotNetStac/Extensions/Projection/CentroidObject.cs new file mode 100644 index 00000000..e5987094 --- /dev/null +++ b/src/DotNetStac/Extensions/Projection/CentroidObject.cs @@ -0,0 +1,22 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: CentroidObject.cs + +namespace Stac.Extensions.Projection +{ + /// + /// Centroid object + /// + public class CentroidObject + { + /// + /// Gets or sets the longitude. + /// + public double Longitude { get; set; } + + /// + /// Gets or sets the latitude. + /// + public double Latitude { get; set; } + } +} diff --git a/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs b/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs index 4bf1d9ec..c8487cdd 100644 --- a/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs +++ b/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs @@ -1,13 +1,20 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProjectionStacExtension.cs + +using System; using System.Collections.Generic; using GeoJSON.Net.Geometry; using ProjNet.CoordinateSystems; namespace Stac.Extensions.Projection { + /// + /// Helper class to access the fields defined by the Projection extension + /// public class ProjectionStacExtension : StacPropertiesContainerExtension, IStacExtension { - +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/projection/v1.0.0/schema.json"; public const string EpsgField = "proj:epsg"; @@ -19,126 +26,217 @@ public class ProjectionStacExtension : StacPropertiesContainerExtension, IStacEx public const string ProjShapeField = "proj:shape"; public const string ProjTransformField = "proj:transform"; - private readonly Dictionary itemFields; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + private readonly Dictionary _itemFields; - internal ProjectionStacExtension(StacItem stacItem) : base(JsonSchemaUrl, stacItem) + internal ProjectionStacExtension(StacItem stacItem) + : base(JsonSchemaUrl, stacItem) { - itemFields = new Dictionary(); - itemFields.Add(EpsgField, typeof(int)); - itemFields.Add(Wkt2Field, typeof(string)); - itemFields.Add(ProjJsonField, typeof(string)); - itemFields.Add(ProjGeometryField, typeof(IGeometryObject)); - itemFields.Add(ProjBboxField, typeof(double[])); - itemFields.Add(ProjCentroidField, typeof(CentroidObject)); - itemFields.Add(ProjShapeField, typeof(int[])); - itemFields.Add(ProjTransformField, typeof(double[])); + this._itemFields = new Dictionary(); + this._itemFields.Add(EpsgField, typeof(int)); + this._itemFields.Add(Wkt2Field, typeof(string)); + this._itemFields.Add(ProjJsonField, typeof(string)); + this._itemFields.Add(ProjGeometryField, typeof(IGeometryObject)); + this._itemFields.Add(ProjBboxField, typeof(double[])); + this._itemFields.Add(ProjCentroidField, typeof(CentroidObject)); + this._itemFields.Add(ProjShapeField, typeof(int[])); + this._itemFields.Add(ProjTransformField, typeof(double[])); } - internal ProjectionStacExtension(StacAsset stacAsset) : base(JsonSchemaUrl, stacAsset) + internal ProjectionStacExtension(StacAsset stacAsset) + : base(JsonSchemaUrl, stacAsset) { - itemFields = new Dictionary(); - itemFields.Add(EpsgField, typeof(int)); - itemFields.Add(Wkt2Field, typeof(string)); - itemFields.Add(ProjJsonField, typeof(string)); - itemFields.Add(ProjGeometryField, typeof(IGeometryObject)); - itemFields.Add(ProjBboxField, typeof(double[])); - itemFields.Add(ProjCentroidField, typeof(CentroidObject)); - itemFields.Add(ProjShapeField, typeof(int[])); - itemFields.Add(ProjTransformField, typeof(double[])); + this._itemFields = new Dictionary(); + this._itemFields.Add(EpsgField, typeof(int)); + this._itemFields.Add(Wkt2Field, typeof(string)); + this._itemFields.Add(ProjJsonField, typeof(string)); + this._itemFields.Add(ProjGeometryField, typeof(IGeometryObject)); + this._itemFields.Add(ProjBboxField, typeof(double[])); + this._itemFields.Add(ProjCentroidField, typeof(CentroidObject)); + this._itemFields.Add(ProjShapeField, typeof(int[])); + this._itemFields.Add(ProjTransformField, typeof(double[])); } + /// + /// Gets or sets the EPSG code. + /// public long? Epsg { - get { return StacPropertiesContainer.GetProperty(EpsgField); } - set { StacPropertiesContainer.SetProperty(EpsgField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(EpsgField); + } + + set + { + this.StacPropertiesContainer.SetProperty(EpsgField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the WKT2 string. + /// public string Wkt2 { - get { return StacPropertiesContainer.GetProperty(Wkt2Field); } - set { StacPropertiesContainer.SetProperty(Wkt2Field, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(Wkt2Field); + } + + set + { + this.StacPropertiesContainer.SetProperty(Wkt2Field, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the PROJJSON string. + /// public string ProjJson { - get { return StacPropertiesContainer.GetProperty(ProjJsonField); } - set { StacPropertiesContainer.SetProperty(ProjJsonField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProjJsonField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProjJsonField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the specific geometry. + /// public IGeometryObject Geometry { - get { return StacPropertiesContainer.GetProperty(Wkt2Field); } - set { StacPropertiesContainer.SetProperty(Wkt2Field, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(Wkt2Field); + } + + set + { + this.StacPropertiesContainer.SetProperty(Wkt2Field, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the bounding box. + /// public double[] Bbox { - get { return StacPropertiesContainer.GetProperty(ProjBboxField); } - set { StacPropertiesContainer.SetProperty(ProjBboxField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProjBboxField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProjBboxField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the centroid. + /// public CentroidObject Centroid { - get { return StacPropertiesContainer.GetProperty(ProjCentroidField); } - set { StacPropertiesContainer.SetProperty(ProjCentroidField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProjCentroidField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProjCentroidField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the shape. + /// public int[] Shape { - get { return StacPropertiesContainer.GetProperty(ProjShapeField); } - set { StacPropertiesContainer.SetProperty(ProjShapeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProjShapeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProjShapeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the transformation matrix. + /// public double[] Transform { - get { return StacPropertiesContainer.GetProperty(ProjTransformField); } - set { StacPropertiesContainer.SetProperty(ProjTransformField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProjTransformField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProjTransformField, value); + this.DeclareStacExtension(); + } } - public override IDictionary ItemFields => itemFields; + /// + public override IDictionary ItemFields => this._itemFields; + /// + /// Sets the coordinate system by the given coordinate system. + /// + /// The coordinate system. public void SetCoordinateSystem(CoordinateSystem coordinateSystem) { if (coordinateSystem.AuthorityCode > 0) - Epsg = coordinateSystem.AuthorityCode; + { + this.Epsg = coordinateSystem.AuthorityCode; + } else - Epsg = null; - Wkt2 = coordinateSystem.WKT; + { + this.Epsg = null; + } + + this.Wkt2 = coordinateSystem.WKT; } + /// + /// Sets the coordinate system by the given SRID. + /// + /// The SRID. public void SetCoordinateSystem(int srid) { var cs = SRIDReader.GetCSbyID(srid); - if (cs == null) return; - Wkt2 = cs.WKT; - Epsg = srid; + if (cs == null) + { + return; + } + + this.Wkt2 = cs.WKT; + this.Epsg = srid; } + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); - summaryFunctions.Add(EpsgField, new SummaryFunction(this, EpsgField, CreateSummaryValueSet)); + summaryFunctions.Add(EpsgField, new SummaryFunction(this, EpsgField, CreateSummaryValueSet)); return summaryFunctions; } } - - public class CentroidObject - { - double Longitude { get; set; } - - double Latitude { get; set; } - } - - public static class ProjectionStacExtensionExtensions - { - public static ProjectionStacExtension ProjectionExtension(this StacItem stacItem) - { - return new ProjectionStacExtension(stacItem); - } - - public static ProjectionStacExtension ProjectionExtension(this StacAsset stacAsset) - { - return new ProjectionStacExtension(stacAsset); - } - } } diff --git a/src/DotNetStac/Extensions/Projection/ProjectionStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Projection/ProjectionStacExtensionExtensions.cs new file mode 100644 index 00000000..ce0266f1 --- /dev/null +++ b/src/DotNetStac/Extensions/Projection/ProjectionStacExtensionExtensions.cs @@ -0,0 +1,32 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ProjectionStacExtensionExtensions.cs + +namespace Stac.Extensions.Projection +{ + /// + /// Helper class to access the Projection extension. + /// + public static class ProjectionStacExtensionExtensions + { + /// + /// Get the Projection extension from a StacItem. + /// + /// The StacItem. + /// The Projection extension. + public static ProjectionStacExtension ProjectionExtension(this StacItem stacItem) + { + return new ProjectionStacExtension(stacItem); + } + + /// + /// Get the Projection extension from a Stac Asset. + /// + /// The Stac Asset. + /// The Projection extension. + public static ProjectionStacExtension ProjectionExtension(this StacAsset stacAsset) + { + return new ProjectionStacExtension(stacAsset); + } + } +} diff --git a/src/DotNetStac/Extensions/Projection/SRIDReader.cs b/src/DotNetStac/Extensions/Projection/SRIDReader.cs index c2d6b431..80857745 100644 --- a/src/DotNetStac/Extensions/Projection/SRIDReader.cs +++ b/src/DotNetStac/Extensions/Projection/SRIDReader.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SRIDReader.cs + +using System.Collections.Generic; using System.IO; using ProjNet.CoordinateSystems; using ProjNet.IO.CoordinateSystems; @@ -7,19 +11,7 @@ namespace Stac.Extensions.Projection { internal class SRIDReader { - private const string filename = @"SRID.csv"; - - public struct WKTstring - { - /// - /// Well-known ID - /// - public int WKID; - /// - /// Well-known Text - /// - public string WKT; - } + private const string Filename = @"SRID.csv"; /// /// Enumerates all SRID's in the SRID.csv file. @@ -27,7 +19,7 @@ public struct WKTstring /// Enumerator public static IEnumerable GetSRIDs() { - using (StreamReader sr = System.IO.File.OpenText(filename)) + using (StreamReader sr = System.IO.File.OpenText(Filename)) { while (!sr.EndOfStream) { @@ -35,15 +27,17 @@ public static IEnumerable GetSRIDs() int split = line.IndexOf(';'); if (split > -1) { - WKTstring wkt = new WKTstring(); + WKTstring wkt = default(WKTstring); wkt.WKID = int.Parse(line.Substring(0, split)); wkt.WKT = line.Substring(split + 1); yield return wkt; } } + sr.Close(); } } + /// /// Gets a coordinate system from the SRID.csv file /// @@ -59,7 +53,21 @@ public static CoordinateSystem GetCSbyID(int id) return CoordinateSystemWktReader.Parse(wkt.WKT) as CoordinateSystem; } } + return null; } + + public struct WKTstring + { + /// + /// Well-known ID + /// + public int WKID; + + /// + /// Well-known Text + /// + public string WKT; + } } } diff --git a/src/DotNetStac/Extensions/Raster/RasterBand.cs b/src/DotNetStac/Extensions/Raster/RasterBand.cs new file mode 100644 index 00000000..13683eba --- /dev/null +++ b/src/DotNetStac/Extensions/Raster/RasterBand.cs @@ -0,0 +1,142 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterBand.cs + +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Stac.Common; + +namespace Stac.Extensions.Raster +{ + /// + /// Represents the Raster Band Object + /// of the Raster extension + /// + [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] + public class RasterBand : IStacPropertiesContainer + { + private IDictionary _properties; + private double? _nodata; + private RasterSampling? _sampling; + private DataType? _dataType; + private string _unit; + private double? _scale; + private double? _offset; + + /// + /// Initializes a new instance of the class. + /// + public RasterBand() + { + this._properties = new Dictionary(); + } + + /// + /// Gets or sets pixel values used to identify pixels that are nodata in the assets. + /// + /// + /// Pixel values used to identify pixels that are nodata in the assets. + /// + [JsonProperty("nodata")] + public double? Nodata { get => this._nodata; set => this._nodata = value; } + + /// + /// Gets or sets one of area or point. Indicates whether a pixel value should be assumed to represent + /// a sampling over the region of the pixel or a point sample at the center of the pixel. + /// + /// + /// One of area or point. Indicates whether a pixel value should be assumed to represent + /// a sampling over the region of the pixel or a point sample at the center of the pixel. + /// + [JsonProperty("sampling")] + [JsonConverter(typeof(StringEnumConverter))] + public RasterSampling? Sampling { get => this._sampling; set => this._sampling = value; } + + /// + /// Gets or sets the data type of the band. + /// + /// + /// The data type of the band. + /// + [JsonProperty("data_type")] + [JsonConverter(typeof(StringEnumConverter))] + public DataType? DataType { get => this._dataType; set => this._dataType = value; } + + /// + /// Gets or sets the actual number of bits used for this band. + /// + /// + /// The actual number of bits used for this band. + /// + [JsonProperty("bits_per_sample")] + public int? BitsPerSample { get; set; } + + /// + /// Gets or sets average spatial resolution (in meters) of the pixels in the band. + /// + /// + /// Average spatial resolution (in meters) of the pixels in the band. + /// + [JsonProperty("spatial_resolution")] + public double? SpatialResolution { get; set; } + + /// + /// Gets or sets statistics of all the pixels in the band + /// + /// + /// Statistics of all the pixels in the band + /// + [JsonProperty("statistics")] + public Statistics Statistics { get; set; } + + /// + /// Gets or sets unit denomination of the pixel value. + /// + /// + /// Unit denomination of the pixel value. + /// + [JsonProperty("unit")] + public string Unit { get => this._unit; set => this._unit = value; } + + /// + /// Gets or sets multiplicator factor of the pixel value to transform into the value (i.e. translate digital number to reflectance). + /// + /// + /// multiplicator factor of the pixel value to transform into the value (i.e. translate digital number to reflectance). + /// + [JsonProperty("scale")] + public double? Scale { get => this._scale; set => this._scale = value; } + + /// + /// Gets or sets number to be added to the pixel value (after scaling) to transform into the value (i.e. translate digital number to reflectance). + /// + /// + /// number to be added to the pixel value (after scaling) to transform into the value (i.e. translate digital number to reflectance). + /// + [JsonProperty("offset")] + public double? Offset { get => this._offset; set => this._offset = value; } + + /// + /// Gets or sets histogram distribution information of the pixels values in the band + /// + /// + /// Histogram distribution information of the pixels values in the band + /// + [JsonProperty("histogram")] + public RasterHistogram Histogram { get; set; } + + /// + /// Gets or sets additional fields + /// + /// + /// Additional fields + /// + [JsonExtensionData] + public IDictionary Properties { get => this._properties; set => this._properties = value; } + + /// + [JsonIgnore] + public IStacObject StacObjectContainer => null; + } +} diff --git a/src/DotNetStac/Extensions/Raster/RasterBandObject.cs b/src/DotNetStac/Extensions/Raster/RasterBandObject.cs deleted file mode 100644 index 917f7980..00000000 --- a/src/DotNetStac/Extensions/Raster/RasterBandObject.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Stac.Common; - -namespace Stac.Extensions.Raster -{ - /// - /// Represents the Raster Band Object - /// of the Raster extension - /// - [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] - public class RasterBand : IStacPropertiesContainer - { - - IDictionary properties; - private double? nodata; - private RasterSampling? sampling; - private DataType? dataType; - private string unit; - private double? scale; - private double? offset; - - /// - /// Initialize a new Raster Band Object - /// - public RasterBand() - { - properties = new Dictionary(); - } - - /// - /// Pixel values used to identify pixels that are nodata in the assets. - /// - [JsonProperty("nodata")] - public double? Nodata { get => nodata; set => nodata = value; } - - /// - /// One of area or point. Indicates whether a pixel value should be assumed to represent - /// a sampling over the region of the pixel or a point sample at the center of the pixel. - /// - [JsonProperty("sampling")] - [JsonConverter(typeof(StringEnumConverter))] - public RasterSampling? Sampling { get => sampling; set => sampling = value; } - - /// - /// The data type of the band. - /// - /// - [JsonProperty("data_type")] - [JsonConverter(typeof(StringEnumConverter))] - public DataType? DataType { get => dataType; set => dataType = value; } - - /// - /// The actual number of bits used for this band. - /// - /// - [JsonProperty("bits_per_sample")] - public int? BitsPerSample { get; set; } - - /// - /// Average spatial resolution (in meters) of the pixels in the band. - /// - /// - [JsonProperty("spatial_resolution")] - public double? SpatialResolution { get; set; } - - /// - /// Statistics of all the pixels in the band - /// - /// - [JsonProperty("statistics")] - public Statistics Statistics { get; set; } - - /// - /// Unit denomination of the pixel value. - /// - [JsonProperty("unit")] - public string Unit { get => unit; set => unit = value; } - - /// - /// multiplicator factor of the pixel value to transform into the value (i.e. translate digital number to reflectance). - /// - [JsonProperty("scale")] - public double? Scale { get => scale; set => scale = value; } - - /// - /// number to be added to the pixel value (after scaling) to transform into the value (i.e. translate digital number to reflectance). - /// - [JsonProperty("offset")] - public double? Offset { get => offset; set => offset = value; } - - /// - /// Histogram distribution information of the pixels values in the band - /// - /// - [JsonProperty("histogram")] - public RasterHistogram Histogram { get; set; } - - /// - /// Additional fields - /// - /// - [JsonExtensionData] - public IDictionary Properties { get => properties; set => properties = value; } - - [JsonIgnore] - public IStacObject StacObjectContainer => null; - } -} diff --git a/src/DotNetStac/Extensions/Raster/RasterHistogram.cs b/src/DotNetStac/Extensions/Raster/RasterHistogram.cs index 38327c28..0dfb9628 100644 --- a/src/DotNetStac/Extensions/Raster/RasterHistogram.cs +++ b/src/DotNetStac/Extensions/Raster/RasterHistogram.cs @@ -1,4 +1,8 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterHistogram.cs + +using Newtonsoft.Json; namespace Stac.Extensions.Raster { @@ -9,30 +13,38 @@ namespace Stac.Extensions.Raster public class RasterHistogram { /// - /// number of buckets of the distribution. + /// Gets or sets number of buckets of the distribution. /// - /// + /// + /// Number of buckets of the distribution. + /// [JsonProperty("count")] public int? Count { get; set; } /// - /// minimum value of the distribution. Also the mean value of the first bucket. + /// Gets or sets minimum value of the distribution. Also the mean value of the first bucket. /// - /// + /// + /// Minimum value of the distribution. Also the mean value of the first bucket. + /// [JsonProperty("min")] public double? Min { get; set; } /// - /// minimum value of the distribution. Also the mean value of the last bucket. + /// Gets or sets minimum value of the distribution. Also the mean value of the last bucket. /// - /// + /// + /// Minimum value of the distribution. Also the mean value of the last bucket. + /// [JsonProperty("max")] public double? Max { get; set; } /// - /// Array of integer indicating the number of pixels included in the bucket. + /// Gets or sets array of integer indicating the number of pixels included in the bucket. /// - /// + /// + /// Array of integer indicating the number of pixels included in the bucket. + /// [JsonProperty("buckets")] public double[] Buckets { get; set; } } diff --git a/src/DotNetStac/Extensions/Raster/RasterSampling.cs b/src/DotNetStac/Extensions/Raster/RasterSampling.cs index 7ad57fdc..9789905f 100644 --- a/src/DotNetStac/Extensions/Raster/RasterSampling.cs +++ b/src/DotNetStac/Extensions/Raster/RasterSampling.cs @@ -1,13 +1,27 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterSampling.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Extensions.Raster { + /// + /// Raster sampling + /// [JsonConverter(typeof(StringEnumConverter))] public enum RasterSampling { +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + area, - point + point, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Raster/RasterStacExtension.cs b/src/DotNetStac/Extensions/Raster/RasterStacExtension.cs index 33b1fc1c..3b89382f 100644 --- a/src/DotNetStac/Extensions/Raster/RasterStacExtension.cs +++ b/src/DotNetStac/Extensions/Raster/RasterStacExtension.cs @@ -1,6 +1,9 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterStacExtension.cs + +using System; using System.Collections.Generic; -using System.Linq; namespace Stac.Extensions.Raster { @@ -9,51 +12,48 @@ namespace Stac.Extensions.Raster /// public class RasterStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extensions identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/raster/v1.0.0/schema.json"; - private static IDictionary itemFields; - private const string BandsField = "raster:bands"; + public const string BandsField = "raster:bands"; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + private readonly IDictionary _itemFields; - internal RasterStacExtension(StacAsset stacAsset) : base(JsonSchemaUrl, stacAsset) + internal RasterStacExtension(StacAsset stacAsset) + : base(JsonSchemaUrl, stacAsset) { - itemFields = new Dictionary(); - itemFields.Add(BandsField, typeof(RasterBand[])); + this._itemFields = new Dictionary(); + this._itemFields.Add(BandsField, typeof(RasterBand[])); } /// - /// An array of available bands where each object is a Band Object. + /// Gets or sets an array of available bands where each object is a Band Object. /// public RasterBand[] Bands { - get { return StacPropertiesContainer.GetProperty(BandsField); } - set { StacPropertiesContainer.SetProperty(BandsField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(BandsField); + } + + set + { + this.StacPropertiesContainer.SetProperty(BandsField, value); + this.DeclareStacExtension(); + } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; + public override IDictionary ItemFields => this._itemFields; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } } - - /// - /// Extension methods for accessing EO extension - /// - public static class RasterStacExtensionExtensions - { - - /// - /// Initilize a EoStacExtension class from a STAC asset - /// - public static RasterStacExtension RasterExtension(this StacAsset stacAsset) - { - return new RasterStacExtension(stacAsset); - } - } } diff --git a/src/DotNetStac/Extensions/Raster/RasterStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Raster/RasterStacExtensionExtensions.cs new file mode 100644 index 00000000..f7bf6624 --- /dev/null +++ b/src/DotNetStac/Extensions/Raster/RasterStacExtensionExtensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: RasterStacExtensionExtensions.cs + +namespace Stac.Extensions.Raster +{ + /// + /// Extension methods for accessing EO extension + /// + public static class RasterStacExtensionExtensions + { + /// + /// Gets RasterStacExtension class from a STAC asset + /// + /// The STAC asset + /// The RasterStacExtension class + public static RasterStacExtension RasterExtension(this StacAsset stacAsset) + { + return new RasterStacExtension(stacAsset); + } + } +} diff --git a/src/DotNetStac/Extensions/Sar/ObservationDirection.cs b/src/DotNetStac/Extensions/Sar/ObservationDirection.cs index 5d237831..4243732e 100644 --- a/src/DotNetStac/Extensions/Sar/ObservationDirection.cs +++ b/src/DotNetStac/Extensions/Sar/ObservationDirection.cs @@ -1,4 +1,8 @@ -using System.Runtime.Serialization; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ObservationDirection.cs + +using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -10,12 +14,16 @@ namespace Stac.Extensions.Sar [JsonConverter(typeof(StringEnumConverter))] public enum ObservationDirection { - /// left +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + [EnumMember(Value = "left")] Left, - /// right [EnumMember(Value = "right")] - Right + Right, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + } } diff --git a/src/DotNetStac/Extensions/Sar/SarCommonFrequencyBandName.cs b/src/DotNetStac/Extensions/Sar/SarCommonFrequencyBandName.cs index f9efcdcf..984d919b 100644 --- a/src/DotNetStac/Extensions/Sar/SarCommonFrequencyBandName.cs +++ b/src/DotNetStac/Extensions/Sar/SarCommonFrequencyBandName.cs @@ -1,12 +1,21 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SarCommonFrequencyBandName.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac.Extensions.Sar { + /// + /// SAR common frequency band name + /// [JsonConverter(typeof(StringEnumConverter))] public enum SarCommonFrequencyBandName { - +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member P, L, S, @@ -14,6 +23,9 @@ public enum SarCommonFrequencyBandName X, Ku, K, - Ka + Ka, +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/Extensions/Sar/SarStacExtension.cs b/src/DotNetStac/Extensions/Sar/SarStacExtension.cs index afdbaa6f..c4d45851 100644 --- a/src/DotNetStac/Extensions/Sar/SarStacExtension.cs +++ b/src/DotNetStac/Extensions/Sar/SarStacExtension.cs @@ -1,11 +1,18 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SarStacExtension.cs + +using System; using System.Collections.Generic; -using System.Linq; namespace Stac.Extensions.Sar { + /// + /// Helper class to access the fields defined by the SAR extension + /// public class SarStacExtension : StacPropertiesContainerExtension, IStacExtension { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/sar/v1.0.0/schema.json"; public const string InstrumentModeField = "sar:instrument_mode"; @@ -21,136 +28,250 @@ public class SarStacExtension : StacPropertiesContainerExtension, IStacExtension public const string LooksAzimuthField = "sar:looks_azimuth"; public const string LooksEquivalentNumberField = "sar:looks_equivalent_number"; public const string ObservationDirectionField = "sar:observation_direction"; - private readonly IDictionary itemFields; +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + private readonly IDictionary _itemFields; - internal SarStacExtension(IStacPropertiesContainer stacPropertiesContainer) : base(JsonSchemaUrl, stacPropertiesContainer) + internal SarStacExtension(IStacPropertiesContainer stacPropertiesContainer) + : base(JsonSchemaUrl, stacPropertiesContainer) { - itemFields = new Dictionary(); - itemFields.Add(InstrumentModeField, typeof(string[])); - itemFields.Add(FrequencyBandField, typeof(SarCommonFrequencyBandName)); - itemFields.Add(CenterFrequencyField, typeof(double)); - itemFields.Add(PolarizationsField, typeof(string[])); - itemFields.Add(ProductTypeField, typeof(string)); - itemFields.Add(ResolutionRangeField, typeof(double)); - itemFields.Add(ResolutionAzimuthField, typeof(double)); - itemFields.Add(PixelSpacingRangeField, typeof(double)); - itemFields.Add(PixelSpacingAzimuthField, typeof(double)); - itemFields.Add(LooksRangeField, typeof(double)); - itemFields.Add(LooksAzimuthField, typeof(double)); - itemFields.Add(LooksEquivalentNumberField, typeof(double)); - itemFields.Add(ObservationDirectionField, typeof(string)); + this._itemFields = new Dictionary(); + this._itemFields.Add(InstrumentModeField, typeof(string[])); + this._itemFields.Add(FrequencyBandField, typeof(SarCommonFrequencyBandName)); + this._itemFields.Add(CenterFrequencyField, typeof(double)); + this._itemFields.Add(PolarizationsField, typeof(string[])); + this._itemFields.Add(ProductTypeField, typeof(string)); + this._itemFields.Add(ResolutionRangeField, typeof(double)); + this._itemFields.Add(ResolutionAzimuthField, typeof(double)); + this._itemFields.Add(PixelSpacingRangeField, typeof(double)); + this._itemFields.Add(PixelSpacingAzimuthField, typeof(double)); + this._itemFields.Add(LooksRangeField, typeof(double)); + this._itemFields.Add(LooksAzimuthField, typeof(double)); + this._itemFields.Add(LooksEquivalentNumberField, typeof(double)); + this._itemFields.Add(ObservationDirectionField, typeof(string)); } + /// + /// Gets or sets the instrument mode + /// public string InstrumentMode { - get { return StacPropertiesContainer.GetProperty(InstrumentModeField); } - set { StacPropertiesContainer.SetProperty(InstrumentModeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(InstrumentModeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(InstrumentModeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the frequency band + /// public SarCommonFrequencyBandName FrequencyBand { - get { return StacPropertiesContainer.GetProperty(FrequencyBandField); } - set { StacPropertiesContainer.SetProperty(FrequencyBandField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(FrequencyBandField); + } + + set + { + this.StacPropertiesContainer.SetProperty(FrequencyBandField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the center frequency + /// public double CenterFrequency { - get { return StacPropertiesContainer.GetProperty(CenterFrequencyField); } - set { StacPropertiesContainer.SetProperty(CenterFrequencyField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(CenterFrequencyField); + } + + set + { + this.StacPropertiesContainer.SetProperty(CenterFrequencyField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the polarizations + /// public string[] Polarizations { - get { return StacPropertiesContainer.GetProperty(PolarizationsField); } - set { StacPropertiesContainer.SetProperty(PolarizationsField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(PolarizationsField); + } + + set + { + this.StacPropertiesContainer.SetProperty(PolarizationsField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the SAR product type + /// public string ProductType { - get { return StacPropertiesContainer.GetProperty(ProductTypeField); } - set { StacPropertiesContainer.SetProperty(ProductTypeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ProductTypeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ProductTypeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the resolution range + /// public double ResolutionRange { - get { return StacPropertiesContainer.GetProperty(ResolutionRangeField); } - set { StacPropertiesContainer.SetProperty(ResolutionRangeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ResolutionRangeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ResolutionRangeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the resolution azimuth + /// public double ResolutionAzimuth { - get { return StacPropertiesContainer.GetProperty(ResolutionAzimuthField); } - set { StacPropertiesContainer.SetProperty(ResolutionAzimuthField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(ResolutionAzimuthField); + } + + set + { + this.StacPropertiesContainer.SetProperty(ResolutionAzimuthField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the pixel spacing range + /// public double PixelSpacingRange { - get { return StacPropertiesContainer.GetProperty(PixelSpacingRangeField); } - set { StacPropertiesContainer.SetProperty(PixelSpacingRangeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(PixelSpacingRangeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(PixelSpacingRangeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the pixel spacing azimuth + /// public double PixelSpacingAzimuth { - get { return StacPropertiesContainer.GetProperty(PixelSpacingAzimuthField); } - set { StacPropertiesContainer.SetProperty(PixelSpacingAzimuthField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(PixelSpacingAzimuthField); + } + + set + { + this.StacPropertiesContainer.SetProperty(PixelSpacingAzimuthField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the looks range + /// public double LooksRange { - get { return StacPropertiesContainer.GetProperty(LooksRangeField); } - set { StacPropertiesContainer.SetProperty(LooksRangeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(LooksRangeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(LooksRangeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the looks azimuth + /// public double LooksAzimuth { - get { return StacPropertiesContainer.GetProperty(LooksAzimuthField); } - set { StacPropertiesContainer.SetProperty(LooksAzimuthField, value); DeclareStacExtension(); } - } + get + { + return this.StacPropertiesContainer.GetProperty(LooksAzimuthField); + } - public double LooksEquivalentNumber - { - get { return StacPropertiesContainer.GetProperty(LooksEquivalentNumberField); } - set { StacPropertiesContainer.SetProperty(LooksEquivalentNumberField, value); DeclareStacExtension(); } + set + { + this.StacPropertiesContainer.SetProperty(LooksAzimuthField, value); + this.DeclareStacExtension(); + } } - public ObservationDirection? ObservationDirection + /// + /// Gets or sets the looks equivalent number + /// + public double LooksEquivalentNumber { - get { return StacPropertiesContainer.GetProperty(ObservationDirectionField); } - set { StacPropertiesContainer.SetProperty(ObservationDirectionField, value); DeclareStacExtension(); } - } + get + { + return this.StacPropertiesContainer.GetProperty(LooksEquivalentNumberField); + } - public override IDictionary ItemFields => itemFields; - } - - public static class SarStacExtensionExtensions - { - public static SarStacExtension SarExtension(this StacItem stacItem) - { - return new SarStacExtension(stacItem); + set + { + this.StacPropertiesContainer.SetProperty(LooksEquivalentNumberField, value); + this.DeclareStacExtension(); + } } - public static SarStacExtension SarExtension(this StacAsset stacAsset) + /// + /// Gets or sets the observation direction + /// + public ObservationDirection? ObservationDirection { - return new SarStacExtension(stacAsset); - } + get + { + return this.StacPropertiesContainer.GetProperty(ObservationDirectionField); + } - public static StacAsset GetAsset(this StacItem stacItem, string polarization) - { - return stacItem.Assets.Values.FirstOrDefault(a => a.SarExtension().Polarizations.Contains(polarization)); + set + { + this.StacPropertiesContainer.SetProperty(ObservationDirectionField, value); + this.DeclareStacExtension(); + } } - public static void Required(this SarStacExtension sarStacExtension, - string instrumentMode, - SarCommonFrequencyBandName frequencyBandName, - string[] polarizations, - string productType) - { - sarStacExtension.InstrumentMode = instrumentMode; - sarStacExtension.FrequencyBand = frequencyBandName; - sarStacExtension.Polarizations = polarizations; - sarStacExtension.ProductType = productType; - } + /// + public override IDictionary ItemFields => this._itemFields; } - - } diff --git a/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs new file mode 100644 index 00000000..11aa1cc1 --- /dev/null +++ b/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs @@ -0,0 +1,67 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SarStacExtensionExtensions.cs + +using System; +using System.Linq; + +namespace Stac.Extensions.Sar +{ + /// + /// Helper class to access the SAR extension. + /// + public static class SarStacExtensionExtensions + { + /// + /// Gets the SAR extension. + /// + /// The STAC item. + /// The SAR extension. + public static SarStacExtension SarExtension(this StacItem stacItem) + { + return new SarStacExtension(stacItem); + } + + /// + /// Gets the SAR extension. + /// + /// The STAC asset. + /// The SAR extension. + public static SarStacExtension SarExtension(this StacAsset stacAsset) + { + return new SarStacExtension(stacAsset); + } + + /// + /// Gets the Stac Asset with the specified polarization. + /// + /// The STAC item. + /// The polarization. + /// The Stac Asset. + public static StacAsset GetAsset(this StacItem stacItem, string polarization) + { + return stacItem.Assets.Values.FirstOrDefault(a => a.SarExtension().Polarizations.Contains(polarization)); + } + + /// + /// Sets the required SAR extension properties. + /// + /// The SAR extension. + /// The instrument mode. + /// Name of the frequency band. + /// The polarizations. + /// Type of the product. + public static void Required( + this SarStacExtension sarStacExtension, + string instrumentMode, + SarCommonFrequencyBandName frequencyBandName, + string[] polarizations, + string productType) + { + sarStacExtension.InstrumentMode = instrumentMode; + sarStacExtension.FrequencyBand = frequencyBandName; + sarStacExtension.Polarizations = polarizations; + sarStacExtension.ProductType = productType; + } + } +} diff --git a/src/DotNetStac/Extensions/Sat/BaselineCalculation.cs b/src/DotNetStac/Extensions/Sat/BaselineCalculation.cs index 0e09e206..ab9b3448 100644 --- a/src/DotNetStac/Extensions/Sat/BaselineCalculation.cs +++ b/src/DotNetStac/Extensions/Sat/BaselineCalculation.cs @@ -1,6 +1,8 @@ -using System; -using System.Collections; -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: BaselineCalculation.cs + +using System; using GeoJSON.Net.Geometry; using MathNet.Numerics; using MathNet.Numerics.Interpolation; @@ -9,16 +11,16 @@ namespace Stac.Extensions.Sat { - + /// + /// Baseline calculation helper class. + /// public class BaselineCalculation { - - /// Synchronizes the vector. /// The vector. /// T0. /// Ground point. - /// Master. + /// Slave. /// Converged. /// Max error. /// Max iterations. @@ -30,15 +32,13 @@ public static double SynchronizeVector( out bool converged, out double maxError, int maxIterations = 100, - double tolerance = 0.00000001 - ) + double tolerance = 0.00000001) { double t = t0; double delta = 0; for (int i = 0; i < maxIterations; i++) { - double x = groundPoint.Longitude; double y = groundPoint.Latitude; double z = groundPoint.Altitude.Value; @@ -55,10 +55,12 @@ public static double SynchronizeVector( double aym = Ay(t, slave); double azm = Az(t, slave); - delta = -(vxm * (x - sxm) + vym * (y - sym) + vzm * (z - szm)) / (axm * (x - sxm) + aym * (y - sym) + azm * (z - szm) - vxm * vxm - vym * vym - vzm * vzm); + delta = -((vxm * (x - sxm)) + (vym * (y - sym)) + (vzm * (z - szm))) / ((axm * (x - sxm)) + (aym * (y - sym)) + (azm * (z - szm)) - (vxm * vxm) - (vym * vym) - (vzm * vzm)); t += delta; - if (Math.Abs(delta) < tolerance) break; - + if (Math.Abs(delta) < tolerance) + { + break; + } } maxError = Math.Abs(delta); @@ -69,8 +71,15 @@ public static double SynchronizeVector( return t; } - //--------------------------------------------------------------------------------------------------------------------- - + /// Synchronizes the vector2. + /// T0. + /// Ground point. + /// Interpol. + /// Converged. + /// Max error. + /// Max iterations. + /// Tolerance. + /// The vector2. public static double SynchronizeVector2( double t0, IPosition groundPoint, @@ -78,15 +87,13 @@ public static double SynchronizeVector2( out bool converged, out double maxError, int maxIterations = 100, - double tolerance = 0.00000001 - ) + double tolerance = 0.00000001) { double t = t0; double delta = 0; for (int i = 0; i < maxIterations; i++) { - double x = groundPoint.Longitude; double y = groundPoint.Latitude; double z = groundPoint.Altitude.Value; @@ -103,10 +110,12 @@ public static double SynchronizeVector2( double aym = Ay(t, interpol); double azm = Az(t, interpol); - delta = -(vxm * (x - sxm) + vym * (y - sym) + vzm * (z - szm)) / (axm * (x - sxm) + aym * (y - sym) + azm * (z - szm) - vxm * vxm - vym * vym - vzm * vzm); + delta = -((vxm * (x - sxm)) + (vym * (y - sym)) + (vzm * (z - szm))) / ((axm * (x - sxm)) + (aym * (y - sym)) + (azm * (z - szm)) - (vxm * vxm) - (vym * vym) - (vzm * vzm)); t += delta; - if (Math.Abs(delta) < tolerance) break; - + if (Math.Abs(delta) < tolerance) + { + break; + } } maxError = Math.Abs(delta); @@ -117,10 +126,14 @@ public static double SynchronizeVector2( return t; } - + /// Calculates the baseline. + /// Time. + /// Master. + /// Slave. + /// Ground point. + /// The baseline. public static BaselineVector CalculateBaseline(DateTime[] time, SatOrbitStateVector[] master, SatOrbitStateVector[] slave, IPosition groundPoint) { - var interpolSlave = PolyInterpol(time[1], slave); var interpolMaster = PolyInterpol(time[0], master); @@ -131,163 +144,195 @@ public static BaselineVector CalculateBaseline(DateTime[] time, SatOrbitStateVec // bool converged; // double maxError; double t = time[2].Subtract(time[0]).TotalSeconds; - //double tm = SynchronizeVector(t, groundPoint, interpolMaster, out converged, out maxError); - //double ts = SynchronizeVector(t, groundPoint, interpolSlave, out converged, out maxError); + + // double tm = SynchronizeVector(t, groundPoint, interpolMaster, out converged, out maxError); + // double ts = SynchronizeVector(t, groundPoint, interpolSlave, out converged, out maxError); // Define baseline vector: - double[] b = new double[3] { + double[] defaultBaselineVector = new double[3] + { Sx(t, interpolSlave) - Sx(t, interpolMaster), Sy(t, interpolSlave) - Sy(t, interpolMaster), - Sz(t, interpolSlave) - Sz(t, interpolMaster) + Sz(t, interpolSlave) - Sz(t, interpolMaster), }; - double bMod = Math.Sqrt(b[0] * b[0] + b[1] * b[1] + b[2] * b[2]); + double baselineModulo = Math.Sqrt((defaultBaselineVector[0] * defaultBaselineVector[0]) + (defaultBaselineVector[1] * defaultBaselineVector[1]) + (defaultBaselineVector[2] * defaultBaselineVector[2])); // Baseline unit vector - double[] bUnit = new double[3]; // - for (int k = 0; k < 3; k++) bUnit[k] = b[k] / bMod; + double[] baselineUnit = new double[3]; + for (int k = 0; k < 3; k++) + { + baselineUnit[k] = defaultBaselineVector[k] / baselineModulo; + } // Parallel vector - double[] vpar = new double[3] { + double[] parallelVector = new double[3] + { x - Sx(t, interpolMaster), y - Sy(t, interpolMaster), - z - Sz(t, interpolMaster) + z - Sz(t, interpolMaster), }; - double vparMod = Math.Sqrt(vpar[0] * vpar[0] + vpar[1] * vpar[1] + vpar[2] * vpar[2]); + double parallelVectorModulo = Math.Sqrt((parallelVector[0] * parallelVector[0]) + (parallelVector[1] * parallelVector[1]) + (parallelVector[2] * parallelVector[2])); // Parallel unit vector - double[] vparUnit = new double[3]; - for (int k = 0; k < 3; k++) vparUnit[k] = vpar[k] / vparMod; + double[] parallelVectorUnit = new double[3]; + for (int k = 0; k < 3; k++) + { + parallelVectorUnit[k] = parallelVector[k] / parallelVectorModulo; + } // Along-track vector - double[] va = new double[3] { + double[] alongTrackVector = new double[3] + { Vx(t, interpolMaster), Vy(t, interpolMaster), - Vz(t, interpolMaster) + Vz(t, interpolMaster), }; - double vaMod = Math.Sqrt(va[0] * va[0] + va[1] * va[1] + va[2] * va[2]); + double alongTrackVectorMod = Math.Sqrt((alongTrackVector[0] * alongTrackVector[0]) + (alongTrackVector[1] * alongTrackVector[1]) + (alongTrackVector[2] * alongTrackVector[2])); // Along-track unit vector - double[] vaUnit = new double[3]; - for (int k = 0; k < 3; k++) vaUnit[k] = va[k] / vaMod; - - double[] vperpUnit = VectorProduct3D(vparUnit, vaUnit); + double[] alongTrackVectorUnit = new double[3]; + for (int k = 0; k < 3; k++) + { + alongTrackVectorUnit[k] = alongTrackVector[k] / alongTrackVectorMod; + } - double bPerp = b[0] * vperpUnit[0] + b[1] * vperpUnit[1] + b[2] * vperpUnit[2]; - double bParallel = b[0] * vparUnit[0] + b[1] * vparUnit[1] + b[2] * vparUnit[2]; - double bAlong = b[0] * vaUnit[0] + b[1] * vaUnit[1] + b[2] * vaUnit[2]; + double[] perpendicularVectorUnit = VectorProduct3D(parallelVectorUnit, alongTrackVectorUnit); - return new BaselineVector(bPerp, bParallel, bAlong); + double perpendicularBaseline = (defaultBaselineVector[0] * perpendicularVectorUnit[0]) + (defaultBaselineVector[1] * perpendicularVectorUnit[1]) + (defaultBaselineVector[2] * perpendicularVectorUnit[2]); + double parallelBaseline = (defaultBaselineVector[0] * parallelVectorUnit[0]) + (defaultBaselineVector[1] * parallelVectorUnit[1]) + (defaultBaselineVector[2] * parallelVectorUnit[2]); + double alongBaseline = (defaultBaselineVector[0] * alongTrackVectorUnit[0]) + (defaultBaselineVector[1] * alongTrackVectorUnit[1]) + (defaultBaselineVector[2] * alongTrackVectorUnit[2]); + return new BaselineVector(perpendicularBaseline, parallelBaseline, alongBaseline); } + /// Calculates 3D vector product + /// Vector A. + /// Vector B. + /// 3D vector product. public static double[] VectorProduct3D(double[] vectorA, double[] vectorB) { if (vectorA.Length != 3 || vectorB.Length != 3) + { throw new ArgumentException("3D vector product cannot be calculated, because one of the vectors is not a 3D vector"); - return new double[3] { - vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1], - vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2], - vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0] + } + + return new double[3] + { + (vectorA[1] * vectorB[2]) - (vectorA[2] * vectorB[1]), + (vectorA[2] * vectorB[0]) - (vectorA[0] * vectorB[2]), + (vectorA[0] * vectorB[1]) - (vectorA[1] * vectorB[0]), }; } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Sx(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 0); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Sy(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 1); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Sz(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 2); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Vx(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 3); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Vy(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 4); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Vz(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 5); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Ax(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 6); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Ay(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 7); } - //--------------------------------------------------------------------------------------------------------------------- - + /// Calculates the orbit value. + /// Time. + /// Orbit states. + /// The orbit value. public static double Az(double time, IInterpolation[] orbitStates) { return GetOrbitValue(time, orbitStates, 8); } - //--------------------------------------------------------------------------------------------------------------------- - - private static double GetOrbitValue(double time, IInterpolation[] interpol, int index) - { - - return interpol[index].Interpolate(time); - - } - - //--------------------------------------------------------------------------------------------------------------------- - + /// + /// Interpolates the orbit state vectors. + /// + /// Time of the orbit state vector to interpolate + /// The orbit state vectors. + /// Interpolated orbit state vectors. public static IInterpolation[] PolyInterpol(DateTime time0, SatOrbitStateVector[] orbitStateVectors) { + var time = Array.ConvertAll(orbitStateVectors, o => o.Time.Subtract(time0).TotalSeconds); - var time = Array.ConvertAll(orbitStateVectors, o => o.Time.Subtract(time0).TotalSeconds); - - Vector x1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[0])); - Vector y1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[1])); - Vector z1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[2])); + Vector x1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[0])); + Vector y1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[1])); + Vector z1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Position[2])); - Vector vx1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[0])); - Vector vy1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[1])); - Vector vz1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[2])); + Vector vx1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[0])); + Vector vy1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[1])); + Vector vz1 = DenseVector.OfArray(Array.ConvertAll(orbitStateVectors, o => o.Velocity[2])); Vector ax1 = DenseVector.Create(vx1.Count, 0.0); Vector ay1 = DenseVector.Create(vy1.Count, 0.0); Vector az1 = DenseVector.Create(vz1.Count, 0.0); for (int i = 0; i < vx1.Count; i++) { - ax1[i] = vx1[i] * i + 1; - ay1[i] = vy1[i] * i + 1; - az1[i] = vz1[i] * i + 1; + ax1[i] = (vx1[i] * i) + 1; + ay1[i] = (vy1[i] * i) + 1; + az1[i] = (vz1[i] * i) + 1; } IInterpolation[] coeff = new IInterpolation[9]; @@ -303,10 +348,11 @@ public static IInterpolation[] PolyInterpol(DateTime time0, SatOrbitStateVector[ coeff[8] = Interpolate.CubicSplineRobust(time, az1.ToArray()); return coeff; - } + private static double GetOrbitValue(double time, IInterpolation[] interpol, int index) + { + return interpol[index].Interpolate(time); + } } - - } diff --git a/src/DotNetStac/Extensions/Sat/BaselineVector.cs b/src/DotNetStac/Extensions/Sat/BaselineVector.cs index 1a4c1a05..fff626d3 100644 --- a/src/DotNetStac/Extensions/Sat/BaselineVector.cs +++ b/src/DotNetStac/Extensions/Sat/BaselineVector.cs @@ -1,33 +1,56 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: BaselineVector.cs namespace Stac.Extensions.Sat { - + /// + /// Baseline vector + /// public struct BaselineVector { - private double perpendicular, parallel, along; + private readonly double _perpendicular; + private readonly double _parallel; + private readonly double _along; - public double Perpendicular + /// + /// Initializes a new instance of the struct. + /// + /// Perpendicular component. + /// Parallel component. + /// Along component. + public BaselineVector(double perpendicular, double parallel, double along) { - get { return perpendicular; } + this._perpendicular = perpendicular; + this._parallel = parallel; + this._along = along; } - public double Parallel + /// + /// Gets the perpendicular component. + /// + /// The perpendicular component. + public double Perpendicular { - get { return parallel; } + get { return this._perpendicular; } } - public double Along + /// + /// Gets the parallel component. + /// + /// The parallel component. + public double Parallel { - get { return along; } + get { return this._parallel; } } - public BaselineVector(double perpendicular, double parallel, double along) + /// + /// Gets the along component. + /// + /// The along component. + public double Along { - this.perpendicular = perpendicular; - this.parallel = parallel; - this.along = along; + get { return this._along; } } } - } diff --git a/src/DotNetStac/Extensions/Sat/SatOrbitStateVector.cs b/src/DotNetStac/Extensions/Sat/SatOrbitStateVector.cs index 4078add8..d0e6363b 100644 --- a/src/DotNetStac/Extensions/Sat/SatOrbitStateVector.cs +++ b/src/DotNetStac/Extensions/Sat/SatOrbitStateVector.cs @@ -1,23 +1,61 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SatOrbitStateVector.cs + +using System; namespace Stac.Extensions.Sat { + /// + /// Orbit state vector + /// public class SatOrbitStateVector { - public DateTime Time; + /// + /// Initializes a new instance of the class. + /// + /// Time of the state vector + /// Position of the state vector + /// Velocity of the state vector + /// Acceleration of the state vector + public SatOrbitStateVector(DateTime time, double[] position, double[] velocity, double[] acceleration) + { + this.Time = time; + this.Position = position; + this.Velocity = velocity; + this.Acceleration = acceleration; + } - public double[] Position; + /// + /// Gets or sets time of the state vector + /// + /// + /// Time of the state vector + /// + public DateTime Time { get; set; } - public double[] Velocity; + /// + /// Gets or sets position of the state vector + /// + /// + /// Position of the state vector + /// + public double[] Position { get; set; } - public double[] Acceleration; + /// + /// Gets or sets velocity of the state vector + /// + /// + /// Velocity of the state vector + /// + public double[] Velocity { get; set; } - public SatOrbitStateVector(DateTime time, double[] position, double[] velocity, double[] acceleration) - { - Time = time; - Position = position; - Velocity = velocity; - Acceleration = acceleration; - } + /// + /// Gets or sets acceleration of the state vector + /// + /// + /// Acceleration of the state vector + /// + public double[] Acceleration { get; set; } } } diff --git a/src/DotNetStac/Extensions/Sat/SatStacExtension.cs b/src/DotNetStac/Extensions/Sat/SatStacExtension.cs index 46226f29..000b22f1 100644 --- a/src/DotNetStac/Extensions/Sat/SatStacExtension.cs +++ b/src/DotNetStac/Extensions/Sat/SatStacExtension.cs @@ -1,12 +1,20 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SatStacExtension.cs + +using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Linq; namespace Stac.Extensions.Sat { + /// + /// Satellite extension + /// public class SatStacExtension : StacPropertiesContainerExtension, IStacExtension { +#pragma warning disable CS1591 // Elements should be documented public const string JsonSchemaUrl = "https://stac-extensions.github.io/sat/v1.0.0/schema.json"; public const string OrbitStateVectorField = "sat:orbit_state_vectors"; public const string AscendingNodeCrossingDateTimeField = "sat:anx_datetime"; @@ -15,89 +23,190 @@ public class SatStacExtension : StacPropertiesContainerExtension, IStacExtension public const string AbsoluteOrbitField = "sat:absolute_orbit"; public const string OrbitStateField = "sat:orbit_state"; public const string PlatformInternationalDesignatorField = "sat:platform_international_designator"; - private readonly Dictionary itemFields; +#pragma warning restore CS1591 // Elements should be documented + + private readonly Dictionary _itemFields; - public SatStacExtension(StacItem stacItem) : base(JsonSchemaUrl, stacItem) + /// + /// Initializes a new instance of the class. + /// + /// The stac item. + public SatStacExtension(StacItem stacItem) + : base(JsonSchemaUrl, stacItem) { - itemFields = new Dictionary(); - itemFields.Add(AscendingNodeCrossingDateTimeField, typeof(DateTime)); - itemFields.Add(SceneCenterCoordinatesField, typeof(double[])); - itemFields.Add(RelativeOrbitField, typeof(int)); - itemFields.Add(AbsoluteOrbitField, typeof(int)); - itemFields.Add(OrbitStateField, typeof(string)); - itemFields.Add(PlatformInternationalDesignatorField, typeof(string)); + this._itemFields = new Dictionary(); + this._itemFields.Add(AscendingNodeCrossingDateTimeField, typeof(DateTime)); + this._itemFields.Add(SceneCenterCoordinatesField, typeof(double[])); + this._itemFields.Add(RelativeOrbitField, typeof(int)); + this._itemFields.Add(AbsoluteOrbitField, typeof(int)); + this._itemFields.Add(OrbitStateField, typeof(string)); + this._itemFields.Add(PlatformInternationalDesignatorField, typeof(string)); } + /// + /// Gets the orbit state vectors. + /// + /// + /// The orbit state vectors. + /// public SortedDictionary OrbitStateVectors { get { SortedDictionary orbitStateVectors = new SortedDictionary(); - var osvarray = StacPropertiesContainer.GetProperty(OrbitStateVectorField); - if (osvarray == null) return null; - orbitStateVectors = SortOrbitStateVectors(osvarray as JToken); + var osvarray = this.StacPropertiesContainer.GetProperty(OrbitStateVectorField); + if (osvarray == null) + { + return null; + } + + orbitStateVectors = this.SortOrbitStateVectors(osvarray as JToken); return orbitStateVectors; } } + /// + /// Gets or sets the ascending node crossing date time. + /// + /// + /// The ascending node crossing date time. + /// public DateTime AscendingNodeCrossingDateTime { - get { return StacPropertiesContainer.GetProperty(AscendingNodeCrossingDateTimeField); } - set { StacPropertiesContainer.SetProperty(AscendingNodeCrossingDateTimeField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(AscendingNodeCrossingDateTimeField); + } + + set + { + this.StacPropertiesContainer.SetProperty(AscendingNodeCrossingDateTimeField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the platform international designator. + /// + /// + /// The platform international designator. + /// public string PlatformInternationalDesignator { - get { return StacPropertiesContainer.GetProperty(PlatformInternationalDesignatorField); } - set { StacPropertiesContainer.SetProperty(PlatformInternationalDesignatorField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(PlatformInternationalDesignatorField); + } + + set + { + this.StacPropertiesContainer.SetProperty(PlatformInternationalDesignatorField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the scene center coordinates. + /// + /// + /// The scene center coordinates. + /// public double[] SceneCenterCoordinates { - get { return StacPropertiesContainer.GetProperty(SceneCenterCoordinatesField); } - set { StacPropertiesContainer.SetProperty(SceneCenterCoordinatesField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(SceneCenterCoordinatesField); + } + + set + { + this.StacPropertiesContainer.SetProperty(SceneCenterCoordinatesField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the relative orbit. + /// + /// + /// The relative orbit. + /// public int RelativeOrbit { - get { return StacPropertiesContainer.GetProperty(RelativeOrbitField); } - set { StacPropertiesContainer.SetProperty(RelativeOrbitField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(RelativeOrbitField); + } + + set + { + this.StacPropertiesContainer.SetProperty(RelativeOrbitField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the absolute orbit. + /// + /// + /// The absolute orbit. + /// public int AbsoluteOrbit { - get { return StacPropertiesContainer.GetProperty(AbsoluteOrbitField); } - set { StacPropertiesContainer.SetProperty(AbsoluteOrbitField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(AbsoluteOrbitField); + } + + set + { + this.StacPropertiesContainer.SetProperty(AbsoluteOrbitField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the orbit state. + /// + /// + /// The orbit state. + /// public string OrbitState { - get { return StacPropertiesContainer.GetProperty(OrbitStateField); } - set { StacPropertiesContainer.SetProperty(OrbitStateField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(OrbitStateField); + } + + set + { + this.StacPropertiesContainer.SetProperty(OrbitStateField, value); + this.DeclareStacExtension(); + } } - public StacItem StacItem => StacPropertiesContainer as StacItem; + /// + /// Gets the stac item. + /// + /// + /// The stac item. + /// + public StacItem StacItem => this.StacPropertiesContainer as StacItem; - public override IDictionary ItemFields => itemFields; + /// + public override IDictionary ItemFields => this._itemFields; private SortedDictionary SortOrbitStateVectors(JToken osvarray) { if (!(osvarray is JArray)) + { throw new FormatException(string.Format("[sat] field {0}: not an array", OrbitStateVectorField)); + } var osvlist = osvarray.ToObject>(); return new SortedDictionary(osvlist.ToDictionary(osv => osv.Time, osv => osv)); } - - } - - public static class SatStacExtensionExtensions - { - public static SatStacExtension SatExtension(this StacItem stacItem) - { - return new SatStacExtension(stacItem); - } } } diff --git a/src/DotNetStac/Extensions/Sat/SatStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Sat/SatStacExtensionExtensions.cs new file mode 100644 index 00000000..6bcb6513 --- /dev/null +++ b/src/DotNetStac/Extensions/Sat/SatStacExtensionExtensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SatStacExtensionExtensions.cs + +namespace Stac.Extensions.Sat +{ + /// + /// Extension methods for the SatStacExtension + /// + public static class SatStacExtensionExtensions + { + /// + /// Gets the SatStacExtension from the StacItem. + /// + /// The StacItem. + /// The SatStacExtension. + public static SatStacExtension SatExtension(this StacItem stacItem) + { + return new SatStacExtension(stacItem); + } + } +} diff --git a/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs b/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs index 32378ee8..52392040 100644 --- a/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs +++ b/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs @@ -1,23 +1,38 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SatStacExtensionHelpers.cs + +using System; using System.Linq; using GeoJSON.Net.Geometry; -using Itenso.TimePeriod; -using Stac; -using Stac.Extensions; namespace Stac.Extensions.Sat { + /// + /// Helpers methods for the SatStacExtension + /// public static class SatStacExtensionHelpers { + /// + /// Calculates the baseline. + /// + /// The baseline. + /// Sat1. + /// Sat2. public static BaselineVector CalculateBaseline(this SatStacExtension sat1, SatStacExtension sat2) { StacItem masterItem = sat1.StacItem; StacItem slaveItem = sat2.StacItem; if (sat1.OrbitStateVectors.Count() == 0) + { throw new OperationCanceledException("sat1 has no orbit state vectors"); + } + if (sat2.OrbitStateVectors.Count() == 0) + { throw new OperationCanceledException("sat2 has no orbit state vectors"); + } DateTime masterAnxDate = sat1.AscendingNodeCrossingDateTime; DateTime slaveAnxDate = sat2.AscendingNodeCrossingDateTime; @@ -31,7 +46,6 @@ public static BaselineVector CalculateBaseline(this SatStacExtension sat1, SatSt var baseline = BaselineCalculation.CalculateBaseline(times, masterOrbits.ToArray(), slaveOrbits.ToArray(), p0); return baseline; - } } } diff --git a/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs b/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs index f9659cab..55e39abc 100644 --- a/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs +++ b/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs @@ -1,53 +1,90 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SchemaBasedStacExtension.cs + +using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json.Schema; using Stac.Exceptions; using Stac.Schemas; namespace Stac.Extensions { + /// + /// A schema based extension + /// public class SchemaBasedStacExtension : StacPropertiesContainerExtension, IStacExtension { - private readonly IStacObject stacObject; + private readonly IStacObject _stacObject; - public SchemaBasedStacExtension(Uri jsonSchema, - IStacObject stacObject) : base(jsonSchema.ToString(), - stacObject) + /// + /// Initializes a new instance of the class. + /// + /// The json schema. + /// The stac object. + public SchemaBasedStacExtension( + Uri jsonSchema, + IStacObject stacObject) + : base( + jsonSchema.ToString(), + stacObject) { - Preconditions.CheckNotNull(jsonSchema, "jsonSchema"); - JsonSchema = jsonSchema; - this.stacObject = stacObject; + Preconditions.CheckNotNull(jsonSchema, "jsonSchema"); + this.JsonSchema = jsonSchema; + this._stacObject = stacObject; } - public SchemaBasedStacExtension(Uri schemaUri, - StacSchemaResolver stacSchemaResolver, - IStacObject stacObject) : base(schemaUri.ToString(), - stacObject) + /// + /// Initializes a new instance of the class. + /// + /// The schema URI. + /// The stac schema resolver. + /// The stac object. + public SchemaBasedStacExtension( + Uri schemaUri, + StacSchemaResolver stacSchemaResolver, + IStacObject stacObject) + : base( + schemaUri.ToString(), + stacObject) { - Preconditions.CheckNotNull(schemaUri, "schemaUri"); - this.stacObject = stacObject; - JsonSchema = schemaUri; + Preconditions.CheckNotNull(schemaUri, "schemaUri"); + this._stacObject = stacObject; + this.JsonSchema = schemaUri; } + /// + public override string Identifier => this.JsonSchema.ToString(); + + /// + /// Gets the json schema. + /// + /// The schema URI + public Uri JsonSchema { get; } + + /// + public override IDictionary ItemFields => new Dictionary(); - public static SchemaBasedStacExtension Create(string shortcut, - StacSchemaResolver stacSchemaResolver, - IStacObject stacObject) + /// + /// Creates a new instance of the class. + /// + /// The shortcut. + /// The stac schema resolver. + /// The stac object. + /// The extension + public static SchemaBasedStacExtension Create( + string shortcut, + StacSchemaResolver stacSchemaResolver, + IStacObject stacObject) { if (StacSchemaResolver.CoreTypes.Contains(shortcut)) - throw new Exceptions.InvalidStacSchemaException(shortcut + "is not an extension"); + { + throw new InvalidStacSchemaException(shortcut + "is not an extension"); + } + Uri schema = new Uri($"https://stac-extensions.github.io/{shortcut}/v1.0.0/schema.json"); return new SchemaBasedStacExtension(schema, stacObject); } - - public override string Identifier => JsonSchema.ToString(); - - public Uri JsonSchema { get; } - - public override IDictionary ItemFields => new Dictionary(); } } diff --git a/src/DotNetStac/Extensions/StacExtensions.cs b/src/DotNetStac/Extensions/StacExtensions.cs index cb530cb8..1fa1680e 100644 --- a/src/DotNetStac/Extensions/StacExtensions.cs +++ b/src/DotNetStac/Extensions/StacExtensions.cs @@ -1,10 +1,12 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacExtensions.cs + +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; -using Newtonsoft.Json.Schema; -using Stac.Schemas; namespace Stac.Extensions { @@ -13,21 +15,27 @@ namespace Stac.Extensions /// public static class StacExtensions { - private static Dictionary managedStacExtensions = new Dictionary(); - private static object initLock = new object(); + private static readonly object InitLock = new object(); + private static Dictionary ManagedStacExtensionsDic = new Dictionary(); /// - /// Dictionary of extensions managed by the library + /// Gets dictionary of extensions managed by the library /// - /// + /// + /// Dictionary of extensions managed by the library + /// public static Dictionary ManagedStacExtensions { get { - if (managedStacExtensions.Count == 0) InitManagedExtensions(); - return managedStacExtensions; + if (ManagedStacExtensionsDic.Count == 0) + { + InitManagedExtensions(); + } + + return ManagedStacExtensionsDic; } - private set => managedStacExtensions = value; + private set => ManagedStacExtensionsDic = value; } /// @@ -35,33 +43,37 @@ public static Dictionary ManagedStacExtensions /// public static void InitManagedExtensions() { - lock (initLock) + lock (InitLock) { - managedStacExtensions.Clear(); - managedStacExtensions.Add(Eo.EoStacExtension.JsonSchemaUrl, typeof(Eo.EoStacExtension)); - managedStacExtensions.Add("eo", typeof(Eo.EoStacExtension)); - managedStacExtensions.Add(Processing.ProcessingStacExtension.JsonSchemaUrl, typeof(Processing.ProcessingStacExtension)); - managedStacExtensions.Add("processing", typeof(Processing.ProcessingStacExtension)); - managedStacExtensions.Add(Projection.ProjectionStacExtension.JsonSchemaUrl, typeof(Projection.ProjectionStacExtension)); - managedStacExtensions.Add("projection", typeof(Projection.ProjectionStacExtension)); - managedStacExtensions.Add(Raster.RasterStacExtension.JsonSchemaUrl, typeof(Raster.RasterStacExtension)); - managedStacExtensions.Add(Sar.SarStacExtension.JsonSchemaUrl, typeof(Sar.SarStacExtension)); - managedStacExtensions.Add("sar", typeof(Sar.SarStacExtension)); - managedStacExtensions.Add(Sat.SatStacExtension.JsonSchemaUrl, typeof(Sat.SatStacExtension)); - managedStacExtensions.Add("sat", typeof(Sat.SatStacExtension)); - managedStacExtensions.Add(View.ViewStacExtension.JsonSchemaUrl, typeof(View.ViewStacExtension)); - managedStacExtensions.Add("view", typeof(View.ViewStacExtension)); + ManagedStacExtensionsDic.Clear(); + ManagedStacExtensionsDic.Add(Eo.EoStacExtension.JsonSchemaUrl, typeof(Eo.EoStacExtension)); + ManagedStacExtensionsDic.Add("eo", typeof(Eo.EoStacExtension)); + ManagedStacExtensionsDic.Add(Processing.ProcessingStacExtension.JsonSchemaUrl, typeof(Processing.ProcessingStacExtension)); + ManagedStacExtensionsDic.Add("processing", typeof(Processing.ProcessingStacExtension)); + ManagedStacExtensionsDic.Add(Projection.ProjectionStacExtension.JsonSchemaUrl, typeof(Projection.ProjectionStacExtension)); + ManagedStacExtensionsDic.Add("projection", typeof(Projection.ProjectionStacExtension)); + ManagedStacExtensionsDic.Add(Raster.RasterStacExtension.JsonSchemaUrl, typeof(Raster.RasterStacExtension)); + ManagedStacExtensionsDic.Add(Sar.SarStacExtension.JsonSchemaUrl, typeof(Sar.SarStacExtension)); + ManagedStacExtensionsDic.Add("sar", typeof(Sar.SarStacExtension)); + ManagedStacExtensionsDic.Add(Sat.SatStacExtension.JsonSchemaUrl, typeof(Sat.SatStacExtension)); + ManagedStacExtensionsDic.Add("sat", typeof(Sat.SatStacExtension)); + ManagedStacExtensionsDic.Add(View.ViewStacExtension.JsonSchemaUrl, typeof(View.ViewStacExtension)); + ManagedStacExtensionsDic.Add("view", typeof(View.ViewStacExtension)); } } /// /// Get the declared extensions for a specific stac properties container /// - /// - /// + /// The stac properties container + /// Collection of extensions public static IEnumerable GetDeclaredExtensions(this IStacPropertiesContainer stacPropertiesContainer) { - if (ManagedStacExtensions.Count == 0) InitManagedExtensions(); + if (ManagedStacExtensions.Count == 0) + { + InitManagedExtensions(); + } + return stacPropertiesContainer.StacObjectContainer.StacExtensions .Select(stacExtension => LoadStacExtension(stacExtension, stacPropertiesContainer.StacObjectContainer)); } @@ -76,14 +88,20 @@ private static IStacExtension LoadStacExtension(string stacExtension, IStacObjec { return Activator.CreateInstance(ManagedStacExtensions[stacExtension], flags, null, new object[1] { stacObject }, culture) as IStacExtension; } - catch { } + catch + { + } } Uri schema = null; if (Uri.IsWellFormedUriString(stacExtension, UriKind.Absolute)) + { schema = new Uri(stacExtension); + } else + { schema = new Uri($"https://stac-extensions.github.io/{stacExtension}/v1.0.0/schema.json"); + } return new SchemaBasedStacExtension(schema, stacObject); } diff --git a/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs b/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs index ed22ca70..31c48543 100644 --- a/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs +++ b/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs @@ -1,13 +1,11 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacPropertiesContainerExtension.cs + +using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json.Schema; using Stac.Collection; -using Stac.Exceptions; - -public delegate IStacSummaryItem CreateSummary(IEnumerable arg); namespace Stac.Extensions { @@ -19,106 +17,158 @@ namespace Stac.Extensions /// public abstract class StacPropertiesContainerExtension : IStacExtension { - private readonly string identifier; + private readonly string _identifier; /// - /// Initialize a new class for a STAC object implementing . + /// Initializes a new instance of the class. /// /// Identifier of the extension /// STAC object protected StacPropertiesContainerExtension(string identifier, IStacPropertiesContainer stacPropertiesContainer) { - this.identifier = identifier; - StacPropertiesContainer = stacPropertiesContainer; + this._identifier = identifier; + this.StacPropertiesContainer = stacPropertiesContainer; } /// - /// Identifier of the extension + /// Gets identifier of the extension /// - public virtual string Identifier => identifier; + /// + /// Identifier of the extension + /// + public virtual string Identifier => this._identifier; /// - /// Stac Object extended by the extension + /// Gets stac Object extended by the extension /// + /// + /// Stac Object extended by the extension + /// public IStacPropertiesContainer StacPropertiesContainer { get; private set; } /// - /// Get the potential fields of the extensions and their type + /// Gets get the potential fields of the extensions and their type /// + /// + /// Get the potential fields of the extensions and their type + /// public abstract IDictionary ItemFields { get; } /// + /// Gets a value indicating whether indicate if the extension is already declared + /// + /// /// Indicate if the extension is already declared + /// + public bool IsDeclared => this.StacPropertiesContainer.GetDeclaredExtensions().Any(e => e.Identifier == this.Identifier); + + /// + /// Generic method to summarize in a range any ordinal object + /// + /// ordinal object + /// Type of the object + /// Range summary object + public static IStacSummaryItem CreateRangeSummaryObject(IEnumerable arg) + { + return new StacSummaryRangeObject(arg.Min(), arg.Max()); + } + + /// + /// Generic method to summarize in a value set an array of object /// - public bool IsDeclared => StacPropertiesContainer.GetDeclaredExtensions().Any(e => e.Identifier == Identifier); + /// array of object + /// Type of the object + /// Value set summary object + public static StacSummaryValueSet CreateSummaryValueSet(IEnumerable arg) + { + return new StacSummaryValueSet(arg.Distinct()); + } /// /// Get he potential summary functions for each field that can be summarized /// - /// + /// Dictionary of summary functions public virtual IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); - foreach (var itemField in ItemFields) + foreach (var itemField in this.ItemFields) { if (itemField.Value == typeof(bool)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateSummaryValueSet)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateSummaryValueSet)); + } else if (itemField.Value == typeof(short)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else if (itemField.Value == typeof(int)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else if (itemField.Value == typeof(long)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else if (itemField.Value == typeof(float)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else if (itemField.Value == typeof(double)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else if (itemField.Value == typeof(DateTime)) - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateRangeSummaryObject)); + } else - summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateSummaryValueSet)); + { + summaryFunctions.Add(itemField.Key, new SummaryFunction(this, itemField.Key, CreateSummaryValueSet)); + } } + return summaryFunctions; } /// - /// Generic method to summarize in a range any ordinal object + /// Set a property in the container /// - /// ordinal object - public static IStacSummaryItem CreateRangeSummaryObject(IEnumerable arg) + /// Key of the property + /// Value of the property + public void SetProperty(string key, object value) { - return new StacSummaryRangeObject(arg.Min(), arg.Max()); + this.SetProperty(key, value); + this.DeclareStacExtension(); } /// - /// Generic method to summarize in a value set an array of object + /// Remove a property in the container /// - /// - /// - public static StacSummaryValueSet CreateSummaryValueSet(IEnumerable arg) + /// Key of the property + public void RemoveProperty(string key) { - return new StacSummaryValueSet(arg.Distinct()); + this.RemoveProperty(key); + if (!this.StacPropertiesContainer.Properties.Any(p => this.ItemFields.ContainsKey(p.Key))) + { + this.RemoveStacExtension(); + } } - /// - /// Generic method to summarize in a value set an array of array - /// - /// an array - /// - // internal static IStacSummaryItem CreateSummaryValueSetFromArrays(IEnumerable arg) - // { - // return new StacSummaryValueSet(arg.SelectMany(a => a as IEnumerable).Distinct()); - // } - /// /// Declares the extension in the STAC object /// protected void DeclareStacExtension() { - if (StacPropertiesContainer.StacObjectContainer == null) return; - if (!StacPropertiesContainer.StacObjectContainer.StacExtensions.Contains(Identifier)) - StacPropertiesContainer.StacObjectContainer.StacExtensions.Add(Identifier); + if (this.StacPropertiesContainer.StacObjectContainer == null) + { + return; + } + + if (!this.StacPropertiesContainer.StacObjectContainer.StacExtensions.Contains(this.Identifier)) + { + this.StacPropertiesContainer.StacObjectContainer.StacExtensions.Add(this.Identifier); + } } /// @@ -126,22 +176,15 @@ protected void DeclareStacExtension() /// protected void RemoveStacExtension() { - if (StacPropertiesContainer.StacObjectContainer == null) return; - if (StacPropertiesContainer.StacObjectContainer.StacExtensions.Contains(Identifier)) - StacPropertiesContainer.StacObjectContainer.StacExtensions.Remove(Identifier); - } - - public void SetProperty(string key, object value) - { - this.SetProperty(key, value); - DeclareStacExtension(); - } + if (this.StacPropertiesContainer.StacObjectContainer == null) + { + return; + } - public void RemoveProperty(string key) - { - this.RemoveProperty(key); - if (!StacPropertiesContainer.Properties.Any(p => ItemFields.ContainsKey(p.Key))) - RemoveStacExtension(); + if (this.StacPropertiesContainer.StacObjectContainer.StacExtensions.Contains(this.Identifier)) + { + this.StacPropertiesContainer.StacObjectContainer.StacExtensions.Remove(this.Identifier); + } } } -} +} diff --git a/src/DotNetStac/Extensions/Storage/StorageStacExtension.cs b/src/DotNetStac/Extensions/Storage/StorageStacExtension.cs index 4bfd7270..b42c1ba7 100644 --- a/src/DotNetStac/Extensions/Storage/StorageStacExtension.cs +++ b/src/DotNetStac/Extensions/Storage/StorageStacExtension.cs @@ -1,13 +1,9 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StorageStacExtension.cs + +using System; using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Security.Cryptography; -using System.Threading.Tasks; -using Multiformats.Base; -using Multiformats.Hash; -using Multiformats.Hash.Algorithms; -using Stac.Model; namespace Stac.Extensions.Storage { @@ -16,97 +12,122 @@ namespace Stac.Extensions.Storage /// public class StorageStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Elements should be documented public const string JsonSchemaUrl = "https://stac-extensions.github.io/storage/v1.0.0/schema.json"; public const string PlatformField = "storage:platform"; public const string RegionField = "storage:region"; public const string RequesterPaysField = "storage:requester_pays"; public const string TierField = "storage:tier"; - private readonly Dictionary itemFields; +#pragma warning restore CS1591 // Elements should be documented + private readonly Dictionary _itemFields; - internal StorageStacExtension(IStacPropertiesContainer stacObject) : base(JsonSchemaUrl, stacObject) + /// + /// Initializes a new instance of the class. + /// + /// The stac object. + internal StorageStacExtension(IStacPropertiesContainer stacObject) + : base(JsonSchemaUrl, stacObject) { - itemFields = new Dictionary(); - itemFields.Add(PlatformField, typeof(string)); - itemFields.Add(RegionField, typeof(string)); - itemFields.Add(RequesterPaysField, typeof(bool)); - itemFields.Add(TierField, typeof(string)); + this._itemFields = new Dictionary(); + this._itemFields.Add(PlatformField, typeof(string)); + this._itemFields.Add(RegionField, typeof(string)); + this._itemFields.Add(RequesterPaysField, typeof(bool)); + this._itemFields.Add(TierField, typeof(string)); } /// - /// The cloud provider where data is stored + /// Gets or sets the cloud provider where data is stored /// - /// + /// + /// The cloud provider where data is stored + /// public string Platform { - get { return StacPropertiesContainer.GetProperty(PlatformField); } - set { StacPropertiesContainer.SetProperty(PlatformField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(PlatformField); + } + + set + { + this.StacPropertiesContainer.SetProperty(PlatformField, value); + this.DeclareStacExtension(); + } } /// - /// The region where the data is stored. Relevant to speed of access and inter region egress costs (as defined by PaaS provider) + /// Gets or sets the region where the data is stored. Relevant to speed of access and inter region egress costs (as defined by PaaS provider) /// - /// + /// + /// The region where the data is stored. Relevant to speed of access and inter region egress costs (as defined by PaaS provider) + /// public string Region { - get { return StacPropertiesContainer.GetProperty(RegionField); } - set { StacPropertiesContainer.SetProperty(RegionField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(RegionField); + } + + set + { + this.StacPropertiesContainer.SetProperty(RegionField, value); + this.DeclareStacExtension(); + } } /// - /// Is the data requester pays or is it data manager/cloud provider pays. Defaults to false + /// Gets or sets is the data requester pays or is it data manager/cloud provider pays. Defaults to false /// - /// + /// + /// Is the data requester pays or is it data manager/cloud provider pays. Defaults to false + /// public bool? RequesterPays { - get { return StacPropertiesContainer.GetProperty(RequesterPaysField); } - set { StacPropertiesContainer.SetProperty(RequesterPaysField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(RequesterPaysField); + } + + set + { + this.StacPropertiesContainer.SetProperty(RequesterPaysField, value); + this.DeclareStacExtension(); + } } /// - /// The title for the tier type (as defined by PaaS provider) + /// Gets or sets the title for the tier type (as defined by PaaS provider) /// - /// + /// + /// The title for the tier type (as defined by PaaS provider) + /// public string Tier { - get { return StacPropertiesContainer.GetProperty(TierField); } - set { StacPropertiesContainer.SetProperty(TierField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(TierField); + } + + set + { + this.StacPropertiesContainer.SetProperty(TierField, value); + this.DeclareStacExtension(); + } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; - + /// + /// Potential fields and their types + /// + public override IDictionary ItemFields => this._itemFields; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } - - } - - /// - /// Extension methods for accessing Storage extension - /// - public static class StorageStacExtensionExtensions - { - /// - /// Initilize a StorageStacExtension class from a STAC Asset - /// - public static StorageStacExtension StorageExtension(this StacAsset stacAsset) - { - return new StorageStacExtension(stacAsset); - } - - /// - /// Initilize a StorageStacExtension class from a STAC Item - /// - public static StorageStacExtension StorageExtension(this StacItem stacItem) - { - return new StorageStacExtension(stacItem); - } - } } diff --git a/src/DotNetStac/Extensions/Storage/StorageStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Storage/StorageStacExtensionExtensions.cs new file mode 100644 index 00000000..dc3154db --- /dev/null +++ b/src/DotNetStac/Extensions/Storage/StorageStacExtensionExtensions.cs @@ -0,0 +1,32 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StorageStacExtensionExtensions.cs + +namespace Stac.Extensions.Storage +{ + /// + /// Extension methods for accessing Storage extension + /// + public static class StorageStacExtensionExtensions + { + /// + /// Get StorageStacExtension class from a STAC Asset + /// + /// The STAC Asset + /// The StorageStacExtension class + public static StorageStacExtension StorageExtension(this StacAsset stacAsset) + { + return new StorageStacExtension(stacAsset); + } + + /// + /// Get StorageStacExtension class from a STAC Item + /// + /// The STAC Item + /// The StorageStacExtension class + public static StorageStacExtension StorageExtension(this StacItem stacItem) + { + return new StorageStacExtension(stacItem); + } + } +} diff --git a/src/DotNetStac/Extensions/SummaryFunction.cs b/src/DotNetStac/Extensions/SummaryFunction.cs index b5c6c91e..ba6cb443 100644 --- a/src/DotNetStac/Extensions/SummaryFunction.cs +++ b/src/DotNetStac/Extensions/SummaryFunction.cs @@ -1,4 +1,8 @@ -using System.Collections; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SummaryFunction.cs + +using System.Collections; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json.Linq; @@ -6,22 +10,45 @@ namespace Stac.Extensions { +#pragma warning disable SA1649 // File name should match first type name + /// + /// Defines a function that creates a summary item from a collection of items. + /// + /// The type of the items. public class SummaryFunction : ISummaryFunction { + private readonly CreateSummary _summaryFunction; + + /// + /// Initializes a new instance of the class. + /// + /// The Stac Extension associated to the summary function. + /// The PropertyName of the summary function. + /// The summary function. + public SummaryFunction(IStacExtension extension, string propertyName, CreateSummary summaryFunction) + { + this.Extension = extension; + this.PropertyName = propertyName; + this._summaryFunction = summaryFunction; + } + + /// public IStacExtension Extension { get; } + /// public string PropertyName { get; } - private CreateSummary summaryFunction; - + /// public IStacSummaryItem Summarize(IEnumerable items) { - return summaryFunction(items.SelectMany(i => + return this._summaryFunction(items.SelectMany(i => { try { if (i is JArray) + { return (i as IEnumerable).OfType().Select(i2 => StacAccessorsHelpers.ChangeType(i2)); + } return new T[] { StacAccessorsHelpers.ChangeType(i) }; } @@ -31,12 +58,6 @@ public IStacSummaryItem Summarize(IEnumerable items) } })); } - - public SummaryFunction(IStacExtension extension, string propertyName, CreateSummary summaryFunction) - { - Extension = extension; - PropertyName = propertyName; - this.summaryFunction = summaryFunction; - } } +#pragma warning restore SA1649 // File name should match first type name } diff --git a/src/DotNetStac/Extensions/Version/VersionStacExtension.cs b/src/DotNetStac/Extensions/Version/VersionStacExtension.cs index 0ae87eab..b0a1127a 100644 --- a/src/DotNetStac/Extensions/Version/VersionStacExtension.cs +++ b/src/DotNetStac/Extensions/Version/VersionStacExtension.cs @@ -1,6 +1,9 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VersionStacExtension.cs + +using System; using System.Collections.Generic; -using System.Linq; namespace Stac.Extensions.Version { @@ -9,153 +12,83 @@ namespace Stac.Extensions.Version /// public class VersionStacExtension : StacPropertiesContainerExtension, IStacExtension { - - /// Extension identifier and schema url +#pragma warning disable CS1591 // Elements should be documented public const string JsonSchemaUrl = "https://stac-extensions.github.io/version/v1.0.0/schema.json"; - internal const string VersionField = "version"; - internal const string DeprecatedField = "deprecated"; + public const string VersionField = "version"; + public const string DeprecatedField = "deprecated"; - internal const string PredecessorVersionRel = "predecessor-version"; + public const string PredecessorVersionRel = "predecessor-version"; - internal const string SuccessorVersionRel = "predecessor-version"; + public const string SuccessorVersionRel = "predecessor-version"; - internal const string LatestVersionRel = "predecessor-version"; + public const string LatestVersionRel = "predecessor-version"; - private readonly Dictionary itemFields; +#pragma warning disable CS1591 // Elements should be documented - internal VersionStacExtension(IStacObject stacObject) : base(JsonSchemaUrl, stacObject) + private readonly Dictionary _itemFields; + + internal VersionStacExtension(IStacObject stacObject) + : base(JsonSchemaUrl, stacObject) { - itemFields = new Dictionary(); - itemFields.Add(VersionField, typeof(string)); - itemFields.Add(DeprecatedField, typeof(bool)); + this._itemFields = new Dictionary(); + this._itemFields.Add(VersionField, typeof(string)); + this._itemFields.Add(DeprecatedField, typeof(bool)); } /// - /// Version of the Collection or Item. + /// Gets or sets version of the Collection or Item. /// - /// + /// + /// Version of the Collection or Item. + /// public string Version { - get { return StacPropertiesContainer.GetProperty(VersionField); } - set { StacPropertiesContainer.SetProperty(VersionField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(VersionField); + } + + set + { + this.StacPropertiesContainer.SetProperty(VersionField, value); + this.DeclareStacExtension(); + } } /// - /// Specifies that the Collection or Item is deprecated with the potential to be removed. + /// Gets or sets a value indicating whether specifies that the Collection or Item is deprecated with the potential to be removed. /// - /// + /// + /// A value indicating whether specifies that the Collection or Item is deprecated with the potential to be removed. + /// public bool Deprecated { - get { return StacPropertiesContainer.GetProperty(DeprecatedField); } - set { StacPropertiesContainer.SetProperty(DeprecatedField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(DeprecatedField); + } + + set + { + this.StacPropertiesContainer.SetProperty(DeprecatedField, value); + this.DeclareStacExtension(); + } } /// - /// Potential fields and their types + /// Gets potential fields and their types /// - public override IDictionary ItemFields => itemFields; + /// + /// Potential fields and their types + /// + public override IDictionary ItemFields => this._itemFields; + /// public override IDictionary GetSummaryFunctions() { Dictionary summaryFunctions = new Dictionary(); return summaryFunctions; } - - } - - /// - /// Extension methods for accessing EO extension - /// - public static class VersionStacExtensionExtensions - { - /// - /// Initilize a EoStacExtension class from a STAC item - /// - public static VersionStacExtension VersionExtension(this StacItem stacItem) - { - return new VersionStacExtension(stacItem); - } - - /// - /// Initilize a EoStacExtension class from a STAC collection - /// - public static VersionStacExtension VersionExtension(this StacCollection stacItem) - { - return new VersionStacExtension(stacItem); - } - - /// - /// Retrieve the predecessor version of the Stac Item if any - /// - /// current Stac Item - /// Function that read a Stac Link to get the StacItem - /// null if no precedessor version - public static StacItem PredecessorVersion(this StacItem stacItem, Func stacLinkResolver) - { - return GetVersion(stacItem, VersionStacExtension.PredecessorVersionRel, stacLinkResolver); - } - - /// - /// Retrieve the predecessor version of the Stac Collection if any - /// - /// current Stac Collection - /// Function that read a Stac Link to get the StacItem - /// null if no precedessor version - public static StacCollection PredecessorVersion(this StacCollection stacCollection, Func stacLinkResolver) - { - return GetVersion(stacCollection, VersionStacExtension.PredecessorVersionRel, stacLinkResolver); - } - - /// - /// Retrieve the successor version of the Stac Item if any - /// - /// current Stac Item - /// Function that read a Stac Link to get the StacItem - /// null if no successor version - public static StacItem SuccessorVersion(this StacItem stacItem, Func stacLinkResolver) - { - return GetVersion(stacItem, VersionStacExtension.SuccessorVersionRel, stacLinkResolver); - } - - /// - /// Retrieve the successor version of the Stac Collection if any - /// - /// current Stac Collection - /// Function that read a Stac Link to get the StacItem - /// null if no successor version - public static StacCollection SuccessorVersion(this StacCollection stacCollection, Func stacLinkResolver) - { - return GetVersion(stacCollection, VersionStacExtension.SuccessorVersionRel, stacLinkResolver); - } - - /// - /// Retrieve the latest version of the Stac Item if any - /// - /// current Stac Item - /// Function that read a Stac Link to get the StacItem - /// null if no latest version - public static StacItem LatestVersion(this StacItem stacItem, Func stacLinkResolver) - { - return GetVersion(stacItem, VersionStacExtension.LatestVersionRel, stacLinkResolver); - } - - /// - /// Retrieve the latest version of the Stac Collection if any - /// - /// current Stac Collection - /// Function that read a Stac Link to get the StacItem - /// null if no latest version - public static StacCollection LatestVersion(this StacCollection stacCollection, Func stacLinkResolver) - { - return GetVersion(stacCollection, VersionStacExtension.LatestVersionRel, stacLinkResolver); - } - - internal static T GetVersion(this T stacObject, string relType, Func stacLinkResolver) where T : IStacObject - { - var predecessorVersionLink = stacObject.Links.FirstOrDefault(l => l.RelationshipType == relType); - if (predecessorVersionLink == null) return default(T); - return stacLinkResolver(predecessorVersionLink); - } } } diff --git a/src/DotNetStac/Extensions/Version/VersionStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Version/VersionStacExtensionExtensions.cs new file mode 100644 index 00000000..a2a40239 --- /dev/null +++ b/src/DotNetStac/Extensions/Version/VersionStacExtensionExtensions.cs @@ -0,0 +1,113 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VersionStacExtensionExtensions.cs + +using System; +using System.Linq; + +namespace Stac.Extensions.Version +{ + /// + /// Extension methods for accessing EO extension + /// + public static class VersionStacExtensionExtensions + { + /// + /// Initilize a VersionStacExtension class from a STAC item + /// + /// The STAC item + /// The VersionStacExtension class + public static VersionStacExtension VersionExtension(this StacItem stacItem) + { + return new VersionStacExtension(stacItem); + } + + /// + /// Initilize a VersionStacExtension class from a STAC collection + /// + /// The STAC collection + /// The VersionStacExtension class + public static VersionStacExtension VersionExtension(this StacCollection stacCollection) + { + return new VersionStacExtension(stacCollection); + } + + /// + /// Retrieve the predecessor version of the Stac Item if any + /// + /// current Stac Item + /// Function that read a Stac Link to get the StacItem + /// null if no precedessor version + public static StacItem PredecessorVersion(this StacItem stacItem, Func stacLinkResolver) + { + return GetVersion(stacItem, VersionStacExtension.PredecessorVersionRel, stacLinkResolver); + } + + /// + /// Retrieve the predecessor version of the Stac Collection if any + /// + /// current Stac Collection + /// Function that read a Stac Link to get the StacItem + /// null if no precedessor version + public static StacCollection PredecessorVersion(this StacCollection stacCollection, Func stacLinkResolver) + { + return GetVersion(stacCollection, VersionStacExtension.PredecessorVersionRel, stacLinkResolver); + } + + /// + /// Retrieve the successor version of the Stac Item if any + /// + /// current Stac Item + /// Function that read a Stac Link to get the StacItem + /// null if no successor version + public static StacItem SuccessorVersion(this StacItem stacItem, Func stacLinkResolver) + { + return GetVersion(stacItem, VersionStacExtension.SuccessorVersionRel, stacLinkResolver); + } + + /// + /// Retrieve the successor version of the Stac Collection if any + /// + /// current Stac Collection + /// Function that read a Stac Link to get the StacItem + /// null if no successor version + public static StacCollection SuccessorVersion(this StacCollection stacCollection, Func stacLinkResolver) + { + return GetVersion(stacCollection, VersionStacExtension.SuccessorVersionRel, stacLinkResolver); + } + + /// + /// Retrieve the latest version of the Stac Item if any + /// + /// current Stac Item + /// Function that read a Stac Link to get the StacItem + /// null if no latest version + public static StacItem LatestVersion(this StacItem stacItem, Func stacLinkResolver) + { + return GetVersion(stacItem, VersionStacExtension.LatestVersionRel, stacLinkResolver); + } + + /// + /// Retrieve the latest version of the Stac Collection if any + /// + /// current Stac Collection + /// Function that read a Stac Link to get the StacItem + /// null if no latest version + public static StacCollection LatestVersion(this StacCollection stacCollection, Func stacLinkResolver) + { + return GetVersion(stacCollection, VersionStacExtension.LatestVersionRel, stacLinkResolver); + } + + internal static T GetVersion(this T stacObject, string relType, Func stacLinkResolver) + where T : IStacObject + { + var predecessorVersionLink = stacObject.Links.FirstOrDefault(l => l.RelationshipType == relType); + if (predecessorVersionLink == null) + { + return default(T); + } + + return stacLinkResolver(predecessorVersionLink); + } + } +} diff --git a/src/DotNetStac/Extensions/View/ViewStacExtension.cs b/src/DotNetStac/Extensions/View/ViewStacExtension.cs index bb361b28..22b477ce 100644 --- a/src/DotNetStac/Extensions/View/ViewStacExtension.cs +++ b/src/DotNetStac/Extensions/View/ViewStacExtension.cs @@ -1,68 +1,140 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ViewStacExtension.cs + +using System; using System.Collections.Generic; namespace Stac.Extensions.View { + /// + /// View extension + /// public class ViewStacExtension : StacPropertiesContainerExtension, IStacExtension { - +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/view/v1.0.0/schema.json"; - private readonly Dictionary itemFields; - public static string OffNadirField => "view:off_nadir"; - public static string IncidenceAngleField => "view:incidence_angle"; - public static string AzimuthField => "view:azimuth"; - public static string SunAzimuthField => "view:sun_azimuth"; - public static string SunElevationField => "view:sun_elevation"; + public const string OffNadirField = "view:off_nadir"; + + public const string IncidenceAngleField = "view:incidence_angle"; + + public const string AzimuthField = "view:azimuth"; + + public const string SunAzimuthField = "view:sun_azimuth"; - public ViewStacExtension(IStacObject stacObject) : base(JsonSchemaUrl, stacObject) + public const string SunElevationField = "view:sun_elevation"; + +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + private readonly Dictionary _itemFields; + + /// + /// Initializes a new instance of the class. + /// + /// The stac object. + public ViewStacExtension(IStacObject stacObject) + : base(JsonSchemaUrl, stacObject) { - itemFields = new Dictionary(); - itemFields.Add(OffNadirField, typeof(double)); - itemFields.Add(IncidenceAngleField, typeof(double)); - itemFields.Add(AzimuthField, typeof(double)); - itemFields.Add(SunAzimuthField, typeof(double)); - itemFields.Add(SunElevationField, typeof(double)); + this._itemFields = new Dictionary(); + this._itemFields.Add(OffNadirField, typeof(double)); + this._itemFields.Add(IncidenceAngleField, typeof(double)); + this._itemFields.Add(AzimuthField, typeof(double)); + this._itemFields.Add(SunAzimuthField, typeof(double)); + this._itemFields.Add(SunElevationField, typeof(double)); } + /// + /// Gets or sets the off nadir angle. + /// The angle between the local surface normal and the satellite's nadir direction. + /// public double OffNadir { - get { return StacPropertiesContainer.GetProperty(OffNadirField); } - set { StacPropertiesContainer.SetProperty(OffNadirField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(OffNadirField); + } + + set + { + this.StacPropertiesContainer.SetProperty(OffNadirField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the incidence angle. + /// The angle between the local surface normal and the line of sight to the satellite. + /// public double IncidenceAngle { - get { return StacPropertiesContainer.GetProperty(IncidenceAngleField); } - set { StacPropertiesContainer.SetProperty(IncidenceAngleField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(IncidenceAngleField); + } + + set + { + this.StacPropertiesContainer.SetProperty(IncidenceAngleField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the azimuth angle. + /// The angle angle between a satellite and the North which is measured clockwise + /// public double Azimuth { - get { return StacPropertiesContainer.GetProperty(AzimuthField); } - set { StacPropertiesContainer.SetProperty(AzimuthField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(AzimuthField); + } + + set + { + this.StacPropertiesContainer.SetProperty(AzimuthField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the sun azimuth angle. + /// The angle between the sun and the North which is measured clockwise + /// public double SunAzimuth { - get { return StacPropertiesContainer.GetProperty(SunAzimuthField); } - set { StacPropertiesContainer.SetProperty(SunAzimuthField, value); DeclareStacExtension(); } + get + { + return this.StacPropertiesContainer.GetProperty(SunAzimuthField); + } + + set + { + this.StacPropertiesContainer.SetProperty(SunAzimuthField, value); + this.DeclareStacExtension(); + } } + /// + /// Gets or sets the sun elevation angle. + /// The angle between the sun and the local surface normal + /// public double SunElevation { - get { return StacPropertiesContainer.GetProperty(SunElevationField); } - set { StacPropertiesContainer.SetProperty(SunElevationField, value); DeclareStacExtension(); } - } + get + { + return this.StacPropertiesContainer.GetProperty(SunElevationField); + } - public override IDictionary ItemFields => itemFields; - } - - public static class ViewStacExtensionExtensions - { - public static ViewStacExtension ViewExtension(this StacItem stacItem) - { - return new ViewStacExtension(stacItem); + set + { + this.StacPropertiesContainer.SetProperty(SunElevationField, value); + this.DeclareStacExtension(); + } } + + /// + public override IDictionary ItemFields => this._itemFields; } } diff --git a/src/DotNetStac/Extensions/View/ViewStacExtensionExtensions.cs b/src/DotNetStac/Extensions/View/ViewStacExtensionExtensions.cs new file mode 100644 index 00000000..d13f40f3 --- /dev/null +++ b/src/DotNetStac/Extensions/View/ViewStacExtensionExtensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ViewStacExtensionExtensions.cs + +namespace Stac.Extensions.View +{ + /// + /// Extension methods for accessing View extension + /// + public static class ViewStacExtensionExtensions + { + /// + /// Gets the View extension from a StacItem + /// + /// The StacItem + /// The View extension + public static ViewStacExtension ViewExtension(this StacItem stacItem) + { + return new ViewStacExtension(stacItem); + } + } +} diff --git a/src/DotNetStac/Extensions/VirtualAssets/VirtualAsset.cs b/src/DotNetStac/Extensions/VirtualAssets/VirtualAsset.cs index 3056300e..33bb3e1d 100644 --- a/src/DotNetStac/Extensions/VirtualAssets/VirtualAsset.cs +++ b/src/DotNetStac/Extensions/VirtualAssets/VirtualAsset.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VirtualAsset.cs + +using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; @@ -10,42 +14,25 @@ namespace Stac.Extensions.VirtualAssets /// public class VirtualAsset : StacAsset { - - #region Static members - - /// - /// Create a new Virtual Asset from assets defined in an existing stac item - /// - /// Stac Item to reference the assets from - /// keys of the assets to be referenced - /// new stac object container of the virtuals assets. If not specified, the stacItem is used - /// - public static VirtualAsset Create(StacItem stacItem, IList assetsKey, IStacObject newStacObject = null) - { - IStacObject parentObject = newStacObject ?? stacItem; - return new VirtualAsset(parentObject, stacItem.Assets.Select(asset => new Uri(asset.Value.Uri, "#" + asset.Key)).ToList()); - } - - #endregion - /// - /// Initialize a new Virtual Asset for a STAC object with an array of items + /// Initializes a new instance of the class. /// - /// - public VirtualAsset(IStacObject stacObject, IList uris) : base(stacObject, null) + /// The stac object. + /// The uris. + public VirtualAsset(IStacObject stacObject, IList uris) + : base(stacObject, null) { - Uris = uris; + this.Uris = uris; } /// - /// array of URIs to the assets object composing the virtual asset. Relative and absolute URI are both allowed + /// Gets array of URIs to the assets object composing the virtual asset. Relative and absolute URI are both allowed /// - /// [JsonProperty("href")] public IList Uris { get; private set; } /// - /// Do not use + /// Gets or sets do not use /// [JsonIgnore] public new Uri Uri @@ -54,7 +41,21 @@ public VirtualAsset(IStacObject stacObject, IList uris) : base(stacObject, set { } } + /// + /// Create a new Virtual Asset from assets defined in an existing stac item + /// + /// Stac Item to reference the assets from + /// keys of the assets to be referenced + /// new stac object container of the virtuals assets. If not specified, the stacItem is used + /// Virtual Asset + public static VirtualAsset Create(StacItem stacItem, IList assetsKey, IStacObject newStacObject = null) + { + IStacObject parentObject = newStacObject ?? stacItem; + return new VirtualAsset(parentObject, stacItem.Assets.Select(asset => new Uri(asset.Value.Uri, "#" + asset.Key)).ToList()); + } + #pragma warning disable 1591 public bool ShouldSerializeUri() => false; +#pragma warning restore 1591 } } diff --git a/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtension.cs b/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtension.cs index 56c69eda..562deda0 100644 --- a/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtension.cs +++ b/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtension.cs @@ -1,60 +1,51 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VirtualAssetsStacExtension.cs + +using System; using System.Collections.Generic; -using System.Linq; namespace Stac.Extensions.VirtualAssets { /// - /// Helper class to access the fields deined by the EO extension + /// Helper class to access the fields deined by the virtual assets extension /// public class VirtualAssetsStacExtension : StacPropertiesContainerExtension, IStacExtension { - /// Extension identifier and schema url +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string JsonSchemaUrl = "https://stac-extensions.github.io/virtual-assets/v1.0.0/schema.json"; - private static IDictionary itemFields; - private const string VirtualAssetsField = "virtual:assets"; + public const string VirtualAssetsField = "virtual:assets"; + +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + + private readonly IDictionary _itemFields; - internal VirtualAssetsStacExtension(IStacObject stacObject) : base(JsonSchemaUrl, stacObject) + internal VirtualAssetsStacExtension(IStacObject stacObject) + : base(JsonSchemaUrl, stacObject) { - itemFields = new Dictionary(); - itemFields.Add(VirtualAssetsField, typeof(VirtualAsset)); + this._itemFields = new Dictionary(); + this._itemFields.Add(VirtualAssetsField, typeof(VirtualAsset)); } /// - /// Virtual Assets + /// Gets or sets virtual Assets /// public IDictionary Assets { - get { return StacPropertiesContainer.GetProperty>(VirtualAssetsField); } - set { StacPropertiesContainer.SetProperty(VirtualAssetsField, value); DeclareStacExtension(); } - } + get + { + return this.StacPropertiesContainer.GetProperty>(VirtualAssetsField); + } - /// - /// Potential fields and their types - /// - public override IDictionary ItemFields => itemFields; - } - - /// - /// Extension methods for accessing EO extension - /// - public static class VirtualAssetsStacExtensionExtensions - { - /// - /// Initilize a VirtualAssetsStacExtension class from a STAC item - /// - public static VirtualAssetsStacExtension EoExtension(this StacItem stacItem) - { - return new VirtualAssetsStacExtension(stacItem); + set + { + this.StacPropertiesContainer.SetProperty(VirtualAssetsField, value); + this.DeclareStacExtension(); + } } - /// - /// Initilize a VirtualAssetsStacExtension class from a STAC collection - /// - public static VirtualAssetsStacExtension EoExtension(this StacCollection stacCollection) - { - return new VirtualAssetsStacExtension(stacCollection); - } + /// + public override IDictionary ItemFields => this._itemFields; } } diff --git a/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtensionExtensions.cs b/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtensionExtensions.cs new file mode 100644 index 00000000..3770660c --- /dev/null +++ b/src/DotNetStac/Extensions/VirtualAssets/VirtualAssetsStacExtensionExtensions.cs @@ -0,0 +1,32 @@ +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: VirtualAssetsStacExtensionExtensions.cs + +namespace Stac.Extensions.VirtualAssets +{ + /// + /// Extension methods for accessing VirtualAssets extension + /// + public static class VirtualAssetsStacExtensionExtensions + { + /// + /// Initilize a VirtualAssetsStacExtension class from a STAC item + /// + /// The STAC item + /// The VirtualAssetsStacExtension class + public static VirtualAssetsStacExtension EoExtension(this StacItem stacItem) + { + return new VirtualAssetsStacExtension(stacItem); + } + + /// + /// Initilize a VirtualAssetsStacExtension class from a STAC collection + /// + /// The STAC collection + /// The VirtualAssetsStacExtension class + public static VirtualAssetsStacExtension EoExtension(this StacCollection stacCollection) + { + return new VirtualAssetsStacExtension(stacCollection); + } + } +} diff --git a/src/DotNetStac/ILinksCollectionObject.cs b/src/DotNetStac/ILinksCollectionObject.cs index 8698e214..06bb4de5 100644 --- a/src/DotNetStac/ILinksCollectionObject.cs +++ b/src/DotNetStac/ILinksCollectionObject.cs @@ -1,9 +1,19 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ILinksCollectionObject.cs + +using System.Collections.Generic; namespace Stac { + /// + /// Interface for objects that have a collection of links + /// public interface ILinksCollectionObject { + /// + /// Gets the links. + /// ICollection Links { get; } } } diff --git a/src/DotNetStac/IStacCatalog.cs b/src/DotNetStac/IStacCatalog.cs index 3db9b7ce..c480d7b9 100644 --- a/src/DotNetStac/IStacCatalog.cs +++ b/src/DotNetStac/IStacCatalog.cs @@ -1,10 +1,13 @@ -namespace Stac +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacCatalog.cs + +namespace Stac { /// /// Common interface for all Stac catalogs (catalogs, collections) /// public interface IStacCatalog : IStacObject, IStacParent { - } } diff --git a/src/DotNetStac/IStacObject.cs b/src/DotNetStac/IStacObject.cs index 5c832dd9..f2cf9946 100644 --- a/src/DotNetStac/IStacObject.cs +++ b/src/DotNetStac/IStacObject.cs @@ -1,10 +1,10 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacObject.cs + using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Net.Mime; -using Newtonsoft.Json.Linq; using Semver; -using Stac.Extensions; namespace Stac { @@ -13,17 +13,34 @@ namespace Stac /// public interface IStacObject : IStacPropertiesContainer, ILinksCollectionObject { + /// + /// Gets the id of the object + /// string Id { get; } + /// + /// Gets the title of the object + /// string Title { get; } + /// + /// Gets the STAC version of the object + /// SemVersion StacVersion { get; } - ICollection Links { get; } + /// + /// Gets the description of the object + /// + new ICollection Links { get; } + /// + /// Gets the type of the object + /// ContentType MediaType { get; } + /// + /// Gets the STAC extensions of the object + /// ICollection StacExtensions { get; } - } } diff --git a/src/DotNetStac/IStacParent.cs b/src/DotNetStac/IStacParent.cs index 2adc6f71..768f50cc 100644 --- a/src/DotNetStac/IStacParent.cs +++ b/src/DotNetStac/IStacParent.cs @@ -1,10 +1,13 @@ -namespace Stac +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacParent.cs + +namespace Stac { /// /// Common interface for all Stac objects that can have children links /// public interface IStacParent : IStacObject { - } } diff --git a/src/DotNetStac/IStacPropertiesContainer.cs b/src/DotNetStac/IStacPropertiesContainer.cs index 6b355299..54b07259 100644 --- a/src/DotNetStac/IStacPropertiesContainer.cs +++ b/src/DotNetStac/IStacPropertiesContainer.cs @@ -1,9 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: IStacPropertiesContainer.cs + using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using Newtonsoft.Json.Linq; -using Stac.Extensions; namespace Stac { @@ -12,9 +11,14 @@ namespace Stac /// public interface IStacPropertiesContainer { + /// + /// Gets the properties. + /// IDictionary Properties { get; } + /// + /// Gets the StacObjectContainer. + /// IStacObject StacObjectContainer { get; } - } } diff --git a/src/DotNetStac/Model/ObservableDictionary.cs b/src/DotNetStac/Model/ObservableDictionary.cs index 8a5bcbd5..de9f83e7 100644 --- a/src/DotNetStac/Model/ObservableDictionary.cs +++ b/src/DotNetStac/Model/ObservableDictionary.cs @@ -1,15 +1,19 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: ObservableDictionary.cs + using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; -using System.Linq; using System.Threading; namespace Stac.Model { +#pragma warning disable SA1649 // File name should match first type name + /// /// Provides a thread-safe dictionary for use with data binding. /// @@ -24,18 +28,23 @@ public class ObservableDictionary : private readonly ConcurrentDictionary _dictionary; /// - /// Initializes an instance of the ObservableConcurrentDictionary class. + /// Initializes a new instance of the class. /// public ObservableDictionary() { - _context = AsyncOperationManager.SynchronizationContext; - _dictionary = new ConcurrentDictionary(); + this._context = AsyncOperationManager.SynchronizationContext; + this._dictionary = new ConcurrentDictionary(); } - public ObservableDictionary(IDictionary init) : this() + /// + /// Initializes a new instance of the class. + /// + /// The initial dictionary. + public ObservableDictionary(IDictionary init) + : this() { - _context = AsyncOperationManager.SynchronizationContext; - _dictionary = new ConcurrentDictionary(init); + this._context = AsyncOperationManager.SynchronizationContext; + this._dictionary = new ConcurrentDictionary(init); } /// Event raised when the collection changes. @@ -44,16 +53,88 @@ public ObservableDictionary(IDictionary init) : this() /// Event raised when a property on the collection changes. public event PropertyChangedEventHandler PropertyChanged; + int ICollection>.Count + { + get => this._dictionary.Count; + } + + bool ICollection>.IsReadOnly + { + get => ((ICollection>)this._dictionary).IsReadOnly; + } + + /// + public ICollection Keys + { + get { return this._dictionary.Keys; } + } + + /// + public ICollection Values + { + get => this._dictionary.Values; + } + + /// + public TValue this[TKey key] + { + get => this._dictionary[key]; + set => this.UpdateWithNotification(key, value); + } + + void ICollection>.Add(KeyValuePair item) + => this.TryAddWithNotification(item); + + void ICollection>.Clear() + { + this._dictionary.Clear(); + this.NotifyObserversOfChange(); + } + + bool ICollection>.Contains(KeyValuePair item) + => ((ICollection>)this._dictionary).Contains(item); + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)this._dictionary).CopyTo(array, arrayIndex); + + bool ICollection>.Remove(KeyValuePair item) + => this.TryRemoveWithNotification(item.Key, out TValue temp); + + IEnumerator> IEnumerable>.GetEnumerator() + => this._dictionary.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => this._dictionary.GetEnumerator(); + + // IDictionary Members + + /// + public void Add(TKey key, TValue value) + => this.TryAddWithNotification(key, value); + + /// + public bool ContainsKey(TKey key) + => this._dictionary.ContainsKey(key); + + /// + public bool Remove(TKey key) + => this.TryRemoveWithNotification(key, out TValue temp); + + /// + public bool TryGetValue(TKey key, out TValue value) + => this._dictionary.TryGetValue(key, out value); + /// /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary. /// private void NotifyObserversOfChange() { - var collectionHandler = CollectionChanged; - var propertyHandler = PropertyChanged; + var collectionHandler = this.CollectionChanged; + var propertyHandler = this.PropertyChanged; if (collectionHandler != null || propertyHandler != null) { - _context.Send(s => + this._context.Send( + s => { collectionHandler?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); propertyHandler?.Invoke(this, new PropertyChangedEventArgs("Count")); @@ -70,11 +151,12 @@ private void NotifyObserversOfChange() /// The item involved with the change private void NotifyObserversOfChange(NotifyCollectionChangedAction actionType, object changedItem) { - var collectionHandler = CollectionChanged; - var propertyHandler = PropertyChanged; + var collectionHandler = this.CollectionChanged; + var propertyHandler = this.PropertyChanged; if (collectionHandler != null || propertyHandler != null) { - _context.Send(s => + this._context.Send( + s => { collectionHandler?.Invoke(this, new NotifyCollectionChangedEventArgs(actionType, changedItem)); propertyHandler?.Invoke(this, new PropertyChangedEventArgs("Count")); @@ -92,11 +174,12 @@ private void NotifyObserversOfChange(NotifyCollectionChangedAction actionType, o /// The position of the item in the collection private void NotifyObserversOfChange(NotifyCollectionChangedAction actionType, object item, int index) { - var collectionHandler = CollectionChanged; - var propertyHandler = PropertyChanged; + var collectionHandler = this.CollectionChanged; + var propertyHandler = this.PropertyChanged; if (collectionHandler != null || propertyHandler != null) { - _context.Send(s => + this._context.Send( + s => { collectionHandler?.Invoke(this, new NotifyCollectionChangedEventArgs(actionType, item, index)); propertyHandler?.Invoke(this, new PropertyChangedEventArgs("Count")); @@ -110,7 +193,7 @@ private void NotifyObserversOfChange(NotifyCollectionChangedAction actionType, o /// The item to be added. /// Whether the add was successful. private bool TryAddWithNotification(KeyValuePair item) - => TryAddWithNotification(item.Key, item.Value); + => this.TryAddWithNotification(item.Key, item.Value); /// Attempts to add an item to the dictionary, notifying observers of any changes. /// The key of the item to be added. @@ -118,9 +201,13 @@ private bool TryAddWithNotification(KeyValuePair item) /// Whether the add was successful. private bool TryAddWithNotification(TKey key, TValue value) { - bool result = _dictionary.TryAdd(key, value); - int index = IndexOf(key); - if (result) NotifyObserversOfChange(NotifyCollectionChangedAction.Add, value, index); + bool result = this._dictionary.TryAdd(key, value); + int index = this.IndexOf(key); + if (result) + { + this.NotifyObserversOfChange(NotifyCollectionChangedAction.Add, value, index); + } + return result; } @@ -130,20 +217,23 @@ private bool TryAddWithNotification(TKey key, TValue value) /// Whether the removal was successful. private bool TryRemoveWithNotification(TKey key, out TValue value) { - int index = IndexOf(key); - bool result = _dictionary.TryRemove(key, out value); - if (result) NotifyObserversOfChange(NotifyCollectionChangedAction.Remove, value, index); + int index = this.IndexOf(key); + bool result = this._dictionary.TryRemove(key, out value); + if (result) + { + this.NotifyObserversOfChange(NotifyCollectionChangedAction.Remove, value, index); + } + return result; } /// Attempts to add or update an item in the dictionary, notifying observers of any changes. /// The key of the item to be updated. /// The new value to set for the item. - /// Whether the update was successful. private void UpdateWithNotification(TKey key, TValue value) { - _dictionary[key] = value; - NotifyObserversOfChange(NotifyCollectionChangedAction.Replace, value); + this._dictionary[key] = value; + this.NotifyObserversOfChange(NotifyCollectionChangedAction.Replace, value); } /// @@ -152,87 +242,21 @@ private void UpdateWithNotification(TKey key, TValue value) /// private int IndexOf(TKey key) { - var keys = _dictionary.Keys; + var keys = this._dictionary.Keys; int index = -1; foreach (TKey k in keys) { index++; - if (k.Equals(key)) return index; + if (k.Equals(key)) + { + return index; + } } - return -1; - } - - // ICollection> Members - - - void ICollection>.Add(KeyValuePair item) - => TryAddWithNotification(item); - - void ICollection>.Clear() - { - _dictionary.Clear(); - NotifyObserversOfChange(); - } - - bool ICollection>.Contains(KeyValuePair item) - => ((ICollection>)_dictionary).Contains(item); - - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - => ((ICollection>)_dictionary).CopyTo(array, arrayIndex); - - int ICollection>.Count - { - get => _dictionary.Count; - } - - bool ICollection>.IsReadOnly - { - get => ((ICollection>)_dictionary).IsReadOnly; - } - - bool ICollection>.Remove(KeyValuePair item) - => TryRemoveWithNotification(item.Key, out TValue temp); - - - // IEnumerable> Members - - IEnumerator> IEnumerable>.GetEnumerator() - => _dictionary.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() - => _dictionary.GetEnumerator(); - - - // IDictionary Members - - - public void Add(TKey key, TValue value) - => TryAddWithNotification(key, value); - - public bool ContainsKey(TKey key) - => _dictionary.ContainsKey(key); - - public ICollection Keys - { - get { return _dictionary.Keys; } + return -1; } + } - public bool Remove(TKey key) - => TryRemoveWithNotification(key, out TValue temp); +#pragma warning restore SA1649 // File name should match first type name - public bool TryGetValue(TKey key, out TValue value) - => _dictionary.TryGetValue(key, out value); - - public ICollection Values - { - get => _dictionary.Values; - } - - public TValue this[TKey key] - { - get => _dictionary[key]; - set => UpdateWithNotification(key, value); - } - } } diff --git a/src/DotNetStac/Preconditions.cs b/src/DotNetStac/Preconditions.cs index ca327d2a..9849bb72 100644 --- a/src/DotNetStac/Preconditions.cs +++ b/src/DotNetStac/Preconditions.cs @@ -1,19 +1,32 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Preconditions.cs + +using System; namespace Stac { + /// + /// A collection of methods to check preconditions. + /// public static class Preconditions { - public static T CheckNotNull(T value, string argName = null) where T : class + /// + /// Checks that the specified value is not null. + /// + /// The type of the value. + /// The value to check. + /// The name of the argument. + /// The value. + public static T CheckNotNull(T value, string argName = null) + where T : class { if (value == null) { throw new ArgumentNullException(argName); } + return value; } } - } diff --git a/src/DotNetStac/Schemas/StacSchemaResolver.cs b/src/DotNetStac/Schemas/StacSchemaResolver.cs index c4c0c9de..ebb627bf 100644 --- a/src/DotNetStac/Schemas/StacSchemaResolver.cs +++ b/src/DotNetStac/Schemas/StacSchemaResolver.cs @@ -1,28 +1,46 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacSchemaResolver.cs + +using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using Newtonsoft.Json; using Newtonsoft.Json.Schema; -using Stac.Extensions.ItemCollections; namespace Stac.Schemas { + /// + /// Stac Schema Resolver. + /// public class StacSchemaResolver { - private readonly JSchemaResolver jSchemaResolver; - private IDictionary schemaCompiled; + /// + /// Core types. + /// + public static readonly string[] CoreTypes = new string[] { "item", "catalog", "collection" }; + + private static readonly IDictionary SchemaMap = new Dictionary(); - public static string[] CoreTypes = new string[] { "item", "catalog", "collection" }; + private readonly JSchemaResolver _jsonSchemaResolver; + private readonly IDictionary _schemaCompiled; - public StacSchemaResolver(JSchemaResolver jSchemaResolver) + /// + /// Initializes a new instance of the class. + /// + /// Json schema resolver. + public StacSchemaResolver(JSchemaResolver jsonSchemaResolver) { - this.jSchemaResolver = jSchemaResolver; - this.schemaCompiled = new Dictionary(); + this._jsonSchemaResolver = jsonSchemaResolver; + this._schemaCompiled = new Dictionary(); } - private static IDictionary schemaMap = new Dictionary(); - + /// + /// Loads the schema from url or shortcut. + /// + /// Base url. + /// Version. + /// Shortcut. + /// The schema. public JSchema LoadSchema(string baseUrl = null, string version = null, string shortcut = null) { string vversion = string.IsNullOrEmpty(version) ? "unversioned" : "v" + version; @@ -32,14 +50,15 @@ public JSchema LoadSchema(string baseUrl = null, string version = null, string s baseUri = new Uri($"https://schemas.stacspec.org/{vversion}/"); } else + { baseUri = new Uri(baseUrl); + } Uri schemaUri = null; - bool isExtension = false; if (shortcut == "item" || shortcut == "catalog" || shortcut == "collection") + { schemaUri = new Uri(baseUri, $"{shortcut}-spec/json-schema/{shortcut}.json"); - else if (shortcut == "item-collection") - return ItemCollection.GenerateJSchema(version); + } else if (!string.IsNullOrEmpty(shortcut)) { if (shortcut == "proj") @@ -47,37 +66,38 @@ public JSchema LoadSchema(string baseUrl = null, string version = null, string s // Capture a very common mistake and give a better explanation (see #4) throw new Exception("'stac_extensions' must contain 'projection instead of 'proj'."); } + schemaUri = new Uri(baseUri, $"extensions/{shortcut}/json-schema/schema.json"); - isExtension = true; } else { schemaUri = baseUri; } - if (!string.IsNullOrEmpty(baseUrl) && schemaMap.ContainsKey(baseUrl)) + if (!string.IsNullOrEmpty(baseUrl) && SchemaMap.ContainsKey(baseUrl)) { - schemaUri = schemaMap[baseUrl]; + schemaUri = SchemaMap[baseUrl]; } - if (schemaCompiled.ContainsKey(schemaUri.ToString())) + if (this._schemaCompiled.ContainsKey(schemaUri.ToString())) { - return schemaCompiled[schemaUri.ToString()]; + return this._schemaCompiled[schemaUri.ToString()]; } else { Stream stream = null; try { - stream = jSchemaResolver.GetSchemaResource(null, new SchemaReference() { BaseUri = schemaUri }); + stream = this._jsonSchemaResolver.GetSchemaResource(null, new SchemaReference() { BaseUri = schemaUri }); } catch (Exception e) { - throw new Stac.Exceptions.InvalidStacSchemaException(string.Format("Error getting schema at Uri '{0}'", schemaUri), e); + throw new Exceptions.InvalidStacSchemaException(string.Format("Error getting schema at Uri '{0}'", schemaUri), e); } + var sr = new StreamReader(stream); - schemaCompiled[schemaUri.ToString()] = JSchema.Parse(sr.ReadToEnd(), jSchemaResolver); - return schemaCompiled[schemaUri.ToString()]; + this._schemaCompiled[schemaUri.ToString()] = JSchema.Parse(sr.ReadToEnd(), this._jsonSchemaResolver); + return this._schemaCompiled[schemaUri.ToString()]; } } } diff --git a/src/DotNetStac/Schemas/StacValidator.cs b/src/DotNetStac/Schemas/StacValidator.cs index e0f83532..8db21db3 100644 --- a/src/DotNetStac/Schemas/StacValidator.cs +++ b/src/DotNetStac/Schemas/StacValidator.cs @@ -1,48 +1,97 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacValidator.cs + +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net.Http; -using System.Reflection; -using System.Runtime.CompilerServices; using System.Text; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; using Stac.Exceptions; -using Stac.Extensions.ItemCollections; -using Stac.Schemas; namespace Stac.Schemas { + /// + /// Stac Validator. + /// public class StacValidator { - private StacSchemaResolver schemaResolver = null; + private readonly StacSchemaResolver _schemaResolver = null; - private Dictionary stacTypes = new Dictionary(); + private readonly Dictionary _stacTypes = new Dictionary(); - public StacValidator(JSchemaUrlResolver jSchemaUrlResolver) + /// + /// Initializes a new instance of the class. + /// + /// Json schema resolver. + public StacValidator(JSchemaUrlResolver jsonSchemaUrlResolver) { - this.schemaResolver = new StacSchemaResolver(jSchemaUrlResolver); - this.stacTypes.Add(typeof(StacItem), "item"); - this.stacTypes.Add(typeof(StacCatalog), "catalog"); - this.stacTypes.Add(typeof(StacCollection), "collection"); - this.stacTypes.Add(typeof(ItemCollection), "item-collection"); + this._schemaResolver = new StacSchemaResolver(jsonSchemaUrlResolver); + this._stacTypes.Add(typeof(StacItem), "item"); + this._stacTypes.Add(typeof(StacCatalog), "catalog"); + this._stacTypes.Add(typeof(StacCollection), "collection"); } /// /// Validate a json string against its STAC schema specification /// - /// + /// json string /// true when valid public bool ValidateJson(string jsonstr) { using (var reader = new JsonTextReader(new StringReader(jsonstr)) { DateTimeZoneHandling = DateTimeZoneHandling.Utc }) - DetectDuplicateKeys(reader); + { + this.DetectDuplicateKeys(reader); + } + JObject jobject; using (var reader = new JsonTextReader(new StringReader(jsonstr)) { DateTimeZoneHandling = DateTimeZoneHandling.Utc }) + { jobject = JObject.Load(reader); - return ValidateJObject(jobject); + } + + return this.ValidateJObject(jobject); + } + + internal static string FormatMessage(ValidationError validationError, string prefix) + { + StringBuilder message = new StringBuilder(); + message.Append(prefix); + if (validationError.LineNumber > 1 && validationError.LinePosition > 1) + { + message.AppendFormat("[{0},{1}]", validationError.LineNumber, validationError.LinePosition); + } + else + { + message.AppendFormat("[ROOT]"); + } + + if (!string.IsNullOrEmpty(validationError.Path)) + { + message.AppendFormat(" Path '{0}'", validationError.Path); + } + + message.Append(": "); + + message.Append(validationError.Message); + if (message[message.Length - 1] != '.') + { + message.Append('.'); + } + + if (validationError.ChildErrors != null && validationError.ChildErrors.Count > 0) + { + foreach (ValidationError childError in validationError.ChildErrors) + { + message.Append('\n' + prefix); + message.Append(FormatMessage(childError, prefix + " ")); + } + } + + return message.ToString(); } private bool DetectDuplicateKeys(JsonReader jobject) @@ -53,86 +102,64 @@ private bool DetectDuplicateKeys(JsonReader jobject) switch (jobject.TokenType) { case JsonToken.StartObject: - DetectDuplicateKeys(jobject); + this.DetectDuplicateKeys(jobject); break; case JsonToken.PropertyName: var propertyName = jobject.Value.ToString(); if (stack.Contains(propertyName)) + { throw new InvalidStacDataException($"Duplicate key {propertyName} found in JSON: " + jobject.Path); + } + stack.Push(propertyName); break; case JsonToken.EndObject: return true; } } + return true; } - private bool ValidateJObject(JObject jObject) + private bool ValidateJObject(JObject jsonObject) { - Type stacType = Utils.IdentifyStacType(jObject); + Type stacType = Utils.IdentifyStacType(jsonObject); // Get all schema to validate against - List schemas = new List() { stacTypes[stacType] }; - if (jObject.Value("stac_extensions") != null) - schemas.AddRange(jObject.Value("stac_extensions").Select(a => a.Value())); + List schemas = new List() { this._stacTypes[stacType] }; + if (jsonObject.Value("stac_extensions") != null) + { + schemas.AddRange(jsonObject.Value("stac_extensions").Select(a => a.Value())); + } foreach (var schema in schemas) { string shortcut = null, baseUrl = null; if (Uri.IsWellFormedUriString(schema, UriKind.Absolute)) + { baseUrl = schema; + } else + { shortcut = schema; + } - if (!jObject.ContainsKey("stac_version")) + if (!jsonObject.ContainsKey("stac_version")) + { throw new InvalidStacDataException("Missing 'stac_version' property"); + } - var jsonSchema = schemaResolver.LoadSchema(baseUrl: baseUrl, shortcut: shortcut, version: jObject["stac_version"].Value()); - if (jObject.IsValid(jsonSchema, out IList errorMessages)) + var jsonSchema = this._schemaResolver.LoadSchema(baseUrl: baseUrl, shortcut: shortcut, version: jsonObject["stac_version"].Value()); + if (jsonObject.IsValid(jsonSchema, out IList errorMessages)) + { continue; + } throw new InvalidStacDataException(schema + ":\n" + string.Join("\n", errorMessages. - Select(e => FormatMessage(e, "")))); - } - return true; - } - - internal static string FormatMessage(ValidationError validationError, string prefix) - { - StringBuilder message = new StringBuilder(); - message.Append(prefix); - if (validationError.LineNumber > 1 && validationError.LinePosition > 1) - { - message.AppendFormat("[{0},{1}]", validationError.LineNumber, validationError.LinePosition); - } - else - { - message.AppendFormat("[ROOT]"); - } - if (!string.IsNullOrEmpty(validationError.Path)) - { - message.AppendFormat(" Path '{0}'", validationError.Path); - } - - message.Append(": "); - - message.Append(validationError.Message); - if (message[message.Length - 1] != '.') - { - message.Append('.'); - } - - if (validationError.ChildErrors != null && validationError.ChildErrors.Count > 0) - { - foreach (ValidationError childError in validationError.ChildErrors) - { - message.Append('\n' + prefix); - message.Append(FormatMessage(childError, prefix + " ")); - } + Select(e => FormatMessage(e, string.Empty)))); } - return message.ToString(); + return true; } } } diff --git a/src/DotNetStac/SimpleLinksCollectionObject.cs b/src/DotNetStac/SimpleLinksCollectionObject.cs index e064263c..fd03fa44 100644 --- a/src/DotNetStac/SimpleLinksCollectionObject.cs +++ b/src/DotNetStac/SimpleLinksCollectionObject.cs @@ -1,14 +1,25 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: SimpleLinksCollectionObject.cs + +using System.Collections.Generic; namespace Stac { + /// + /// A simple implementation of that can be used as a base class for other objects. + /// public class SimpleLinksCollectionObject : ILinksCollectionObject { + /// + /// Initializes a new instance of the class. + /// public SimpleLinksCollectionObject() { - Links = new List(); + this.Links = new List(); } + /// public ICollection Links { get; set; } } } diff --git a/src/DotNetStac/StacAccessorsHelpers.cs b/src/DotNetStac/StacAccessorsHelpers.cs index 9ab08432..611aae78 100644 --- a/src/DotNetStac/StacAccessorsHelpers.cs +++ b/src/DotNetStac/StacAccessorsHelpers.cs @@ -1,7 +1,9 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacAccessorsHelpers.cs + +using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; using System.Linq; using System.Reflection; using Newtonsoft.Json.Linq; @@ -9,60 +11,125 @@ namespace Stac { + /// + /// Helper class for accessing properties in Stac objects + /// public static class StacAccessorsHelpers { - + /// + /// Sets the property. + /// + /// The stac object. + /// The key. + /// The value. public static void SetProperty(this IStacObject stacObject, string key, object value) { stacObject.Properties.SetProperty(key, value); } + /// + /// Sets the property. + /// + /// The stac properties container. + /// The key. + /// The value. public static void SetProperty(this IStacPropertiesContainer stacPropertiesContainer, string key, object value) { stacPropertiesContainer.Properties.SetProperty(key, value); } + /// + /// Sets the property. + /// + /// The properties dictionary. + /// The key. + /// The value. public static void SetProperty(this IDictionary properties, string key, object value) { properties.Remove(key); properties.Add(key, value); } + /// + /// Gets the property. + /// + /// The stac properties container. + /// The key. + /// the property value public static object GetProperty(this IStacPropertiesContainer propertiesContainer, string key) { return propertiesContainer.Properties.GetProperty(key); } + /// + /// Gets the property. + /// + /// the type of the property + /// The stac properties container. + /// The key. + /// the property value public static T GetProperty(this IStacPropertiesContainer propertiesContainer, string key) { return propertiesContainer.Properties.GetProperty(key); } + /// + /// Gets the property. + /// + /// The properties dictionary. + /// The key. + /// the property value public static object GetProperty(this IDictionary properties, string key) { if (!properties.ContainsKey(key)) + { return null; + } + return properties[key]; } + /// + /// Gets the property. + /// + /// the type of the property + /// The properties dictionary. + /// The key. + /// the property value public static T GetProperty(this IDictionary properties, string key) { var @object = GetProperty(properties, key); - if (@object == null) return default(T); + if (@object == null) + { + return default(T); + } + if (@object is JToken) { return (@object as JToken).ToObject(); } + var t = typeof(T); if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { t = Nullable.GetUnderlyingType(t); } + if (t.GetTypeInfo().IsEnum) + { return (T)Enum.Parse(t, @object.ToString()); + } + return ChangeType(@object); } + /// + /// Gets the property as an observable collection. + /// + /// the type of the property + /// The properties container. + /// The key. + /// the property collection public static PropertyObservableCollection GetObservableCollectionProperty(this IStacPropertiesContainer propertiesContainer, string key) { List array = new List(); @@ -74,16 +141,22 @@ public static PropertyObservableCollection GetObservableCollectionProperty { array = propertiesContainer.GetProperty(key)?.ToList(); } + PropertyObservableCollection observableCollection = new PropertyObservableCollection(propertiesContainer, key); if (array != null && array.Count() > 0) { - observableCollection.AddRange(array); + observableCollection.AddRange(array); } + return observableCollection; } - - + /// + /// Changes the type. + /// + /// the type of the property + /// The value. + /// the changed type value public static T ChangeType(object value) { var t = typeof(T); @@ -94,35 +167,56 @@ public static T ChangeType(object value) { return default(T); } + t = Nullable.GetUnderlyingType(t); } return (T)Convert.ChangeType(value, t); } + /// + /// Removes the property. + /// + /// The stac properties container. + /// The key. public static void RemoveProperty(this IStacPropertiesContainer propertiesContainer, string key) { propertiesContainer.Properties.RemoveProperty(key); } + /// + /// Removes the property. + /// + /// The properties dictionary. + /// The key. public static void RemoveProperty(this IDictionary properties, string key) { properties.Remove(key); } + /// + /// Gets the children links. + /// + /// The stac parent. + /// the children links public static IEnumerable GetChildrenLinks(this IStacParent stacCatalog) { return stacCatalog.Links.Where(l => l.RelationshipType == "child"); } + /// + /// Gets the item links. + /// + /// The stac parent. + /// the item links public static IEnumerable GetItemLinks(this IStacParent stacCatalog) { return stacCatalog.Links.Where(l => l.RelationshipType == "item"); } /// - /// Set the id of the STAC Collection this Item references to - /// see collection relation type. + /// Set the id of the STAC Collection this Item references to + /// see collection relation type. /// /// stacItem to set the collection to /// identifier of the collection @@ -132,7 +226,10 @@ public static void SetCollection(this StacItem stacItem, string collectionId, Ur { var existingLink = stacItem.Links.FirstOrDefault(l => l.Uri == collectionUri); if (existingLink != null) + { stacItem.Links.Remove(existingLink); + } + stacItem.Links.Add(StacLink.CreateCollectionLink(collectionUri)); stacItem.Collection = collectionId; } @@ -140,13 +237,19 @@ public static void SetCollection(this StacItem stacItem, string collectionId, Ur /// /// Gets the collection of the Item as a StacLink /// - /// + /// The stac item. /// a Stac Link public static StacLink GetCollection(this StacItem stacItem) { return stacItem.Links.FirstOrDefault(l => l.RelationshipType == "collection"); } + /// + /// Adds a range of items to the collection. + /// + /// the type of the collection + /// The collection. + /// The items. public static void AddRange(this ICollection collection, IEnumerable items) { if (collection is List list) @@ -156,15 +259,25 @@ public static void AddRange(this ICollection collection, IEnumerable it else { foreach (T item in items) + { collection.Add(item); + } } } + /// + /// Inserts the item at the specified index in the collection. + /// + /// the type of the collection + /// The collection. + /// The index. + /// The item. public static void Insert(this ICollection collection, int index, T item) { - if (index < 0 || index > collection.Count) + { throw new ArgumentOutOfRangeException(nameof(index), "Index was out of range. Must be non-negative and less than the size of the collection."); + } if (collection is IList list) { @@ -181,6 +294,5 @@ public static void Insert(this ICollection collection, int index, T item) collection.AddRange(temp.Skip(index)); } } - } } diff --git a/src/DotNetStac/StacAsset.cs b/src/DotNetStac/StacAsset.cs index 34d495f3..4c6018d3 100644 --- a/src/DotNetStac/StacAsset.cs +++ b/src/DotNetStac/StacAsset.cs @@ -1,109 +1,50 @@ -using System; -using System.Collections; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacAsset.cs + +using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net.Mime; using System.Runtime.Serialization; using Newtonsoft.Json; -using Stac.Converters; namespace Stac { /// - /// STAC Asset Object implementing STAC Asset + /// STAC Asset Object implementing STAC Asset. /// [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] public class StacAsset : IStacPropertiesContainer { - - #region Static members - - /// - /// Create a thumbnail asset - /// - /// parent stac object - /// Uri to the thumbnail - /// media type of the thumbnail - /// title of the thumbnail (if any) - /// A new Asset describing the thumbnail - public static StacAsset CreateThumbnailAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) - { - return new StacAsset(stacObject, uri, new string[] { "thumbnail" }, title, mediaType); - } - - /// - /// Create an overview asset - /// - /// parent stac object - /// Uri to the overview - /// media type of the overview - /// title of the overview (if any) - /// A new Asset describing the overview - public static StacAsset CreateOverviewAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) - { - return new StacAsset(stacObject, uri, new string[] { "overview" }, title, mediaType); - } - - /// - /// Create a data asset - /// - /// parent stac object - /// Uri to the data - /// media type of the data - /// title of the data (if any) - /// A new Asset describing the data - public static StacAsset CreateDataAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) - { - return new StacAsset(stacObject, uri, new string[] { "data" }, title, mediaType); - } + private readonly Uri _base_uri; + private Uri _href; + private string _title; + private string _description; + private ContentType _type; + private Dictionary _properties; + private IStacObject _parentStacObject; /// - /// Create a metadata asset - /// - /// parent stac object - /// Uri to the metadata - /// media type of the metadata - /// title of the metadata (if any) - /// A new Asset describing the metadata - public static StacAsset CreateMetadataAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) - { - return new StacAsset(stacObject, uri, new string[] { "metadata" }, title, mediaType); - } - - #endregion - - Uri base_uri, href; - string title, description; - - ContentType type; - - private Dictionary properties; - private IStacObject parentStacObject; - - [JsonConstructor] - internal StacAsset() - { - properties = new Dictionary(); - Roles = new SortedSet(); - } - - /// - /// Initialize a new asset with a Uri + /// Initializes a new instance of the class. /// /// parent stac object /// uri to the asset - public StacAsset(IStacObject stacObject, Uri uri) : this() + public StacAsset(IStacObject stacObject, Uri uri) + : this() { if (!(stacObject == null || stacObject is StacItem || stacObject is StacCollection)) + { throw new InvalidOperationException("An asset cannot be defined in " + stacObject.GetType().Name); - parentStacObject = stacObject; - Uri = uri; + } + this._parentStacObject = stacObject; + this.Uri = uri; } /// + /// Initializes a new instance of the class. /// Initialize a new asset /// /// parent stac object @@ -111,14 +52,16 @@ public StacAsset(IStacObject stacObject, Uri uri) : this() /// roles of the asset /// title of the asset /// media-type of the asset - public StacAsset(IStacObject stacObject, Uri uri, IEnumerable roles, string title, ContentType mediaType) : this(stacObject, uri) + public StacAsset(IStacObject stacObject, Uri uri, IEnumerable roles, string title, ContentType mediaType) + : this(stacObject, uri) { - Roles = roles == null ? new SortedSet() : new SortedSet(roles.ToList()); - Title = title; - MediaType = mediaType; + this.Roles = roles == null ? new SortedSet() : new SortedSet(roles.ToList()); + this.Title = title; + this.MediaType = mediaType; } /// + /// Initializes a new instance of the class. /// Initialize a new asset from an existing one /// /// asset source to be copied @@ -126,39 +69,64 @@ public StacAsset(IStacObject stacObject, Uri uri, IEnumerable roles, str public StacAsset(StacAsset source, IStacObject stacObject) { if (!(stacObject == null || stacObject is StacItem || stacObject is StacCollection)) + { throw new InvalidOperationException("An asset cannot be defined in " + stacObject.GetType().Name); + } + if (source == null) + { throw new ArgumentNullException("source"); - base_uri = source.base_uri; - href = source.href; + } + + this._base_uri = source._base_uri; + this._href = source._href; if (source.Roles != null) - Roles = new SortedSet(source.Roles); + { + this.Roles = new SortedSet(source.Roles); + } else - Roles = new SortedSet(); - title = source.title; - type = source.type; - description = source.description; - if (source.properties != null) - properties = new Dictionary(source.properties); - parentStacObject = stacObject; + { + this.Roles = new SortedSet(); + } + + this._title = source._title; + this._type = source._type; + this._description = source._description; + if (source._properties != null) + { + this._properties = new Dictionary(source._properties); + } + + this._parentStacObject = stacObject; + } + + [JsonConstructor] + internal StacAsset() + { + this._properties = new Dictionary(); + this.Roles = new SortedSet(); } /// - /// Media type of the asset + /// Gets or sets media type of the asset /// - /// + /// + /// Media type of the asset + /// [JsonProperty("type")] [JsonConverter(typeof(ContentTypeConverter))] public ContentType MediaType { - get { return type; } - set { type = value; } + get { return this._type; } + set { this._type = value; } } /// - /// The semantic roles of the asset + /// Gets the semantic roles of the asset /// - /// + /// + /// The semantic roles of the asset + /// [JsonProperty("roles")] public ICollection Roles { @@ -167,81 +135,146 @@ public ICollection Roles } /// - /// The displayed title for clients and users. + /// Gets or sets the displayed title for clients and users. /// - /// + /// + /// The displayed title for clients and users. + /// [JsonProperty("title")] public string Title { - get { return title; } - set { title = value; } + get { return this._title; } + set { this._title = value; } } /// - /// URI to the asset object. Relative and absolute URI are both allowed. + /// Gets or sets uRI to the asset object. Relative and absolute URI are both allowed. /// - /// + /// + /// URI to the asset object. Relative and absolute URI are both allowed. + /// [JsonProperty("href")] public Uri Uri { - get { return href; } - set { href = value; } + get { return this._href; } + set { this._href = value; } } /// - /// A description of the Asset providing additional details, such as how it was processed or created. + /// Gets or sets a description of the Asset providing additional details, such as how it was processed or created. /// - /// + /// + /// A description of the Asset providing additional details, such as how it was processed or created. + /// [JsonProperty("description")] public string Description { - get { return description; } - set { description = value; } + get { return this._description; } + set { this._description = value; } } /// - /// Extended properties + /// Gets or sets extended properties /// - /// + /// + /// Extended properties + /// [JsonExtensionData] public IDictionary Properties { get { - return properties; + return this._properties; } set { - properties = new Dictionary(value); + this._properties = new Dictionary(value); } } /// - /// Object container + /// Gets object container /// + /// + /// Object container + /// [JsonIgnore] - public IStacObject StacObjectContainer => ParentStacObject; + public IStacObject StacObjectContainer => this.ParentStacObject; /// - /// parent stac object + /// Gets parent stac object /// - /// + /// + /// Parent stac object + /// [JsonIgnore] - public IStacObject ParentStacObject { get => parentStacObject; internal set => parentStacObject = value; } + public IStacObject ParentStacObject { get => this._parentStacObject; internal set => this._parentStacObject = value; } + + /// + /// Create a thumbnail asset + /// + /// parent stac object + /// Uri to the thumbnail + /// media type of the thumbnail + /// title of the thumbnail (if any) + /// A new Asset describing the thumbnail + public static StacAsset CreateThumbnailAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) + { + return new StacAsset(stacObject, uri, new string[] { "thumbnail" }, title, mediaType); + } + + /// + /// Create an overview asset + /// + /// parent stac object + /// Uri to the overview + /// media type of the overview + /// title of the overview (if any) + /// A new Asset describing the overview + public static StacAsset CreateOverviewAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) + { + return new StacAsset(stacObject, uri, new string[] { "overview" }, title, mediaType); + } + + /// + /// Create a data asset + /// + /// parent stac object + /// Uri to the data + /// media type of the data + /// title of the data (if any) + /// A new Asset describing the data + public static StacAsset CreateDataAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) + { + return new StacAsset(stacObject, uri, new string[] { "data" }, title, mediaType); + } + + /// + /// Create a metadata asset + /// + /// parent stac object + /// Uri to the metadata + /// media type of the metadata + /// title of the metadata (if any) + /// A new Asset describing the metadata + public static StacAsset CreateMetadataAsset(IStacObject stacObject, Uri uri, ContentType mediaType, string title = null) + { + return new StacAsset(stacObject, uri, new string[] { "metadata" }, title, mediaType); + } #pragma warning disable 1591 [ExcludeFromCodeCoverage] public bool ShouldSerializeStacExtensions() { // don't serialize the Manager property if an employee is their own manager - return Roles.Count > 0; + return this.Roles.Count > 0; } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { - Roles = new SortedSet(Roles); + this.Roles = new SortedSet(this.Roles); } } } diff --git a/src/DotNetStac/StacCatalog.CommonMetadata.cs b/src/DotNetStac/StacCatalog.CommonMetadata.cs index 253c2f8a..51648d49 100644 --- a/src/DotNetStac/StacCatalog.CommonMetadata.cs +++ b/src/DotNetStac/StacCatalog.CommonMetadata.cs @@ -1,18 +1,22 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacCatalog.CommonMetadata.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; using Newtonsoft.Json; namespace Stac { /// - /// This class allows accessing commonly used fields in STAC Item + /// This class allows accessing commonly used fields in STAC Item /// They are often used in STAC Item properties, but can also be used in other places, e.g. an Item Asset or Collection Asset. /// STAC Common Metadata /// public partial class StacCatalog : IStacObject, IStacParent, IStacCatalog, ICloneable { + /// [JsonProperty("title")] public string Title { @@ -20,12 +24,18 @@ public string Title set => this.SetProperty("title", value); } + /// + /// Gets or sets the description of the Catalog. + /// public string Description { get => this.GetProperty("description"); set => this.SetProperty("description", value); } + /// + /// Gets or sets the license of the Catalog. + /// public string License { get => this.GetProperty("license"); @@ -33,59 +43,87 @@ public string License } /// - /// A list of providers, which may include all organizations capturing or processing the data or the hosting provider. + /// Gets a list of providers, which may include all organizations capturing or processing the data or the hosting provider. /// Providers should be listed in chronological order with the most recent provider being the last element of the list. /// - /// public Collection Providers => this.GetObservableCollectionProperty("providers"); + /// + /// Gets or sets the platform the data was acquired from. + /// public string Platform { get => this.GetProperty("platform"); set => this.SetProperty("platform", value); } + /// + /// Gets or sets the instruments used to acquire the data. + /// public IEnumerable Instruments { get => this.GetProperty("instruments"); set => this.SetProperty("instruments", value); } + /// + /// Gets or sets the constellation the data was acquired from. + /// public string Constellation { get => this.GetProperty("constellation"); set => this.SetProperty("constellation", value); } + /// + /// Gets or sets the mission the data was acquired from. + /// public string Mission { get => this.GetProperty("mission"); set => this.SetProperty("mission", value); } + /// + /// Gets or sets the gsd (Ground Sample Distance) in meters. + /// public double? Gsd { get => this.GetProperty("gsd"); set { - if (value == 0) this.RemoveProperty("gsd"); + if (value == 0) + { + this.RemoveProperty("gsd"); + } else + { this.SetProperty("gsd", value); + } } } + /// + /// Gets or sets the created date and time of the catalog. + /// public DateTime Created { get => this.GetProperty("created"); set => this.SetProperty("created", value); } + /// + /// Gets or sets the updated date and time of the catalog. + /// public DateTime Updated { get => this.GetProperty("updated"); set => this.SetProperty("updated", value); } + /// + /// Gets or sets the start date and time of the catalog. + /// public Itenso.TimePeriod.ITimePeriod DateTime { get @@ -93,7 +131,9 @@ public Itenso.TimePeriod.ITimePeriod DateTime if (this.Properties.ContainsKey("datetime")) { if (this.Properties["datetime"] is DateTime?) + { return new Itenso.TimePeriod.TimeInterval((DateTime)this.Properties["datetime"]); + } else { try @@ -105,16 +145,23 @@ public Itenso.TimePeriod.ITimePeriod DateTime if (this.Properties.ContainsKey("start_datetime") && this.Properties.ContainsKey("end_datetime")) { if (this.Properties["start_datetime"] is DateTime? && this.Properties["end_datetime"] is DateTime?) - return new Itenso.TimePeriod.TimeInterval((DateTime)this.Properties["start_datetime"], - (DateTime)this.Properties["end_datetime"]); + { + return new Itenso.TimePeriod.TimeInterval( + (DateTime)this.Properties["start_datetime"], + (DateTime)this.Properties["end_datetime"]); + } + throw new FormatException(string.Format("start_datetime and/or end_datetime are not a valid: {0}", e.Message), e); } + throw new FormatException(string.Format("datetime is not a valid", e.Message), e); } } } + return Itenso.TimePeriod.TimeInterval.Anytime; } + set { // datetime, start_datetime, end_datetime @@ -140,6 +187,7 @@ public Itenso.TimePeriod.ITimePeriod DateTime } } + /// public object Clone() { return new StacCatalog(this); diff --git a/src/DotNetStac/StacCatalog.cs b/src/DotNetStac/StacCatalog.cs index b3dc1061..9059a12e 100644 --- a/src/DotNetStac/StacCatalog.cs +++ b/src/DotNetStac/StacCatalog.cs @@ -1,4 +1,8 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacCatalog.cs + +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Net.Mime; @@ -6,7 +10,6 @@ using Newtonsoft.Json; using Semver; using Stac.Converters; -using Stac.Extensions; namespace Stac { @@ -22,13 +25,7 @@ public partial class StacCatalog : IStacObject, IStacParent, IStacCatalog public const string MEDIATYPE = "application/json"; /// - /// Catalog Media-Type Object - /// - /// - public readonly static ContentType CATALOG_MEDIATYPE = new ContentType(MEDIATYPE); - - /// - /// Initialize an empty STAC Catalog + /// Initializes a new instance of the class. /// /// required identifier of the catalog /// required description of the catalog @@ -41,14 +38,20 @@ public StacCatalog(string id, string description, IEnumerable links = this.StacVersion = Versions.StacVersionList.Current; this.Description = description; if (links == null) + { this.Links = new Collection(); + } else + { this.Links = new Collection(links.ToList()); - this.Summaries = new Dictionary(); + } + + this.Summaries = new Dictionary(); this.StacExtensions = new SortedSet(); } /// + /// Initializes a new instance of the class. /// Initialize a new Stac Catalog from an existing one (clone) /// /// existing Stac Catalog @@ -58,38 +61,44 @@ public StacCatalog(StacCatalog stacCatalog) this.StacExtensions = new SortedSet(stacCatalog.StacExtensions); this.StacVersion = stacCatalog.StacVersion; this.Links = new Collection(stacCatalog.Links.ToList()); - this.Summaries = new Dictionary(stacCatalog.Summaries); + this.Summaries = new Dictionary(stacCatalog.Summaries); this.Properties = new Dictionary(stacCatalog.Properties); } - # region IStacObject - /// - /// Identifier for the Catalog. + /// Gets identifier for the Catalog. /// - /// + /// + /// Identifier for the Catalog. + /// [JsonProperty("id")] public string Id { get; internal set; } /// - /// The STAC version the Catalog implements + /// Gets or sets the STAC version the Catalog implements /// - /// + /// + /// The STAC version the Catalog implements + /// [JsonProperty("stac_version")] [JsonConverter(typeof(SemVersionConverter))] public SemVersion StacVersion { get; set; } /// - /// A list of extension identifiers the Catalog implements + /// Gets a list of extension identifiers the Catalog implements /// - /// + /// + /// A list of extension identifiers the Catalog implements + /// [JsonProperty("stac_extensions")] public ICollection StacExtensions { get; private set; } /// - /// A list of references to other documents. + /// Gets a list of references to other documents. /// - /// + /// + /// A list of references to other documents. + /// [JsonConverter(typeof(CollectionConverter))] [JsonProperty("links")] public ICollection Links @@ -97,57 +106,64 @@ public ICollection Links get; internal set; } + /// [JsonIgnore] - public ContentType MediaType => CATALOG_MEDIATYPE; - - # endregion IStacObject + public ContentType MediaType => new ContentType(MEDIATYPE); /// - /// STAC type (Catalog) + /// Gets sTAC type (Catalog) /// + /// + /// STAC type (Catalog) + /// [JsonProperty("type")] public string Type => "Catalog"; /// - /// A map of property summaries, either a set of values or statistics such as a range. + /// Gets a map of property summaries, either a set of values or statistics such as a range. /// - /// + /// + /// A map of property summaries, either a set of values or statistics such as a range. + /// [JsonProperty("summaries")] [JsonConverter(typeof(StacSummariesConverter))] - public Dictionary Summaries { get; internal set; } + public Dictionary Summaries { get; internal set; } /// - /// Catalog Properties + /// Gets catalog Properties /// - /// + /// + /// Catalog Properties + /// [JsonExtensionData] public IDictionary Properties { get; internal set; } + /// [JsonIgnore] public IStacObject StacObjectContainer => this; - [OnDeserialized] - internal void OnDeserializedMethod(StreamingContext context) - { - foreach (StacLink link in Links) - { - link.Parent = this; - } - StacExtensions = new SortedSet(StacExtensions); - } - #pragma warning disable 1591 public bool ShouldSerializeSummaries() { // don't serialize the Manager property if an employee is their own manager - return Summaries.Count > 0; + return this.Summaries.Count > 0; } public bool ShouldSerializeStacExtensions() { // don't serialize the Manager property if an employee is their own manager - return StacExtensions.Count > 0; + return this.StacExtensions.Count > 0; } + [OnDeserialized] + internal void OnDeserializedMethod(StreamingContext context) + { + foreach (StacLink link in this.Links) + { + link.Parent = this; + } + + this.StacExtensions = new SortedSet(this.StacExtensions); + } } } diff --git a/src/DotNetStac/StacCollection.CommonMetadata.cs b/src/DotNetStac/StacCollection.CommonMetadata.cs index 34ea9aff..1e93f360 100644 --- a/src/DotNetStac/StacCollection.CommonMetadata.cs +++ b/src/DotNetStac/StacCollection.CommonMetadata.cs @@ -1,23 +1,26 @@ -using System; -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacCollection.CommonMetadata.cs + +using System; using System.Collections.ObjectModel; -using System.Linq; using Newtonsoft.Json; namespace Stac { /// - /// This class allows accessing commonly used fields in STAC Item + /// This class allows accessing commonly used fields in STAC Item /// They are often used in STAC Item properties, but can also be used in other places, e.g. an Item Asset or Collection Asset. /// STAC Common Metadata /// public partial class StacCollection : IStacObject, IStacParent, IStacCatalog, ICloneable { - /// - /// A short descriptive one-line title for the Collection. + /// Gets or sets a short descriptive one-line title for the Collection. /// - /// + /// + /// A short descriptive one-line title for the Collection. + /// [JsonProperty("__title", Required = Required.Default)] [JsonIgnore] public string Title @@ -27,9 +30,11 @@ public string Title } /// - /// Detailed multi-line description to fully explain the Collection. CommonMark 0.29 syntax MAY be used for rich text representation. + /// Gets or sets detailed multi-line description to fully explain the Collection. CommonMark 0.29 syntax MAY be used for rich text representation. /// - /// + /// + /// Detailed multi-line description to fully explain the Collection. CommonMark 0.29 syntax MAY be used for rich text representation. + /// [JsonProperty("__description", Required = Required.Default)] [JsonIgnore] public string Description @@ -39,9 +44,11 @@ public string Description } /// - /// Collection's license(s), either a SPDX License identifier, various if multiple licenses apply or proprietary for all other cases. + /// Gets or sets collection's license(s), either a SPDX License identifier, various if multiple licenses apply or proprietary for all other cases. /// - /// + /// + /// Collection's license(s), either a SPDX License identifier, various if multiple licenses apply or proprietary for all other cases. + /// public string License { get => this.GetProperty("license"); @@ -49,13 +56,15 @@ public string License } /// - /// A list of providers, which may include all organizations capturing or processing the data or the hosting provider. + /// Gets a list of providers, which may include all organizations capturing or processing the data or the hosting provider. /// Providers should be listed in chronological order with the most recent provider being the last element of the list. /// - /// + /// + /// A list of providers, which may include all organizations capturing or processing the data or the hosting provider. + /// Providers should be listed in chronological order with the most recent provider being the last element of the list. + /// [JsonProperty("__providers", Required = Required.Default)] [JsonIgnore] public Collection Providers => this.GetObservableCollectionProperty("providers"); - } } diff --git a/src/DotNetStac/StacCollection.cs b/src/DotNetStac/StacCollection.cs index baf7fd14..28e24a9b 100644 --- a/src/DotNetStac/StacCollection.cs +++ b/src/DotNetStac/StacCollection.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacCollection.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -18,31 +22,52 @@ namespace Stac [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, MemberSerialization = MemberSerialization.OptIn)] public partial class StacCollection : IStacObject, IStacParent, IStacCatalog, ICloneable { + /// + /// Media type for STAC Collection + /// public const string MEDIATYPE = "application/json"; - public readonly static ContentType COLLECTION_MEDIATYPE = new ContentType(MEDIATYPE); - + /// + /// Initializes a new instance of the class. + /// + /// Identifier of the collection + /// Description of the collection + /// Extent of the collection + /// Assets of the collection + /// Links of the collection + /// License of the collection [JsonConstructor] - public StacCollection(string id, - string description, - StacExtent extent, - IDictionary assets = null, - IEnumerable links = null, - string license = "proprietary") + public StacCollection( + string id, + string description, + StacExtent extent, + IDictionary assets = null, + IEnumerable links = null, + string license = "proprietary") { this.Properties = new Dictionary(); this.Id = id; this.StacVersion = Versions.StacVersionList.Current; this.Description = description; if (links == null) + { this.Links = new Collection(); + } else + { this.Links = new Collection(links.ToList()); + } + if (assets == null) + { this.Assets = new Dictionary(); + } else + { this.Assets = new Dictionary(assets); - this.Summaries = new Dictionary(); + } + + this.Summaries = new Dictionary(); this.StacExtensions = new SortedSet(); this.License = license; this.Keywords = new Collection(); @@ -50,7 +75,7 @@ public StacCollection(string id, } /// - /// Initialize a new Stac Collection from an existing one (clone) + /// Initializes a new instance of the class. /// /// existing Stac Collection public StacCollection(StacCollection stacCollection) @@ -59,7 +84,7 @@ public StacCollection(StacCollection stacCollection) this.StacExtensions = new SortedSet(stacCollection.StacExtensions); this.StacVersion = stacCollection.StacVersion; this.Links = new Collection(stacCollection.Links.ToList()); - this.Summaries = new Dictionary(stacCollection.Summaries); + this.Summaries = new Dictionary(stacCollection.Summaries); this.Properties = new Dictionary(stacCollection.Properties); this.Assets = new Dictionary(stacCollection.Assets.Select(a => new KeyValuePair(a.Key, new StacAsset(a.Value, this))) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)); @@ -68,34 +93,28 @@ public StacCollection(StacCollection stacCollection) this.Extent = new StacExtent(stacCollection.Extent); } - #region IStacObject - /// - /// Identifier for the Collection. + /// Gets identifier for the Collection. /// - /// [JsonProperty("id")] public string Id { get; internal set; } /// - /// The STAC version the Collection implements + /// Gets or sets the STAC version the Collection implements /// - /// [JsonProperty("stac_version")] [JsonConverter(typeof(SemVersionConverter))] public SemVersion StacVersion { get; set; } /// - /// A list of extension identifiers the Collection implements + /// Gets a list of extension identifiers the Collection implements /// - /// [JsonProperty("stac_extensions")] public ICollection StacExtensions { get; private set; } /// - /// A list of references to other documents. + /// Gets a list of references to other documents. /// - /// [JsonConverter(typeof(CollectionConverter))] [JsonProperty("links")] public ICollection Links @@ -103,104 +122,70 @@ public ICollection Links get; internal set; } + /// [JsonIgnore] - public ContentType MediaType => COLLECTION_MEDIATYPE; - - #endregion IStacObject + public ContentType MediaType => new ContentType(MEDIATYPE); /// - /// STAC type (Collection) + /// Gets sTAC type (Collection) /// [JsonProperty("type")] public virtual string Type => "Collection"; /// - /// A map of property summaries, either a set of values or statistics such as a range. + /// Gets a map of property summaries, either a set of values or statistics such as a range. /// - /// [JsonProperty("summaries")] [JsonConverter(typeof(StacSummariesConverter))] - public Dictionary Summaries { get; internal set; } + public Dictionary Summaries { get; internal set; } /// - /// Collection extended data + /// Gets collection extended data /// - /// [JsonExtensionData] public IDictionary Properties { get; internal set; } /// - /// Spatial and temporal extents. + /// Gets spatial and temporal extents. /// - /// [JsonProperty("extent")] public StacExtent Extent { get; internal set; } /// - /// List of keywords describing the Collection. + /// Gets list of keywords describing the Collection. /// - /// [JsonProperty("keywords", DefaultValueHandling = DefaultValueHandling.Ignore)] public Collection Keywords { get; internal set; } + /// + /// Gets the asset objects that are available for this collection. + /// [JsonProperty("assets")] public IDictionary Assets { get; internal set; } + /// [JsonIgnore] public IStacObject StacObjectContainer => this; - [OnDeserialized] - internal void OnDeserializedMethod(StreamingContext context) - { - foreach (StacLink link in Links) - { - link.Parent = this; - } - StacExtensions = new SortedSet(StacExtensions); - } - -#pragma warning disable 1591 - public bool ShouldSerializeSummaries() - { - // don't serialize the Manager property if an employee is their own manager - return Summaries.Count > 0; - } - -#pragma warning disable 1591 - public bool ShouldSerializeStacExtensions() - { - // don't serialize the Manager property if an employee is their own manager - return StacExtensions.Count > 0; - } - -#pragma warning disable 1591 - public bool ShouldSerializeAssets() - { - // don't serialize the Manager property if an employee is their own manager - return Assets.Count > 0; - } - - #region Static Methods - /// /// Generate a collection corresponding to the items' dictionary. Spatial and temporal extents /// are computed. Fields values are summarized in stats object and value sets. /// All Items are updated with the collection id /// - /// Identifier of the collection /// Description of the collection /// Dictionary of Uri, StacItem. Uri points to the StacItem destination. /// License of the collection /// Uri of the collection. If provided, the items Uri and made relative to this one. /// Assets of the collection - /// - public static StacCollection Create(string id, - string description, - IDictionary items, - string license = null, - Uri collectionUri = null, - IDictionary assets = null) + /// StacCollection + public static StacCollection Create( + string id, + string description, + IDictionary items, + string license = null, + Uri collectionUri = null, + IDictionary assets = null) { var collection = new StacCollection( id, @@ -211,8 +196,15 @@ public static StacCollection Create(string id, { Uri itemUri = item.Key; if (collectionUri != null) + { itemUri = collectionUri.MakeRelativeUri(item.Key); - if (!itemUri.IsAbsoluteUri) { itemUri = new Uri("./" + itemUri.OriginalString, UriKind.Relative); } + } + + if (!itemUri.IsAbsoluteUri) + { + itemUri = new Uri("./" + itemUri.OriginalString, UriKind.Relative); + } + return StacLink.CreateObjectLink(item.Value, itemUri); }), license); @@ -223,10 +215,10 @@ public static StacCollection Create(string id, .GroupBy(prop => prop.Key) .ToDictionary(key => key.Key, value => value.First().Value); - summaryFunctions.Add("gsd", new SummaryFunction(null, "gsd", StacPropertiesContainerExtension.CreateRangeSummaryObject)); - summaryFunctions.Add("platform", new SummaryFunction(null, "platform", StacPropertiesContainerExtension.CreateSummaryValueSet)); - summaryFunctions.Add("constellation", new SummaryFunction(null, "constellation", StacPropertiesContainerExtension.CreateSummaryValueSet)); - summaryFunctions.Add("instruments", new SummaryFunction(null, "instruments", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("gsd", new SummaryFunction(null, "gsd", StacPropertiesContainerExtension.CreateRangeSummaryObject)); + summaryFunctions.Add("platform", new SummaryFunction(null, "platform", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("constellation", new SummaryFunction(null, "constellation", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("instruments", new SummaryFunction(null, "instruments", StacPropertiesContainerExtension.CreateSummaryValueSet)); collection.Summaries = items.Values.SelectMany(item => item.Properties.Where(k => summaryFunctions.Keys.Contains(k.Key))) @@ -236,20 +228,45 @@ public static StacCollection Create(string id, if (summaryFunctions.ContainsKey(value.Key)) { if (summaryFunctions[value.Key].Extension != null && !collection.StacExtensions.Contains(summaryFunctions[value.Key].Extension.Identifier)) + { collection.StacExtensions.Add(summaryFunctions[value.Key].Extension.Identifier); + } + return summaryFunctions[value.Key].Summarize(value.Select(i => i.Value)); } + return null; }); return collection; } - #endregion +#pragma warning disable 1591 + public bool ShouldSerializeSummaries() + { + // don't serialize the Manager property if an employee is their own manager + return this.Summaries.Count > 0; + } - public void Update(IDictionary items) + public bool ShouldSerializeStacExtensions() + { + // don't serialize the Manager property if an employee is their own manager + return this.StacExtensions.Count > 0; + } + + public bool ShouldSerializeAssets() { + // don't serialize the Manager property if an employee is their own manager + return this.Assets.Count > 0; + } +#pragma warning restore 1591 + /// + /// Update the collection with new items. + /// + /// Dictionary of Uri, StacItem. Uri points to the StacItem destination. + public void Update(IDictionary items) + { this.Extent.Update(items.Values); var usedExtensions = items.SelectMany(item => item.Value.GetDeclaredExtensions()); @@ -258,10 +275,10 @@ public void Update(IDictionary items) .GroupBy(prop => prop.Key) .ToDictionary(key => key.Key, value => value.First().Value); - summaryFunctions.Add("gsd", new SummaryFunction(null, "gsd", StacPropertiesContainerExtension.CreateRangeSummaryObject)); - summaryFunctions.Add("platform", new SummaryFunction(null, "platform", StacPropertiesContainerExtension.CreateSummaryValueSet)); - summaryFunctions.Add("constellation", new SummaryFunction(null, "constellation", StacPropertiesContainerExtension.CreateSummaryValueSet)); - summaryFunctions.Add("instruments", new SummaryFunction(null, "instruments", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("gsd", new SummaryFunction(null, "gsd", StacPropertiesContainerExtension.CreateRangeSummaryObject)); + summaryFunctions.Add("platform", new SummaryFunction(null, "platform", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("constellation", new SummaryFunction(null, "constellation", StacPropertiesContainerExtension.CreateSummaryValueSet)); + summaryFunctions.Add("instruments", new SummaryFunction(null, "instruments", StacPropertiesContainerExtension.CreateSummaryValueSet)); this.Summaries = items.Values.SelectMany(item => item.Properties.Where(k => summaryFunctions.Keys.Contains(k.Key))) @@ -272,22 +289,34 @@ public void Update(IDictionary items) if (summaryFunctions.ContainsKey(value.Key)) { if (summaryFunctions[value.Key].Extension != null && !this.StacExtensions.Contains(summaryFunctions[value.Key].Extension.Identifier)) + { this.StacExtensions.Add(summaryFunctions[value.Key].Extension.Identifier); + } + return summaryFunctions[value.Key].Summarize(value.Select(i => i.Value)); } + return null; }); return; } - /// - /// Clone this object. - /// - /// + /// public object Clone() { return new StacCollection(this); } + + [OnDeserialized] + internal void OnDeserializedMethod(StreamingContext context) + { + foreach (StacLink link in this.Links) + { + link.Parent = this; + } + + this.StacExtensions = new SortedSet(this.StacExtensions); + } } } diff --git a/src/DotNetStac/StacConvert.cs b/src/DotNetStac/StacConvert.cs index b28abf87..0d2b0c65 100644 --- a/src/DotNetStac/StacConvert.cs +++ b/src/DotNetStac/StacConvert.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacConvert.cs + +using System; using System.Globalization; using System.IO; using Newtonsoft.Json; @@ -11,13 +15,21 @@ namespace Stac /// public static class StacConvert { - private static JsonSerializerSettings defaultJsonSerializerSettings = new JsonSerializerSettings() + private static readonly JsonSerializerSettings DefaultJsonSerializerSettings = new JsonSerializerSettings() { DateTimeZoneHandling = DateTimeZoneHandling.Utc, - Culture = CultureInfo.CreateSpecificCulture("en-US") + Culture = CultureInfo.CreateSpecificCulture("en-US"), }; - public static T Deserialize(string json, JsonSerializerSettings serializerSettings = null) where T : IStacObject + /// + /// Deserialize a STAC object from a JSON string. + /// + /// The type of the STAC object to deserialize. + /// The JSON string to deserialize. + /// The JSON serializer settings to use. + /// The deserialized STAC object. + public static T Deserialize(string json, JsonSerializerSettings serializerSettings = null) + where T : IStacObject { // if (typeof(T) == typeof(StacItem) // || typeof(T) == typeof(StacCollection) @@ -26,8 +38,9 @@ public static T Deserialize(string json, JsonSerializerSettings serializerSet // return JsonConvert.DeserializeObject(json); if (serializerSettings == null) { - serializerSettings = defaultJsonSerializerSettings; + serializerSettings = DefaultJsonSerializerSettings; } + serializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; JObject jobject = JsonConvert.DeserializeObject(json, serializerSettings); Type stacType = Utils.IdentifyStacType(jobject); @@ -35,6 +48,7 @@ public static T Deserialize(string json, JsonSerializerSettings serializerSet { throw new InvalidCastException(stacType + "is not IStacCatalog"); } + try { // return (T)JsonConvert.DeserializeObject(json, typeof(T), serializerSettings); @@ -46,17 +60,31 @@ public static T Deserialize(string json, JsonSerializerSettings serializerSet } } + /// + /// Serialize a STAC object to a JSON string. + /// + /// The STAC object to serialize. + /// The JSON serializer settings to use. + /// The serialized JSON string. public static string Serialize(IStacObject stacObject, JsonSerializerSettings serializerSettings = null) { if (serializerSettings == null) { - serializerSettings = defaultJsonSerializerSettings; + serializerSettings = DefaultJsonSerializerSettings; } + serializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; return JsonConvert.SerializeObject(stacObject, serializerSettings); } - public static T Deserialize(Stream stream) where T : IStacObject + /// + /// Deserialize a STAC object from a JSON stream. + /// + /// The type of the STAC object to deserialize. + /// The JSON stream to deserialize. + /// The deserialized STAC object. + public static T Deserialize(Stream stream) + where T : IStacObject { StreamReader sr = new StreamReader(stream); return Deserialize(sr.ReadToEnd()); diff --git a/src/DotNetStac/StacGeometryHelpers.cs b/src/DotNetStac/StacGeometryHelpers.cs index f5a4fceb..05efc3a1 100644 --- a/src/DotNetStac/StacGeometryHelpers.cs +++ b/src/DotNetStac/StacGeometryHelpers.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacGeometryHelpers.cs + +using System; using System.Linq; using GeoJSON.Net; using GeoJSON.Net.Geometry; @@ -10,38 +14,49 @@ namespace Stac /// public static class StacGeometryHelpers { - /// /// Get The bounding box of a geometry in a StacItem /// /// The STAC Item containing the geometry - /// + /// The bounding box public static double[] GetBoundingBoxFromGeometryExtent(this StacItem stacItem) { var boundingBoxes = stacItem.Geometry?.GetBoundingBox(); if (boundingBoxes == null) + { return new double[] { -180, -90, 180, 90 }; + } + if (boundingBoxes[0].Altitude.HasValue) - return new double[] { + { + return new double[] + { boundingBoxes[0].Longitude, boundingBoxes[0].Latitude, boundingBoxes[0].Altitude.Value, boundingBoxes[1].Longitude, boundingBoxes[1].Latitude, boundingBoxes[1].Altitude.Value, }; + } else - return new double[] { + { + return new double[] + { boundingBoxes[0].Longitude, boundingBoxes[0].Latitude, boundingBoxes[1].Longitude, boundingBoxes[1].Latitude, }; + } } /// /// Get the bounding box of a geometry object /// /// the geometry object - /// + /// The bounding box public static IPosition[] GetBoundingBox(this IGeometryObject geometry) { if (geometry == null) + { throw new ArgumentNullException(nameof(geometry)); + } + IPosition upperRight = null, lowerLeft = null; double lowerLeftLon, lowerLeftLat, upperRightLon, upperRightLat; double? lowerLeftAlt = null, upperRightAlt = null; @@ -110,28 +125,44 @@ public static IPosition[] GetBoundingBox(this IGeometryObject geometry) /// Get the lower left corner of a bounding box /// /// set of positions - /// + /// the lower left corner public static IPosition GetLowerLeft(this IPosition[] positions) { - if (positions == null || positions.Length == 0) return null; + if (positions == null || positions.Length == 0) + { + return null; + } + if (positions[0].Altitude.HasValue) - return new GeoJSON.Net.Geometry.Position(positions.Min(p => p.Latitude), positions.Min(p => p.Longitude), positions.Min(p => p.Altitude)); + { + return new Position(positions.Min(p => p.Latitude), positions.Min(p => p.Longitude), positions.Min(p => p.Altitude)); + } else - return new GeoJSON.Net.Geometry.Position(positions.Min(p => p.Latitude), positions.Min(p => p.Longitude)); + { + return new Position(positions.Min(p => p.Latitude), positions.Min(p => p.Longitude)); + } } /// - /// Get the upper right corner of a bounding box + /// Get the upper right corner of a bounding box. /// - /// set of positions - /// + /// set of positions. + /// the upper right corner. public static IPosition GetUpperRight(this IPosition[] positions) { - if (positions == null || positions.Length == 0) return null; + if (positions == null || positions.Length == 0) + { + return null; + } + if (positions[0].Altitude.HasValue) - return new GeoJSON.Net.Geometry.Position(positions.Max(p => p.Latitude), positions.Max(p => p.Longitude), positions.Max(p => p.Altitude)); + { + return new Position(positions.Max(p => p.Latitude), positions.Max(p => p.Longitude), positions.Max(p => p.Altitude)); + } else - return new GeoJSON.Net.Geometry.Position(positions.Max(p => p.Latitude), positions.Max(p => p.Longitude)); + { + return new Position(positions.Max(p => p.Latitude), positions.Max(p => p.Longitude)); + } } } } diff --git a/src/DotNetStac/StacItem.CommonMetadata.cs b/src/DotNetStac/StacItem.CommonMetadata.cs index 7d13b1f3..ffd3a91b 100644 --- a/src/DotNetStac/StacItem.CommonMetadata.cs +++ b/src/DotNetStac/StacItem.CommonMetadata.cs @@ -1,25 +1,31 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacItem.CommonMetadata.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; using Newtonsoft.Json; namespace Stac { /// - /// This class allows accessing commonly used fields in STAC Item + /// This class allows accessing commonly used fields in STAC Item /// They are often used in STAC Item properties, but can also be used in other places, e.g. an Item Asset or Collection Asset. /// STAC Common Metadata /// public partial class StacItem : GeoJSON.Net.Feature.Feature, IStacObject { - + /// public string Title { get => this.GetProperty("title"); set => this.SetProperty("title", value); } + /// + /// Gets or sets the description of the Item. + /// [JsonProperty("__description", Required = Required.Default)] [JsonIgnore] public string Description @@ -28,6 +34,9 @@ public string Description set => this.SetProperty("description", value); } + /// + /// Gets or sets the license of the Item. + /// public string License { get => this.GetProperty("license"); @@ -35,59 +44,87 @@ public string License } /// - /// A list of providers, which may include all organizations capturing or processing the data or the hosting provider. + /// Gets a list of providers, which may include all organizations capturing or processing the data or the hosting provider. /// Providers should be listed in chronological order with the most recent provider being the last element of the list. /// - /// public Collection Providers => this.GetObservableCollectionProperty("providers"); + /// + /// Gets or sets the platform the data was acquired from. + /// public string Platform { get => this.GetProperty("platform"); set => this.SetProperty("platform", value); } + /// + /// Gets or sets the instruments used to acquire the data. + /// public IEnumerable Instruments { get => this.GetProperty("instruments"); set => this.SetProperty("instruments", value); } + /// + /// Gets or sets the constellation the data was acquired from. + /// public string Constellation { get => this.GetProperty("constellation"); set => this.SetProperty("constellation", value); } + /// + /// Gets or sets the mission the data was acquired from. + /// public string Mission { get => this.GetProperty("mission"); set => this.SetProperty("mission", value); } + /// + /// Gets or sets the name of the satellite the data was acquired from. + /// public double? Gsd { get => this.GetProperty("gsd"); set { - if (value == 0) this.RemoveProperty("gsd"); + if (value == 0) + { + this.RemoveProperty("gsd"); + } else + { this.SetProperty("gsd", value); + } } } + /// + /// Gets or sets the created date and time of the Item. + /// public DateTime Created { get => this.GetProperty("created"); set => this.SetProperty("created", value); } + /// + /// Gets or sets the updated date and time of the Item. + /// public DateTime Updated { get => this.GetProperty("updated"); set => this.SetProperty("updated", value); } + /// + /// Gets or sets the date and time the data was acquired. + /// public Itenso.TimePeriod.ITimePeriod DateTime { get @@ -95,7 +132,9 @@ public Itenso.TimePeriod.ITimePeriod DateTime if (this.Properties.ContainsKey("datetime")) { if (this.Properties["datetime"] is DateTime?) + { return new Itenso.TimePeriod.TimeInterval((DateTime)this.Properties["datetime"]); + } else { try @@ -105,19 +144,28 @@ public Itenso.TimePeriod.ITimePeriod DateTime catch (NullReferenceException nre) { if (!this.Properties.ContainsKey("datetime") || (!this.Properties.ContainsKey("start_datetime") && !this.Properties.ContainsKey("end_datetime"))) + { throw new FormatException("One of datetime, start_datetime and/or end_datetime are required", nre); + } } + if (this.Properties.ContainsKey("start_datetime") && this.Properties.ContainsKey("end_datetime")) { if (this.Properties["start_datetime"] is DateTime? && this.Properties["end_datetime"] is DateTime?) - return new Itenso.TimePeriod.TimeInterval((DateTime)this.Properties["start_datetime"], - (DateTime)this.Properties["end_datetime"]); + { + return new Itenso.TimePeriod.TimeInterval( + (DateTime)this.Properties["start_datetime"], + (DateTime)this.Properties["end_datetime"]); + } + throw new FormatException(string.Format("start_datetime and/or end_datetime are not a valid")); } } } + return Itenso.TimePeriod.TimeInterval.Anytime; } + set { // datetime, start_datetime, end_datetime @@ -128,6 +176,7 @@ public Itenso.TimePeriod.ITimePeriod DateTime this.SetProperty("datetime", null); return; } + // datetime, start_datetime, end_datetime if (value.IsAnytime) { @@ -150,6 +199,5 @@ public Itenso.TimePeriod.ITimePeriod DateTime } } } - } } diff --git a/src/DotNetStac/StacItem.cs b/src/DotNetStac/StacItem.cs index 7b30e830..971cfc2a 100644 --- a/src/DotNetStac/StacItem.cs +++ b/src/DotNetStac/StacItem.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacItem.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; @@ -19,34 +23,50 @@ namespace Stac [JsonObject(MemberSerialization = MemberSerialization.OptIn)] public partial class StacItem : GeoJSON.Net.Feature.Feature, IStacObject, ICloneable { + /// + /// Item Media-Type string + /// public const string MEDIATYPE = "application/geo+json"; - public readonly static ContentType ITEM_MEDIATYPE = new ContentType(MEDIATYPE); + private readonly StacItemRootPropertyContainer _root; + + /// + /// Initializes a new instance of the class. + /// + /// Identifier of the item + /// Geometry of the item + /// Properties of the item [JsonConstructor] - public StacItem(string id, - IGeometryObject geometry, - IDictionary properties = null) : - base(geometry, properties, id) + public StacItem( + string id, + IGeometryObject geometry, + IDictionary properties = null) + : base(geometry, properties, id) { Preconditions.CheckNotNull(id, "id"); - StacExtensions = new SortedSet(); - Root = new StacItemRootPropertyContainer(this); - StacVersion = Versions.StacVersionList.Current; - Links = new ObservableCollection(); - (Links as ObservableCollection).CollectionChanged += LinksCollectionChanged; - Assets = new Dictionary(); - + this.StacExtensions = new SortedSet(); + this._root = new StacItemRootPropertyContainer(this); + this.StacVersion = Versions.StacVersionList.Current; + this.Links = new ObservableCollection(); + (this.Links as ObservableCollection).CollectionChanged += this.LinksCollectionChanged; + this.Assets = new Dictionary(); } - public StacItem(StacItem stacItem) : base(Preconditions.CheckNotNull(stacItem, "stacItem").Geometry, - new Dictionary(Preconditions.CheckNotNull(stacItem).Properties), - Preconditions.CheckNotNull(stacItem, "id").Id) + /// + /// Initializes a new instance of the class. + /// + /// A StacItem to copy + public StacItem(StacItem stacItem) + : base( + Preconditions.CheckNotNull(stacItem, "stacItem").Geometry, + new Dictionary(Preconditions.CheckNotNull(stacItem).Properties), + Preconditions.CheckNotNull(stacItem, "id").Id) { this.StacExtensions = new SortedSet(stacItem.StacExtensions); - this.Root = new StacItemRootPropertyContainer(this); + this._root = new StacItemRootPropertyContainer(this); this.StacVersion = stacItem.StacVersion; this.Links = new ObservableCollection(stacItem.Links.Select(l => new StacLink(l))); - (Links as ObservableCollection).CollectionChanged += LinksCollectionChanged; + (this.Links as ObservableCollection).CollectionChanged += this.LinksCollectionChanged; this.Assets = new Dictionary(stacItem.Assets.Select(a => new KeyValuePair(a.Key, new StacAsset(a.Value, this))) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)); this.Collection = stacItem.Collection; @@ -54,51 +74,22 @@ public StacItem(StacItem stacItem) : base(Preconditions.CheckNotNull(stacItem, " this.CRS = stacItem.CRS; } - private void LinksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (e.OldItems != null) - { - foreach (var oldLink in e.OldItems.Cast()) - { - if (oldLink.RelationshipType == "collection") - { - Collection = null; - } - } - } - if (e.NewItems != null) - { - foreach (var newLink in e.NewItems.Cast()) - { - if (newLink.RelationshipType == "collection" && string.IsNullOrEmpty(Collection)) - { - Collection = Path.GetFileNameWithoutExtension(newLink.Uri.ToString()); - } - } - } - } - - #region IStacObject - /// - /// The STAC version the Item implements + /// Gets or sets the STAC version the Item implements /// - /// [JsonProperty("stac_version", Order = -10)] [JsonConverter(typeof(SemVersionConverter))] public SemVersion StacVersion { get; set; } /// - /// A list of extension identifiers the Item implements + /// Gets a list of extension identifiers the Item implements /// - /// [JsonProperty("stac_extensions", Order = -9)] public ICollection StacExtensions { get; private set; } /// - /// A list of references to other documents. + /// Gets a list of references /// - /// [JsonConverter(typeof(CollectionConverter))] [JsonProperty("links", Order = 5)] public ICollection Links @@ -106,77 +97,109 @@ public ICollection Links get; private set; } + /// [JsonIgnore] - public ContentType MediaType => ITEM_MEDIATYPE; - - # endregion IStacObject + public ContentType MediaType => new ContentType(MEDIATYPE); + /// + /// Gets the assets of the Item + /// [JsonProperty("assets", Order = 4)] public IDictionary Assets { get; private set; } /// - /// The id of the STAC Collection this Item references to + /// Gets or sets the id of the STAC Collection this Item references to /// - /// gets the collection id [JsonProperty("__collection", Required = Required.Default)] [JsonIgnore] public string Collection { - get => Root.GetProperty("collection"); + get => this._root.GetProperty("collection"); set { - if (value != null) Root.SetProperty("collection", value); - else Root.RemoveProperty("collection"); + if (value != null) + { + this._root.SetProperty("collection", value); + } + else + { + this._root.RemoveProperty("collection"); + } } } /// - /// Item root extended data + /// Gets item root extended data /// - /// [JsonExtensionData] - public IDictionary RootProperties { get => Root.Properties; internal set => Root.Properties = value; } + public IDictionary RootProperties { get => this._root.Properties; internal set => this._root.Properties = value; } + + /// + [JsonIgnore] + public IStacObject StacObjectContainer => this; + +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + public bool ShouldSerializeStacExtensions() + { + // don't serialize the Manager property if an employee is their own manager + return this.StacExtensions.Count > 0; + } +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member - private StacItemRootPropertyContainer Root; + /// + public object Clone() + { + return new StacItem(this); + } [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { - foreach (StacLink link in Links) + foreach (StacLink link in this.Links) { link.Parent = this; } - foreach (StacAsset asset in Assets.Values) + + foreach (StacAsset asset in this.Assets.Values) { asset.ParentStacObject = this; } - StacExtensions = new SortedSet(StacExtensions); + + this.StacExtensions = new SortedSet(this.StacExtensions); } [OnSerializing] internal void OnSerializingMethod(StreamingContext context) { - if (BoundingBoxes == null && Geometry != null) - BoundingBoxes = this.GetBoundingBoxFromGeometryExtent(); - + if (this.BoundingBoxes == null && this.Geometry != null) + { + this.BoundingBoxes = this.GetBoundingBoxFromGeometryExtent(); + } } - public bool ShouldSerializeStacExtensions() + private void LinksCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - // don't serialize the Manager property if an employee is their own manager - return StacExtensions.Count > 0; - } + if (e.OldItems != null) + { + foreach (var oldLink in e.OldItems.Cast()) + { + if (oldLink.RelationshipType == "collection") + { + this.Collection = null; + } + } + } - /// - /// Create a new Stac Item from this existing one - /// - /// - public object Clone() - { - return new StacItem(this); + if (e.NewItems != null) + { + foreach (var newLink in e.NewItems.Cast()) + { + if (newLink.RelationshipType == "collection" && string.IsNullOrEmpty(this.Collection)) + { + this.Collection = Path.GetFileNameWithoutExtension(newLink.Uri.ToString()); + } + } + } } - - [JsonIgnore] - public IStacObject StacObjectContainer => this; } } diff --git a/src/DotNetStac/StacItemRootPropertyContainer.cs b/src/DotNetStac/StacItemRootPropertyContainer.cs index 71bfc247..8521232c 100644 --- a/src/DotNetStac/StacItemRootPropertyContainer.cs +++ b/src/DotNetStac/StacItemRootPropertyContainer.cs @@ -1,22 +1,26 @@ -using System.Collections.Generic; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacItemRootPropertyContainer.cs + +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Stac { internal class StacItemRootPropertyContainer : IStacPropertiesContainer { - private readonly StacItem stacItem; - private IDictionary properties; + private readonly StacItem _stacItem; + private IDictionary _properties; public StacItemRootPropertyContainer(StacItem stacItem) { - this.stacItem = stacItem; - properties = new Dictionary(); + this._stacItem = stacItem; + this._properties = new Dictionary(); } - public IDictionary Properties { get => properties; internal set => properties = value; } + public IDictionary Properties { get => this._properties; internal set => this._properties = value; } [ExcludeFromCodeCoverage] - public IStacObject StacObjectContainer => stacItem; + public IStacObject StacObjectContainer => this._stacItem; } } diff --git a/src/DotNetStac/StacLink.cs b/src/DotNetStac/StacLink.cs index 68b4e80b..71fbe3dd 100644 --- a/src/DotNetStac/StacLink.cs +++ b/src/DotNetStac/StacLink.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacLink.cs + +using System; using System.Collections.Generic; using System.Net.Mime; using System.Runtime.Serialization; @@ -6,124 +10,232 @@ namespace Stac { + /// + /// A STAC link + /// [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] [DataContract] - public class StacLink + public class StacLink : ICloneable { - #region Static members - - public static StacLink CreateSelfLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "self", title, mediaType); - } - - public static StacLink CreateRootLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "root", title, mediaType); - } - - public static StacLink CreateParentLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "parent", title, mediaType); - } - - public static StacLink CreateCollectionLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "collection", title, null); - } - - public static StacLink CreateDerivedFromLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "derived_from", title, mediaType); - } - - public static StacLink CreateAlternateLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "alternate", title, mediaType); - } - - public static StacLink CreateChildLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "child", title, mediaType); - } - - public static StacLink CreateItemLink(Uri uri, string mediaType = null, string title = null) - { - return new StacLink(uri, "item", title, mediaType); - } - - public static StacLink CreateObjectLink(IStacObject stacObject, Uri uri) - { - return new StacObjectLink(stacObject, uri); - } - - #endregion - - + /// + /// Initializes a new instance of the class. + /// public StacLink() { } + /// + /// Initializes a new instance of the class. + /// + /// Uri of the link public StacLink(Uri uri) { - Uri = uri; + this.Uri = uri; } + /// + /// Initializes a new instance of the class. + /// + /// Uri of the link + /// Relationship type of the link + /// Title of the link + /// Media type of the link + /// Content length of the link public StacLink(Uri uri, string relationshipType, string title, string mediaType, ulong contentLength = 0) { - Uri = uri; - RelationshipType = relationshipType; - Title = title; - ContentType = mediaType == null ? null : new ContentType(mediaType); + this.Uri = uri; + this.RelationshipType = relationshipType; + this.Title = title; + this.ContentType = mediaType == null ? null : new ContentType(mediaType); this.Length = contentLength; } + /// + /// Initializes a new instance of the class. + /// + /// Source StacLink to clone public StacLink(StacLink source) { if (source == null) + { throw new ArgumentNullException("source"); - Uri = source.Uri; - RelationshipType = source.RelationshipType; - Title = source.Title; - ContentType = source.ContentType; - Parent = source.Parent; - Length = source.Length; + } + + this.Uri = source.Uri; + this.RelationshipType = source.RelationshipType; + this.Title = source.Title; + this.ContentType = source.ContentType; + this.Parent = source.Parent; + this.Length = source.Length; } + /// + /// Gets or sets the Content Type of the link using a string. + /// [JsonProperty("type")] [DataMember(Name = "type")] public string Type { - get => ContentType?.ToString(); - set => ContentType = value == null ? null : new ContentType(value); + get => this.ContentType?.ToString(); + set => this.ContentType = value == null ? null : new ContentType(value); } + /// + /// Gets or sets the Content-Type of the link. + /// [JsonIgnore] [IgnoreDataMember] public virtual ContentType ContentType { get; set; } + /// + /// Gets or sets the relationship type of the link. + /// [JsonProperty("rel", Required = Required.Always)] [DataMember(Name = "rel", IsRequired = true)] public virtual string RelationshipType { get; set; } + /// + /// Gets or sets the title of the link. + /// [JsonProperty("title")] [DataMember(Name = "title")] public virtual string Title { get; set; } + /// + /// Gets or sets the URI of the link. + /// [JsonProperty("href")] [DataMember(Name = "href", IsRequired = true)] public virtual Uri Uri { get; set; } + /// + /// Gets or sets the parent of the link. + /// This is used to resolve relative links. + /// [JsonIgnore] public IStacObject Parent { get; set; } + /// + /// Gets or sets the length of the link. + /// [JsonIgnore] public ulong Length { get; set; } + /// + /// Gets or sets the additional properties of the link. + /// [JsonExtensionData] public IDictionary AdditionalProperties { get; set; } - public virtual StacLink Clone() + /// + /// Create a self link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateSelfLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "self", title, mediaType); + } + + /// + /// Create a root link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateRootLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "root", title, mediaType); + } + + /// + /// Create a parent link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateParentLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "parent", title, mediaType); + } + + /// + /// Create a collection link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateCollectionLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "collection", title, null); + } + + /// + /// Create a derived_from link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateDerivedFromLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "derived_from", title, mediaType); + } + + /// + /// Create an alternate link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateAlternateLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "alternate", title, mediaType); + } + + /// + /// Create a child link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateChildLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "child", title, mediaType); + } + + /// + /// Create an item link. + /// + /// Uri of the link + /// Media type of the link + /// Title of the link + /// StacLink + public static StacLink CreateItemLink(Uri uri, string mediaType = null, string title = null) + { + return new StacLink(uri, "item", title, mediaType); + } + + /// + /// Create a link from a StacObject. + /// + /// StacObject to create a link from + /// Uri of the link + /// StacLink + public static StacLink CreateObjectLink(IStacObject stacObject, Uri uri) + { + return new StacObjectLink(stacObject, uri); + } + + /// + public object Clone() { return new StacLink(this); } diff --git a/src/DotNetStac/StacObjectLink.cs b/src/DotNetStac/StacObjectLink.cs index 7dd10dc1..34269f2c 100644 --- a/src/DotNetStac/StacObjectLink.cs +++ b/src/DotNetStac/StacObjectLink.cs @@ -1,34 +1,49 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacObjectLink.cs + +using System; using System.Net.Mime; using Newtonsoft.Json; namespace Stac { + /// + /// A link to a STAC object + /// public class StacObjectLink : StacLink { - private readonly IStacObject stacObject; + private readonly IStacObject _stacObject; internal StacObjectLink(IStacObject stacObject, Uri uri) { - this.stacObject = stacObject; + this._stacObject = stacObject; if (stacObject is StacItem) + { this.RelationshipType = "item"; + } + if (stacObject is StacCatalog || stacObject is StacCollection) + { this.RelationshipType = "child"; - Uri = uri; + } + + this.Uri = uri; } + /// [JsonProperty("type")] [JsonConverter(typeof(ContentTypeConverter))] public override ContentType ContentType { - get => stacObject.MediaType; + get => this._stacObject.MediaType; set { throw new InvalidOperationException("Cannot set MediaType on an STAC Object link"); } } + /// [JsonProperty("rel")] public override string RelationshipType { @@ -36,16 +51,18 @@ public override string RelationshipType set; } + /// [JsonProperty("title")] public override string Title { - get => stacObject.Title; + get => this._stacObject.Title; set { throw new InvalidOperationException("Cannot set Title on an STAC Object link"); } } + /// [JsonProperty("href")] public override Uri Uri { @@ -53,7 +70,10 @@ public override Uri Uri set; } + /// + /// Gets the STAC object + /// [JsonIgnore] - public IStacObject StacObject => stacObject; + public IStacObject StacObject => this._stacObject; } } diff --git a/src/DotNetStac/StacProvider.cs b/src/DotNetStac/StacProvider.cs index 0367dde1..084f3709 100644 --- a/src/DotNetStac/StacProvider.cs +++ b/src/DotNetStac/StacProvider.cs @@ -1,4 +1,8 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacProvider.cs + +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -7,9 +11,9 @@ namespace Stac { /// - /// The class provides properties about a provider. - /// A provider is any of the organizations that captures or processes the content of the Collection and - /// therefore influences the data offered by this Collection. + /// The class provides properties about a provider. + /// A provider is any of the organizations that captures or processes the content of the Collection and + /// therefore influences the data offered by this Collection. /// May also include information about the final storage provider hosting the data. /// STAC Provider Object /// @@ -17,7 +21,7 @@ namespace Stac public class StacProvider { /// - /// Initialize a new instance of the class. + /// Initializes a new instance of the class. /// /// The name of the organization or the individual. /// Roles of the provider. Any of . @@ -25,21 +29,25 @@ public StacProvider(string name, IEnumerable providerRoles = n { this.Name = name; if (providerRoles != null) - Roles = new Collection(providerRoles.ToList()); + { + this.Roles = new Collection(providerRoles.ToList()); + } else - Roles = new Collection(); + { + this.Roles = new Collection(); + } } /// - /// The name of the organization or the individual. + /// Gets or sets the name of the organization or the individual. /// /// Gets/sets the name [JsonProperty("name")] public string Name { get; set; } /// - /// Multi-line description to add further provider information such as processing details for processors and producers, - /// hosting details for hosts or basic contact information. + /// Gets or sets multi-line description to add further provider information such as processing details for processors and producers, + /// hosting details for hosts or basic contact information. /// CommonMark 0.29 syntax MAY be used for rich text representation. /// /// Gets/sets the description @@ -47,14 +55,14 @@ public StacProvider(string name, IEnumerable providerRoles = n public string Description { get; set; } /// - /// Roles of the provider. Any of . + /// Gets roles of the provider. Any of . /// /// Gets the roles collection [JsonProperty("roles")] public Collection Roles { get; private set; } /// - /// Homepage on which the provider describes the dataset and publishes contact information. + /// Gets or sets homepage on which the provider describes the dataset and publishes contact information. /// /// Gets/sets the URL [JsonProperty("url")] @@ -64,7 +72,7 @@ public StacProvider(string name, IEnumerable providerRoles = n public bool ShouldSerializeRoles() { // don't serialize the Manager property if an employee is their own manager - return Roles.Count > 0; + return this.Roles.Count > 0; } } } diff --git a/src/DotNetStac/StacProviderRole.cs b/src/DotNetStac/StacProviderRole.cs index bb6211f2..59173a9f 100644 --- a/src/DotNetStac/StacProviderRole.cs +++ b/src/DotNetStac/StacProviderRole.cs @@ -1,4 +1,8 @@ -using Newtonsoft.Json; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacProviderRole.cs + +using Newtonsoft.Json; using Newtonsoft.Json.Converters; namespace Stac @@ -9,14 +13,28 @@ namespace Stac [JsonConverter(typeof(StringEnumConverter))] public enum StacProviderRole { +#pragma warning disable SA1300 // Element should begin with upper-case letter +#pragma warning disable SA1602 // EnumerationItemsMustBeDocumented + /// /// The organization that is licensing the dataset under the license specified in the Collection's field. + /// licensor, + + /// /// The producer of the data is the provider that initially captured and processed the source data, e.g. ESA for Sentinel-2 data. + /// producer, + + /// /// A processor is any provider who processed data to a derived product. + /// processor, - /// The host is the actual provider offering the data on their storage. There should be no more than one host, specified as last element of the list. - host + /// + /// The host is the actual provider offering the data on their storage. There should be no more than one host, specified as last element of the list. + /// + host, +#pragma warning restore SA1602 // EnumerationItemsMustBeDocumented +#pragma warning restore SA1300 // Element should begin with upper-case letter } } diff --git a/src/DotNetStac/StyleCop.ruleset b/src/DotNetStac/StyleCop.ruleset index d8dc112c..5bab8f83 100644 --- a/src/DotNetStac/StyleCop.ruleset +++ b/src/DotNetStac/StyleCop.ruleset @@ -72,16 +72,23 @@ + + + - + + + + + diff --git a/src/DotNetStac/Utils.cs b/src/DotNetStac/Utils.cs index c80b400a..acf4702a 100644 --- a/src/DotNetStac/Utils.cs +++ b/src/DotNetStac/Utils.cs @@ -1,8 +1,11 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: Utils.cs + +using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Stac.Exceptions; -using Stac.Extensions.ItemCollections; namespace Stac { @@ -24,33 +27,29 @@ public static Type IdentifyStacType(string json) /// /// Identify the STAC object from a JObject /// - /// JObject + /// JObject /// STAC Type - public static Type IdentifyStacType(JObject jObject) + public static Type IdentifyStacType(JObject jsonObject) { - if (jObject.Value("type") == "Feature") + if (jsonObject.Value("type") == "Feature") { return typeof(StacItem); } - else if (jObject.Value("type") == "FeatureCollection") - { - return typeof(ItemCollection); - } - else if (jObject.Value("type") == "Collection" || jObject["extent"] != null || jObject["license"] != null) + else if (jsonObject.Value("type") == "Collection" || jsonObject["extent"] != null || jsonObject["license"] != null) { return typeof(StacCollection); } - else if (jObject.Value("type") == "Catalog" || jObject["description"] != null) + else if (jsonObject.Value("type") == "Catalog" || jsonObject["description"] != null) { return typeof(StacCatalog); } - else if (jObject.ContainsKey("links") && jObject["links"].Type == JTokenType.Array) + else if (jsonObject.ContainsKey("links") && jsonObject["links"].Type == JTokenType.Array) { return typeof(SimpleLinksCollectionObject); } else { - throw new InvalidStacDataException($"{jObject.Value("id")}. Unknown data"); + throw new InvalidStacDataException($"{jsonObject.Value("id")}. Unknown data"); } } } diff --git a/src/DotNetStac/Versions/StacVersionList.cs b/src/DotNetStac/Versions/StacVersionList.cs index a869551a..0c30c797 100644 --- a/src/DotNetStac/Versions/StacVersionList.cs +++ b/src/DotNetStac/Versions/StacVersionList.cs @@ -1,10 +1,17 @@ -using System; +// Copyright (c) by Terradue Srl. All Rights Reserved. +// License under the AGPL, Version 3.0. +// File Name: StacVersionList.cs + using Semver; namespace Stac.Versions { + /// + /// List of STAC versions + /// public static class StacVersionList { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static SemVersion Current => V100; public static SemVersion V100 => new SemVersion(1, 0, 0); @@ -22,5 +29,6 @@ public static class StacVersionList public static SemVersion V060 => new SemVersion(0, 6, 0); public static SemVersion V070 => new SemVersion(0, 7, 0); +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } }