From 52bc04512feb5c8ae15617be3f59e0a372e60558 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 10:53:04 +0200 Subject: [PATCH 01/32] fixed typo --- pystac/extensions/mlm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 31d74993d..c45e02025 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -123,7 +123,7 @@ class TaskType(StringEnum): PANOPTIC_SEGMENTATION = "panoptic-segmentation" SIMILARITY_SEARCH = "similarity-search" GENERATIVE = "generative" - IAMGE_CAPTIONING = "image-captioning" + IMAGE_CAPTIONING = "image-captioning" SUPER_RESOLUTION = "super-resolution" From fdb916489db78b041c452cfd92537b812e6ed4cf Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 10:57:12 +0200 Subject: [PATCH 02/32] fixed enum values --- pystac/extensions/mlm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index c45e02025..39027abe2 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -148,8 +148,8 @@ class ResizeType(StringEnum): CROP = "crop" PAD = "pad" - INTERPOLATION_NEAREST = "interpolate-nearest" - INTERPOLATION_LINEAR = "interpolate-linear" + INTERPOLATION_NEAREST = "interpolation-nearest" + INTERPOLATION_LINEAR = "interpolation-linear" INTERPOLATION_CUBIC = "interpolation-cubic" INTERPOLATION_AREA = "interpolation-area" INTERPOLATION_LANCZOS4 = "interpolation-lanczos4" From bd4d736277da40fa7f876a76f53ac0c1fafe8676 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 11:00:18 +0200 Subject: [PATCH 03/32] fixed property name for error message # Conflicts: # pystac/extensions/mlm.py --- pystac/extensions/mlm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 39027abe2..4449a62a2 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -1118,7 +1118,7 @@ def data_type(self) -> DataType: get_required( self.properties.get(DATA_TYPE_RESULT_STRUCTURE_PROP), self, - DIM_ORDER_RESULT_STRUCTURE_PROP, + DATA_TYPE_RESULT_STRUCTURE_PROP, ), ) From 631db213231bce511e91414f7980dda31539ed3d Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 11:07:17 +0200 Subject: [PATCH 04/32] fix: pop max value --- pystac/extensions/mlm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 4449a62a2..a18eb31c0 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -573,7 +573,7 @@ def maximum(self, v: int | float | None) -> None: if v is not None: self.properties[MAXIMUM_VALUE_SCALING_PROP] = v else: - self.properties.get(MAXIMUM_VALUE_SCALING_PROP, None) + self.properties.pop(MAXIMUM_VALUE_SCALING_PROP, None) @property def mean(self) -> int | float | None: From c3103ddcc4cde4d16be9772b748f436c86ee3ed2 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 11:09:53 +0200 Subject: [PATCH 05/32] fix docstring typo --- pystac/extensions/mlm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index a18eb31c0..130172415 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -160,7 +160,7 @@ class ResizeType(StringEnum): class ValueScalingType(StringEnum): """ - An enumeratino of Value Scaling operations supported by the extension + An enumeration of Value Scaling operations supported by the extension """ MIN_MAX = "min-max" From 6800390617ebf9df11c2fe5f8ce5df74b3303b57 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 11:34:16 +0200 Subject: [PATCH 06/32] fix value_scaling property type in ModelInput --- pystac/extensions/mlm.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 130172415..9af9dce2c 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -799,7 +799,7 @@ def apply( bands: list[ModelBand] | list[str], input: InputStructure, description: str | None = None, - value_scaling: ValueScaling | None = None, + value_scaling: list[ValueScaling] | None = None, resize_type: ResizeType | None = None, pre_processing_function: ProcessingExpression | None = None, ) -> None: @@ -850,7 +850,7 @@ def create( bands: list[ModelBand] | list[str], input: InputStructure, description: str | None = None, - value_scaling: ValueScaling | None = None, + value_scaling: list[ValueScaling] | None = None, resize_type: ResizeType | None = None, pre_processing_function: ProcessingExpression | None = None, ) -> ModelInput: @@ -970,18 +970,18 @@ def description(self, v: str | None) -> None: self.properties.pop(DESCRIPTION_INPUT_OBJECT_PROP, None) @property - def value_scaling(self) -> ValueScaling | None: + def value_scaling(self) -> list[ValueScaling] | None: """ Gets or sets the value_scaling property of this ModelInput object """ - v = self.properties.get(VALUE_SCALING_INPUT_OBJECT_PROP) - return ValueScaling(v) if v is not None else v + v_list = self.properties.get(VALUE_SCALING_INPUT_OBJECT_PROP) + return [ValueScaling(v) for v in v_list] if v_list is not None else None @value_scaling.setter - def value_scaling(self, v: ValueScaling | None) -> None: + def value_scaling(self, v: list[ValueScaling] | None) -> None: # add None to properties dict and do not pop it, according to specification self.properties[VALUE_SCALING_INPUT_OBJECT_PROP] = ( - None if v is None else v.to_dict() + None if v is None else [v_entry.to_dict() for v_entry in v] ) @property From 1424cd7e4ce16c238a83e63fc95633127a2d984e Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Apr 2025 11:44:08 +0200 Subject: [PATCH 07/32] change tests for value_scaling --- tests/extensions/test_mlm.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index cb7090fe7..8415b9d0f 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -232,19 +232,19 @@ def test_model_input_structure_props() -> None: input_testdata = [ ( ["B02", "B03", "B04"], - ValueScaling.create(ValueScalingType.SCALE, value=3), + [ValueScaling.create(ValueScalingType.SCALE, value=3)], ResizeType.CROP, ProcessingExpression.create("python", "asdf"), ), ( ["B02", "B03", "B04"], - ValueScaling.create(ValueScalingType.SCALE, value=3), + [ValueScaling.create(ValueScalingType.SCALE, value=3)], None, ProcessingExpression.create("python", "asdf"), ), ( [ModelBand.create("B02"), ModelBand.create("B03"), ModelBand.create("B04")], - ValueScaling.create(ValueScalingType.SCALE, value=3), + [ValueScaling.create(ValueScalingType.SCALE, value=3)], ResizeType.CROP, ProcessingExpression.create("python", "asdf"), ), @@ -256,7 +256,7 @@ def test_model_input_structure_props() -> None: ), ( ["B02", "B03", "B04"], - ValueScaling.create(ValueScalingType.SCALE, value=3), + [ValueScaling.create(ValueScalingType.SCALE, value=3)], ResizeType.CROP, None, ), @@ -268,7 +268,7 @@ def test_model_input_structure_props() -> None: ) def test_model_input( bands: list[str] | list[ModelBand], - value_scaling: ValueScaling | None, + value_scaling: list[ValueScaling] | None, resize_type: ResizeType | None, pre_processing_function: ProcessingExpression | None, ) -> None: @@ -323,7 +323,7 @@ def test_model_input_props() -> None: assert c.input == inp assert c.value_scaling is None - val_obj = ValueScaling.create(ValueScalingType.SCALE, value=3) + val_obj = [ValueScaling.create(ValueScalingType.SCALE, value=3)] c.value_scaling = val_obj assert c.value_scaling == val_obj From 707a5f2b962cf089b1f628cba3d1d9b56f790d2e Mon Sep 17 00:00:00 2001 From: = Date: Wed, 23 Apr 2025 17:44:05 +0200 Subject: [PATCH 08/32] fix: added missing migrations --- pystac/extensions/mlm.py | 78 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 9af9dce2c..52f3536e4 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2052,11 +2052,89 @@ class MLMExtensionHooks(ExtensionHooks): } stac_object_types = {pystac.STACObjectType.ITEM, pystac.STACObjectType.COLLECTION} + @staticmethod + def _migrate_1_0_to_1_1(obj: dict[str, Any]) -> None: + if "mlm:framework" in obj["properties"]: + if obj["properties"]["mlm:framework"] == "Scikit-learn": + obj["properties"]["mlm:framework"] = "scikit-learn" + if obj["properties"]["mlm:framework"] == "Huggingface": + obj["properties"]["mlm:framework"] = "Hugging Face" + + @staticmethod + def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: + pass + + @staticmethod + def _migrate_1_2_to_1_3(obj: dict[str, Any]) -> None: + pass + + @staticmethod + def _migrate_1_3_to_1_4(obj: dict[str, Any]) -> None: + for input_obj in obj["properties"]["mlm:input"]: + if "norm_type" in input_obj and input_obj["norm_type"] is not None: + norm_type = input_obj["norm_type"] + value_scaling_list = [] + if norm_type == "min-max": + for band_statistic in input_obj["statistics"]: + value_scaling_obj = { + "type": "min-max", + "minimum": band_statistic["minimum"], + "maximum": band_statistic["maximum"], + } + value_scaling_list.append(value_scaling_obj) + elif norm_type == "z-score": + for band_statistic in input_obj["statistics"]: + value_scaling_obj = { + "type": "z-score", + "mean": band_statistic["mean"], + "stddev": band_statistic["stddev"], + } + value_scaling_list.append(value_scaling_obj) + elif norm_type == "clip": + for clip_value in input_obj["norm_clip"]: + value_scaling_obj = { + "type": "processing", + "format": "gdal-calc", + "expression": f"numpy.clip(A / {clip_value}, 0, 1)", + } + value_scaling_list.append(value_scaling_obj) + else: + raise NotImplementedError( + f"Normalization type {norm_type} is not supported in stac:mlm" + f" >= 1.3. Therefore an automatic migration is not possible. " + f"Please migrate this normalization manually using " + f'type="processing".' + ) + input_obj["value_scaling"] = value_scaling_list + input_obj.pop("norm_by_channel", None) + input_obj.pop("norm_type", None) + input_obj.pop("norm_clip", None) + input_obj.pop("statistics", None) + def migrate( self, obj: dict[str, Any], version: STACVersionID, info: STACJSONDescription ) -> None: # mo adjustments to objects needed when migrating yet # schema back to v1.0 is fully backwards compatible + + if SCHEMA_URI_PATTERN.format(version="1.0.0") in info.extensions: + self._migrate_1_0_to_1_1(obj) + self._migrate_1_1_to_1_2(obj) + self._migrate_1_2_to_1_3(obj) + self._migrate_1_3_to_1_4(obj) + + if SCHEMA_URI_PATTERN.format(version="1.1.0") in info.extensions: + self._migrate_1_1_to_1_2(obj) + self._migrate_1_2_to_1_3(obj) + self._migrate_1_3_to_1_4(obj) + + if SCHEMA_URI_PATTERN.format(version="1.2.0") in info.extensions: + self._migrate_1_2_to_1_3(obj) + self._migrate_1_3_to_1_4(obj) + + if SCHEMA_URI_PATTERN.format(version="1.3.0") in info.extensions: + self._migrate_1_3_to_1_4(obj) + super().migrate(obj, version, info) From d450c565e5ab379387d395b46c9e5dca24e2c556 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 23 Apr 2025 17:45:47 +0200 Subject: [PATCH 09/32] added testing of migrations --- tests/extensions/test_mlm.py | 125 +++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 8415b9d0f..0c30aff45 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -20,6 +20,7 @@ InputStructure, ItemMLMExtension, MLMExtension, + MLMExtensionHooks, ModelBand, ModelInput, ModelOutput, @@ -1071,3 +1072,127 @@ def test_raise_exception_on_mlm_extension_and_asset() -> None: ) with pytest.raises(TypeError): MLMExtension.ext(asset, add_if_missing=False) + + +@pytest.mark.parametrize( + "framework_old, framework_new", + ((None, None), ("Scikit-learn", "scikit-learn"), ("Huggingface", "Hugging Face")), +) +def test_migration_1_0_to_1_1( + framework_old: None | str, framework_new: None | str +) -> None: + data: dict[str, Any] = {"properties": {}} + + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert "mlm:framework" not in data["properties"] + + data["properties"]["mlm:framework"] = framework_old + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert data["properties"]["mlm:framework"] == framework_new + + +@pytest.mark.parametrize( + ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), + ( + (None, None, None, None, None), + (False, None, None, None, None), + ( + False, + "z-score", + None, + [{"mean": 5, "stddev": 2}], + [ValueScaling.create(ValueScalingType.Z_SCORE, mean=5, stddev=2)], + ), + ( + False, + "min-max", + None, + [{"minimum": 10, "maximum": 20}], + [ValueScaling.create(ValueScalingType.MIN_MAX, minimum=10, maximum=20)], + ), + ( + True, + "z-score", + None, + [ + {"mean": 5, "stddev": 2}, + {"mean": 6, "stddev": 3}, + {"mean": 10, "stddev": 1}, + ], + [ + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=5, stddev=2), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=6, stddev=3), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=10, stddev=1), + ], + ), + ( + True, + "clip", + [3, 4, 5], + None, + [ + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 3, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 4, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 5, 0, 1)", + ), + ], + ), + ), +) +def test_migration_1_3_to_1_4( + norm_by_channel: bool | None, + norm_type: str | None, + norm_clip: list[int] | None, + statistics: list[dict[str, Any]] | None, + value_scaling: list[ValueScaling] | None, +) -> None: + data: dict[str, Any] = {"properties": {"mlm:input": []}} + MLMExtensionHooks._migrate_1_3_to_1_4(data) # nothing is supposed to happen here + + input_obj: dict[str, Any] = {} + if norm_by_channel is not None: + input_obj["norm_by_channel"] = norm_by_channel + if norm_type is not None: + input_obj["norm_type"] = norm_type + if norm_clip is not None: + input_obj["norm_clip"] = norm_clip + if statistics is not None: + input_obj["statistics"] = statistics + data["properties"]["mlm:input"].append(input_obj) + + MLMExtensionHooks._migrate_1_3_to_1_4(data) + if norm_type is not None and value_scaling is not None: + assert len(data["properties"]["mlm:input"][0]["value_scaling"]) == len( + value_scaling + ) + assert data["properties"]["mlm:input"][0]["value_scaling"] == [ + obj.to_dict() for obj in value_scaling + ] + + new_input_obj = data["properties"]["mlm:input"] + assert "norm_by_channel" not in new_input_obj + assert "norm_type" not in new_input_obj + assert "norm_clip" not in new_input_obj + assert "statistics" not in new_input_obj + + +@pytest.mark.parametrize( + "norm_type", + ("l1", "l2", "l2sqr", "hamming", "hamming2", "type-mask", "relative", "inf"), +) +def test_migration_1_3_to_1_4_failure(norm_type: str) -> None: + data: dict[str, Any] = {"properties": {"mlm:input": [{"norm_type": norm_type}]}} + + with pytest.raises(NotImplementedError): + MLMExtensionHooks._migrate_1_3_to_1_4(data) From 21eb6c706ba0cc8a9f40b78e909681e525c55907 Mon Sep 17 00:00:00 2001 From: = Date: Thu, 24 Apr 2025 16:49:09 +0200 Subject: [PATCH 10/32] added regex constraint for mlm:framework to migration --- pystac/extensions/mlm.py | 30 ++++++++++++++++++++++++++++++ tests/extensions/test_mlm.py | 24 ++++++++++++++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 52f3536e4..28b9b409a 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -8,6 +8,7 @@ from __future__ import annotations +import warnings from abc import ABC from collections.abc import Iterable from typing import Any, Generic, Literal, TypeVar, cast @@ -2055,10 +2056,39 @@ class MLMExtensionHooks(ExtensionHooks): @staticmethod def _migrate_1_0_to_1_1(obj: dict[str, Any]) -> None: if "mlm:framework" in obj["properties"]: + framework = obj["properties"]["mlm:framework"] + # remove invalid characters at beginning and end + forbidden_chars = [".", "_", "-", " ", "\t", "\n", "\r", "\f", "\v"] + if framework[0] in forbidden_chars or framework[-1] in forbidden_chars: + warnings.warn( + "Value for mlm:framework is invalid in mlm>=1.1, as it must" + "not start or end with one of the following characters: " + "._- and whitespace. These characters are therefore removed while" + "migrating the STAC object to v1.1.", + SyntaxWarning, + ) + while obj["properties"]["mlm:framework"][0] in forbidden_chars: + new_str = obj["properties"]["mlm:framework"][1:] + obj["properties"]["mlm:framework"] = new_str + while obj["properties"]["mlm:framework"][-1] in forbidden_chars: + new_str = obj["properties"]["mlm:framework"][:-1] + obj["properties"]["mlm:framework"] = new_str + + # rename frameworks if obj["properties"]["mlm:framework"] == "Scikit-learn": obj["properties"]["mlm:framework"] = "scikit-learn" + warnings.warn( + "mlm:framework value Scikit-learn is no longer valid in mlm>=1.1. " + "Renaming it to scikit-learn", + SyntaxWarning, + ) if obj["properties"]["mlm:framework"] == "Huggingface": obj["properties"]["mlm:framework"] = "Hugging Face" + warnings.warn( + "mlm:framework value Huggingface is no longer valid in mlm>=1.1. " + "Renaming it to Hugging Face", + SyntaxWarning, + ) @staticmethod def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 0c30aff45..00e4fb91a 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1,5 +1,6 @@ import json import logging +import re from copy import deepcopy from typing import Any, cast @@ -1075,20 +1076,35 @@ def test_raise_exception_on_mlm_extension_and_asset() -> None: @pytest.mark.parametrize( - "framework_old, framework_new", - ((None, None), ("Scikit-learn", "scikit-learn"), ("Huggingface", "Hugging Face")), + "framework_old, framework_new, valid", + ( + ("Scikit-learn", "scikit-learn", False), + ("Huggingface", "Hugging Face", False), + ("-_ .asdf", "asdf", False), + ("asdf-_ .", "asdf", False), + ("-._ asdf-.", "asdf", False), + ("test_framework", "test_framework", True), + ), ) def test_migration_1_0_to_1_1( - framework_old: None | str, framework_new: None | str + framework_old: None | str, framework_new: None | str, valid: bool ) -> None: data: dict[str, Any] = {"properties": {}} MLMExtensionHooks._migrate_1_0_to_1_1(data) assert "mlm:framework" not in data["properties"] + pattern = r"^(?=[^\s._\-]).*[^\s._\-]$" data["properties"]["mlm:framework"] = framework_old - MLMExtensionHooks._migrate_1_0_to_1_1(data) + + if valid: + MLMExtensionHooks._migrate_1_0_to_1_1(data) + else: + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert data["properties"]["mlm:framework"] == framework_new + assert bool(re.match(pattern, data["properties"]["mlm:framework"])) @pytest.mark.parametrize( From 6ca98f0c7d0ae596f3c8162ddf676437c501845e Mon Sep 17 00:00:00 2001 From: = Date: Fri, 25 Apr 2025 13:40:46 +0200 Subject: [PATCH 11/32] added migration from 1.1 to 1.2 --- pystac/extensions/mlm.py | 13 ++++++++++++- tests/extensions/test_mlm.py | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 28b9b409a..38aea18a6 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2092,7 +2092,18 @@ def _migrate_1_0_to_1_1(obj: dict[str, Any]) -> None: @staticmethod def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: - pass + if "assets" not in obj: + return + assets = obj["assets"] + model_in_assets = any( + ["mlm:model" in assets[asset]["roles"] for asset in assets] + ) + if not model_in_assets: + raise pystac.errors.STACError( + 'Error migrating stac:mlm version: An asset with role "mlm:model" is ' + "required in mlm>=1.2. Include at least one asset with role " + '"mlm:model" ' + ) @staticmethod def _migrate_1_2_to_1_3(obj: dict[str, Any]) -> None: diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 00e4fb91a..1e9a6fb80 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1107,6 +1107,20 @@ def test_migration_1_0_to_1_1( assert bool(re.match(pattern, data["properties"]["mlm:framework"])) +def test_migration_1_1_to_1_2() -> None: + data: dict[str, Any] = {} + MLMExtensionHooks._migrate_1_1_to_1_2(data) + + data["assets"] = {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["labels"]}} + + with pytest.raises(pystac.errors.STACError): + MLMExtensionHooks._migrate_1_1_to_1_2(data) + + data["assets"]["asset3"] = {"roles": ["mlm:model"]} + + MLMExtensionHooks._migrate_1_1_to_1_2(data) + + @pytest.mark.parametrize( ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), ( From 117dac3eb380ed46ad66f2ca70fc3b090f74c610 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 25 Apr 2025 15:50:59 +0200 Subject: [PATCH 12/32] added migration from 1.2 to 1.3 --- pystac/extensions/mlm.py | 26 ++++++++++++++- tests/extensions/test_mlm.py | 63 ++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 38aea18a6..2f4969f55 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2107,7 +2107,31 @@ def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: @staticmethod def _migrate_1_2_to_1_3(obj: dict[str, Any]) -> None: - pass + bands_obj = obj["properties"]["mlm:input"] + + if not bands_obj: + return + + if "raster:bands" not in obj["properties"]: + return + raster_bands = obj["properties"]["raster:bands"] + + # make sure all raster_bands have a name prop with length>0 + names_properties_valid = all( + "name" in band and len(band["name"]) > 0 for band in raster_bands + ) + if not names_properties_valid: + raise STACError( + "Error migrating stac:mlm version: In mlm>=1.3, each band in " + 'raster:bands is required to have a property "name"' + ) + + # copy the raster:bands to assets + for asset_name in obj["assets"]: + asset = obj["assets"][asset_name] + if "mlm:model" not in asset["roles"]: + continue + asset["raster:bands"] = raster_bands @staticmethod def _migrate_1_3_to_1_4(obj: dict[str, Any]) -> None: diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 1e9a6fb80..5fddf167e 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1121,6 +1121,69 @@ def test_migration_1_1_to_1_2() -> None: MLMExtensionHooks._migrate_1_1_to_1_2(data) +@pytest.mark.parametrize( + "inp_bands, raster_bands, valid", + ( + ([], None, True), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "B03", "data_type": "float64"}, + ], + True, + ), + ( + ["B02", "B03"], + [ + {"name": "", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [{"name": "B02", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + ( + ["B02", "B03"], + [{"name": "", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + (["B02", "B03"], [{"data_type": "float64"}, {"data_type": "float64"}], False), + ), +) +def test_migration_1_2_to_1_3( + inp_bands: list[str], raster_bands: list[dict[str, Any]], valid: bool +) -> None: + data: dict[str, Any] = { + "properties": {"mlm:input": {}}, + "assets": {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["mlm:model"]}}, + } + + if inp_bands: + data["properties"]["mlm:input"]["bands"] = inp_bands + data["properties"]["raster:bands"] = raster_bands + + if valid: + MLMExtensionHooks._migrate_1_2_to_1_3(data) + if raster_bands: + assert "raster:bands" not in data["assets"]["asset1"] + assert "raster:bands" in data["assets"]["asset2"] + else: + with pytest.raises(STACError): + MLMExtensionHooks._migrate_1_2_to_1_3(data) + + @pytest.mark.parametrize( ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), ( From 25bc3ea1d99fef8567c6cd4e099566fe432d4225 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 25 Apr 2025 16:50:02 +0200 Subject: [PATCH 13/32] migrate now forbidden properties in assets --- pystac/extensions/mlm.py | 104 +++++++++++++++++++++-------------- tests/extensions/test_mlm.py | 33 ++++++++++- 2 files changed, 96 insertions(+), 41 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 2f4969f55..22990f8f0 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2135,46 +2135,70 @@ def _migrate_1_2_to_1_3(obj: dict[str, Any]) -> None: @staticmethod def _migrate_1_3_to_1_4(obj: dict[str, Any]) -> None: - for input_obj in obj["properties"]["mlm:input"]: - if "norm_type" in input_obj and input_obj["norm_type"] is not None: - norm_type = input_obj["norm_type"] - value_scaling_list = [] - if norm_type == "min-max": - for band_statistic in input_obj["statistics"]: - value_scaling_obj = { - "type": "min-max", - "minimum": band_statistic["minimum"], - "maximum": band_statistic["maximum"], - } - value_scaling_list.append(value_scaling_obj) - elif norm_type == "z-score": - for band_statistic in input_obj["statistics"]: - value_scaling_obj = { - "type": "z-score", - "mean": band_statistic["mean"], - "stddev": band_statistic["stddev"], - } - value_scaling_list.append(value_scaling_obj) - elif norm_type == "clip": - for clip_value in input_obj["norm_clip"]: - value_scaling_obj = { - "type": "processing", - "format": "gdal-calc", - "expression": f"numpy.clip(A / {clip_value}, 0, 1)", - } - value_scaling_list.append(value_scaling_obj) - else: - raise NotImplementedError( - f"Normalization type {norm_type} is not supported in stac:mlm" - f" >= 1.3. Therefore an automatic migration is not possible. " - f"Please migrate this normalization manually using " - f'type="processing".' - ) - input_obj["value_scaling"] = value_scaling_list - input_obj.pop("norm_by_channel", None) - input_obj.pop("norm_type", None) - input_obj.pop("norm_clip", None) - input_obj.pop("statistics", None) + # Migrate to value_scaling + if "mlm:input" in obj["properties"]: + for input_obj in obj["properties"]["mlm:input"]: + if "norm_type" in input_obj and input_obj["norm_type"] is not None: + norm_type = input_obj["norm_type"] + value_scaling_list = [] + if norm_type == "min-max": + for band_statistic in input_obj["statistics"]: + value_scaling_obj = { + "type": "min-max", + "minimum": band_statistic["minimum"], + "maximum": band_statistic["maximum"], + } + value_scaling_list.append(value_scaling_obj) + elif norm_type == "z-score": + for band_statistic in input_obj["statistics"]: + value_scaling_obj = { + "type": "z-score", + "mean": band_statistic["mean"], + "stddev": band_statistic["stddev"], + } + value_scaling_list.append(value_scaling_obj) + elif norm_type == "clip": + for clip_value in input_obj["norm_clip"]: + value_scaling_obj = { + "type": "processing", + "format": "gdal-calc", + "expression": f"numpy.clip(A / {clip_value}, 0, 1)", + } + value_scaling_list.append(value_scaling_obj) + else: + raise NotImplementedError( + f"Normalization type {norm_type} is not supported in " + f"stac:mlm >= 1.3. Therefore an automatic migration is not " + f"possible. Please migrate this normalization manually " + f'using type="processing".' + ) + input_obj["value_scaling"] = value_scaling_list + input_obj.pop("norm_by_channel", None) + input_obj.pop("norm_type", None) + input_obj.pop("norm_clip", None) + input_obj.pop("statistics", None) + + if "assets" in obj: + for asset in obj["assets"]: + # move forbidden fields from asset to properties + if "mlm:name" in obj["assets"][asset]: + obj["properties"]["mlm:name"] = obj["assets"][asset]["mlm:name"] + obj["assets"][asset].pop("mlm:name") + if "mlm:input" in obj["assets"][asset]: + obj["properties"]["mlm:input"] = obj["assets"][asset]["mlm:input"] + obj["assets"][asset].pop("mlm:input") + if "mlm:output" in obj["assets"][asset]: + obj["properties"]["mlm:output"] = obj["assets"][asset]["mlm:output"] + obj["assets"][asset].pop("mlm:output") + if "mlm:hyperparameters" in obj["assets"][asset]: + obj["properties"]["mlm:hyperparameters"] = obj["assets"][asset][ + "mlm:hyperparameters" + ] + obj["assets"][asset].pop("mlm:hyperparameters") + + # add new REQUIRED proretie mlm:artifact_type to asset + if "mlm:model" in obj["assets"][asset]["roles"]: + obj["assets"][asset]["mlm:artifact_type"] = "" def migrate( self, obj: dict[str, Any], version: STACVersionID, info: STACJSONDescription diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 5fddf167e..00af52053 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1243,7 +1243,7 @@ def test_migration_1_2_to_1_3( ), ), ) -def test_migration_1_3_to_1_4( +def test_migration_1_3_to_1_4_value_scaling( norm_by_channel: bool | None, norm_type: str | None, norm_clip: list[int] | None, @@ -1289,3 +1289,34 @@ def test_migration_1_3_to_1_4_failure(norm_type: str) -> None: with pytest.raises(NotImplementedError): MLMExtensionHooks._migrate_1_3_to_1_4(data) + + +def test_migration_1_3_to_1_4_assets() -> None: + data: dict[str, Any] = { + "properties": {}, + "assets": { + "asset1": { + "mlm:name": "asdf", + "mlm:input": {}, + "mlm:output": {}, + "mlm:hyperparameters": {}, + "roles": ["mlm:model"], + } + }, + } + + MLMExtensionHooks._migrate_1_3_to_1_4(data) + + assert "mlm:name" not in data["assets"]["asset1"] + assert "mlm:name" in data["properties"] + + assert "mlm:input" not in data["assets"]["asset1"] + assert "mlm:input" in data["properties"] + + assert "mlm:output" not in data["assets"]["asset1"] + assert "mlm:output" in data["properties"] + + assert "mlm:hyperparameters" not in data["assets"]["asset1"] + assert "mlm:hyperparameters" in data["properties"] + + assert "mlm:artifact_type" in data["assets"]["asset1"] From 71e5d1e43c2cfebf80ded6a08a6cc87d7010e308 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 12:19:26 +0200 Subject: [PATCH 14/32] fix: added missing parameter to docstring --- pystac/extensions/mlm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 22990f8f0..8ea25e6af 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -1204,7 +1204,7 @@ def create( Creates a new Output Args: - name:Name of the output variable defined by the model. If no explicit name + name: Name of the output variable defined by the model. If no explicit name is defined by the model, an informative name (e.g.: "CLASSIFICATION") can be used instead. tasks: Specifies the Machine Learning tasks for which the output can be used @@ -1214,6 +1214,7 @@ def create( from one model head. description: Additional details about the output such as describing its purpose or expected result that cannot be represented by other properties. + description: Description of output. classes: A list of class objects adhering to the Classification Extension. post_processing_function: Custom postprocessing function where normalization, rescaling, or any other significant operations takes From 420f876e8dcc78de0854e84b1f2f7c9129e42454 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 13:59:18 +0200 Subject: [PATCH 15/32] refactor: move properties to parent classes --- pystac/extensions/mlm.py | 343 ++++++++++++++++++++------------------- 1 file changed, 176 insertions(+), 167 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 8ea25e6af..747a7736c 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -1364,156 +1364,68 @@ def to_dict(self) -> dict[str, Any]: return self.properties -class MLMExtension( - Generic[T], - PropertiesExtension, - ExtensionManagementMixin[pystac.Item | pystac.Collection], -): - """An abstract class that can be used to extend to properties of an - :class:`pystac.Item` or :class:`pystac.Collection` with properties from the - :stac-ext:`Machine Learning Model Extension `. - - This class can be used to extend :class:`pystac.Item`, :class:`pystac.Collection` - and :class:`pystac.ItemAssetDefinition`. For extending :class:`pystac.Asset`, use - either :class:`~AssetGeneralMLMExtension`: or :class:`AssetDetailedMLMExtension`. - """ - - name: Literal["mlm"] = "mlm" +class _ExcludedFromAssetProps(PropertiesExtension): properties: dict[str, Any] - def apply( - self, - name: str, - architecture: str, - tasks: list[TaskType], - input: list[ModelInput], - output: list[ModelOutput], - framework: str | None = None, - framework_version: str | None = None, - memory_size: int | None = None, - total_parameters: int | None = None, - pretrained: bool | None = None, - pretrained_source: str | None = None, - batch_size_suggestion: int | None = None, - accelerator: AcceleratorType | None = None, - accelerator_constrained: bool | None = None, - accelerator_summary: str | None = None, - accelerator_count: int | None = None, - hyperparameters: Hyperparameters | None = None, - *args: Any, - **kwargs: Any, - ) -> None: + @property + def mlm_name(self) -> str: """ - Sets the properties of a new MLMExtension - - Args: - name: name for the model - architecture: A generic and well established architecture name of the model - tasks: Specifies the Machine Learning tasks for which the model can be - used for - input: Describes the transformation between the EO data and the model input - output: Describes each model output and how to interpret it. - framework: Framework used to train the model - framework_version: The ``framework`` library version - memory_size: The in-memory size of the model on the accelerator during - inference (bytes) - total_parameters: Total number of model parameters, including trainable and - non-trainable parameters. - pretrained: Indicates if the model was pretrained. If the model was - pretrained, consider providing ``pretrained_source`` if it is known - pretrained_source: The source of the pretraining. - batch_size_suggestion: A suggested batch size for the accelerator and - summarized hardware. - accelerator: The intended computational hardware that runs inference - accelerator_constrained: Indicates if the intended ``accelerator`` is the - only accelerator that can run inference - accelerator_summary: A high level description of the ``accelerator`` - accelerator_count: A minimum amount of ``accelerator`` instances required to - run the model - hyperparameters: Additional hyperparameters relevant for the model - *args: Unused (no effect, only here for signature compliance with apply - method in derived classes - **kwargs: Unused (no effect, only here for signature compliance with apply - method in derived classes + Get or set the required (mlm) name property. It is named mlm_name in this + context to not break convention and overwrite the extension name class property. """ - self.mlm_name = name - self.architecture = architecture - self.tasks = tasks - self.input = input - self.output = output - self.framework = framework - self.framework_version = framework_version - self.memory_size = memory_size - self.total_parameters = total_parameters - self.pretrained = pretrained - self.pretrained_source = pretrained_source - self.batch_size_suggestion = batch_size_suggestion - self.accelerator = accelerator - self.accelerator_constrained = accelerator_constrained - self.accelerator_summary = accelerator_summary - self.accelerator_count = accelerator_count - self.hyperparameters = hyperparameters + return cast(str, get_required(self.properties.get(NAME_PROP), self, NAME_PROP)) - @classmethod - def get_schema_uri(cls) -> str: - """ - Retrieves this extension's schema URI + @mlm_name.setter + def mlm_name(self, v: str) -> None: + self._set_property(NAME_PROP, v) - Returns: - str: the schema URI + @property + def input(self) -> list[ModelInput]: """ - return SCHEMA_URI_PATTERN.format(version=DEFAULT_VERSION) - - @classmethod - def ext(cls, obj: T, add_if_missing: bool = False) -> MLMExtension[T]: + Get or set the required input property """ - Extend a STAC object (``obj``) with the MLMExtension - - Args: - obj: The STAC object to be extended. - add_if_missing: Defines whether this extension's URI should be added to - this object's (or its parent's) list of extensions if it is not already - listed there. + return [ + ModelInput(inp) + for inp in get_required( + self._get_property(INPUT_PROP, list[dict[str, Any]]), self, INPUT_PROP + ) + ] - Returns: - MLMExtension[T]: The extended object + @input.setter + def input(self, v: list[ModelInput]) -> None: + self._set_property(INPUT_PROP, [inp.to_dict() for inp in v]) - Raises: - TypeError: When a :class:`pystac.Asset` object is passed as the - `obj` parameter - pystac.ExtensionTypeError: When any unsupported object is passed as the - `obj` parameter. If you see this extension in this context, please - raise an issue on github. + @property + def output(self) -> list[ModelOutput]: """ - if isinstance(obj, pystac.Item): - cls.ensure_has_extension(obj, add_if_missing) - return cast(MLMExtension[T], ItemMLMExtension(obj)) - elif isinstance(obj, pystac.Collection): - cls.ensure_has_extension(obj, add_if_missing) - return cast(MLMExtension[T], CollectionMLMExtension(obj)) - elif isinstance(obj, pystac.ItemAssetDefinition): - cls.ensure_owner_has_extension(obj, add_if_missing) - return cast(MLMExtension[T], ItemAssetMLMExtension(obj)) - elif isinstance(obj, pystac.Asset): - raise TypeError( - "This class cannot be used to extend STAC objects of type Assets. " - "To extend Asset objects, use either AssetGeneralMLMExtension or " - "AssetDetailedMLMExtension" + Get or set the required output property + """ + return [ + ModelOutput(outp) + for outp in get_required( + self._get_property(OUTPUT_PROP, list[dict[str, Any]]), self, OUTPUT_PROP ) - else: - raise pystac.ExtensionTypeError(cls._ext_error_message(obj)) + ] + + @output.setter + def output(self, v: list[ModelOutput]) -> None: + self._set_property(OUTPUT_PROP, [outp.to_dict() for outp in v]) @property - def mlm_name(self) -> str: + def hyperparameters(self) -> Hyperparameters | None: """ - Get or set the required (mlm) name property. It is named mlm_name in this - context to not break convention and overwrite the extension name class property. + Get or set the hyperparameters property """ - return cast(str, get_required(self.properties.get(NAME_PROP), self, NAME_PROP)) + prop = self._get_property(HYPERPARAMETERS_PROP, dict[str, Any]) + return Hyperparameters(prop) if prop is not None else None - @mlm_name.setter - def mlm_name(self, v: str) -> None: - self._set_property(NAME_PROP, v) + @hyperparameters.setter + def hyperparameters(self, v: Hyperparameters | None) -> None: + self._set_property(HYPERPARAMETERS_PROP, v.to_dict() if v is not None else None) + + +class _IncludedInAssetProps(PropertiesExtension): + properties: dict[str, Any] @property def architecture(self) -> str: @@ -1666,49 +1578,146 @@ def accelerator_count(self) -> int | None: def accelerator_count(self, v: int | None) -> None: self._set_property(ACCELERATOR_COUNT_PROP, v) - @property - def input(self) -> list[ModelInput]: - """ - Get or set the required input property - """ - return [ - ModelInput(inp) - for inp in get_required( - self._get_property(INPUT_PROP, list[dict[str, Any]]), self, INPUT_PROP - ) - ] - @input.setter - def input(self, v: list[ModelInput]) -> None: - self._set_property(INPUT_PROP, [inp.to_dict() for inp in v]) +class MLMExtension( + Generic[T], + _ExcludedFromAssetProps, + _IncludedInAssetProps, + ExtensionManagementMixin[pystac.Item | pystac.Collection], +): + """An abstract class that can be used to extend to properties of an + :class:`pystac.Item` or :class:`pystac.Collection` with properties from the + :stac-ext:`Machine Learning Model Extension `. - @property - def output(self) -> list[ModelOutput]: + This class can be used to extend :class:`pystac.Item`, :class:`pystac.Collection` + and :class:`pystac.ItemAssetDefinition`. For extending :class:`pystac.Asset`, use + either :class:`~AssetGeneralMLMExtension`: or :class:`AssetDetailedMLMExtension`. + """ + + name: Literal["mlm"] = "mlm" + properties: dict[str, Any] + + def apply( + self, + name: str, + architecture: str, + tasks: list[TaskType], + input: list[ModelInput], + output: list[ModelOutput], + framework: str | None = None, + framework_version: str | None = None, + memory_size: int | None = None, + total_parameters: int | None = None, + pretrained: bool | None = None, + pretrained_source: str | None = None, + batch_size_suggestion: int | None = None, + accelerator: AcceleratorType | None = None, + accelerator_constrained: bool | None = None, + accelerator_summary: str | None = None, + accelerator_count: int | None = None, + hyperparameters: Hyperparameters | None = None, + *args: Any, + **kwargs: Any, + ) -> None: """ - Get or set the required output property + Sets the properties of a new MLMExtension + + Args: + name: name for the model + architecture: A generic and well established architecture name of the model + tasks: Specifies the Machine Learning tasks for which the model can be + used for + input: Describes the transformation between the EO data and the model input + output: Describes each model output and how to interpret it. + framework: Framework used to train the model + framework_version: The ``framework`` library version + memory_size: The in-memory size of the model on the accelerator during + inference (bytes) + total_parameters: Total number of model parameters, including trainable and + non-trainable parameters. + pretrained: Indicates if the model was pretrained. If the model was + pretrained, consider providing ``pretrained_source`` if it is known + pretrained_source: The source of the pretraining. + batch_size_suggestion: A suggested batch size for the accelerator and + summarized hardware. + accelerator: The intended computational hardware that runs inference + accelerator_constrained: Indicates if the intended ``accelerator`` is the + only accelerator that can run inference + accelerator_summary: A high level description of the ``accelerator`` + accelerator_count: A minimum amount of ``accelerator`` instances required to + run the model + hyperparameters: Additional hyperparameters relevant for the model + *args: Unused (no effect, only here for signature compliance with apply + method in derived classes + **kwargs: Unused (no effect, only here for signature compliance with apply + method in derived classes """ - return [ - ModelOutput(outp) - for outp in get_required( - self._get_property(OUTPUT_PROP, list[dict[str, Any]]), self, OUTPUT_PROP - ) - ] + self.mlm_name = name + self.architecture = architecture + self.tasks = tasks + self.input = input + self.output = output + self.framework = framework + self.framework_version = framework_version + self.memory_size = memory_size + self.total_parameters = total_parameters + self.pretrained = pretrained + self.pretrained_source = pretrained_source + self.batch_size_suggestion = batch_size_suggestion + self.accelerator = accelerator + self.accelerator_constrained = accelerator_constrained + self.accelerator_summary = accelerator_summary + self.accelerator_count = accelerator_count + self.hyperparameters = hyperparameters - @output.setter - def output(self, v: list[ModelOutput]) -> None: - self._set_property(OUTPUT_PROP, [outp.to_dict() for outp in v]) + @classmethod + def get_schema_uri(cls) -> str: + """ + Retrieves this extension's schema URI - @property - def hyperparameters(self) -> Hyperparameters | None: + Returns: + str: the schema URI """ - Get or set the hyperparameters property + return SCHEMA_URI_PATTERN.format(version=DEFAULT_VERSION) + + @classmethod + def ext(cls, obj: T, add_if_missing: bool = False) -> MLMExtension[T]: """ - prop = self._get_property(HYPERPARAMETERS_PROP, dict[str, Any]) - return Hyperparameters(prop) if prop is not None else None + Extend a STAC object (``obj``) with the MLMExtension - @hyperparameters.setter - def hyperparameters(self, v: Hyperparameters | None) -> None: - self._set_property(HYPERPARAMETERS_PROP, v.to_dict() if v is not None else None) + Args: + obj: The STAC object to be extended. + add_if_missing: Defines whether this extension's URI should be added to + this object's (or its parent's) list of extensions if it is not already + listed there. + + Returns: + MLMExtension[T]: The extended object + + Raises: + TypeError: When a :class:`pystac.Asset` object is passed as the + `obj` parameter + pystac.ExtensionTypeError: When any unsupported object is passed as the + `obj` parameter. If you see this extension in this context, please + raise an issue on github. + """ + if isinstance(obj, pystac.Item): + cls.ensure_has_extension(obj, add_if_missing) + return cast(MLMExtension[T], ItemMLMExtension(obj)) + elif isinstance(obj, pystac.Collection): + cls.ensure_has_extension(obj, add_if_missing) + return cast(MLMExtension[T], CollectionMLMExtension(obj)) + elif isinstance(obj, pystac.ItemAssetDefinition): + cls.ensure_owner_has_extension(obj, add_if_missing) + return cast(MLMExtension[T], ItemAssetMLMExtension(obj)) + elif isinstance(obj, pystac.Asset): + raise TypeError( + "This class cannot be used to extend STAC objects of type Assets. " + "To extend Asset objects, use either AssetGeneralMLMExtension or " + "AssetDetailedMLMExtension" + ) + else: + raise pystac.ExtensionTypeError(cls._ext_error_message(obj)) def to_dict(self) -> dict[str, Any]: """ From ddec1fb56f183807d081d0ec806783de694a5bb1 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 14:01:32 +0200 Subject: [PATCH 16/32] fix: removed forbidden properties from asset extension --- pystac/extensions/mlm.py | 55 +++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 747a7736c..bd25ec9a9 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -1616,8 +1616,6 @@ def apply( accelerator_summary: str | None = None, accelerator_count: int | None = None, hyperparameters: Hyperparameters | None = None, - *args: Any, - **kwargs: Any, ) -> None: """ Sets the properties of a new MLMExtension @@ -1647,10 +1645,6 @@ def apply( accelerator_count: A minimum amount of ``accelerator`` instances required to run the model hyperparameters: Additional hyperparameters relevant for the model - *args: Unused (no effect, only here for signature compliance with apply - method in derived classes - **kwargs: Unused (no effect, only here for signature compliance with apply - method in derived classes """ self.mlm_name = name self.architecture = architecture @@ -1922,7 +1916,11 @@ def __repr__(self) -> str: return f"" -class AssetDetailedMLMExtension(_AssetMLMExtension, MLMExtension[pystac.Asset]): +class AssetDetailedMLMExtension( + _AssetMLMExtension, + _IncludedInAssetProps, + ExtensionManagementMixin[pystac.Item | pystac.Collection], +): """A class that can be used to extend the properties of an :class:`pystac.Asset` object with properties from the :stac-ext:`Machine Learning Model Extension `. @@ -1960,11 +1958,8 @@ def ext( def apply( self, - name: str, architecture: str, tasks: list[TaskType], - input: list[ModelInput], - output: list[ModelOutput], framework: str | None = None, framework_version: str | None = None, memory_size: int | None = None, @@ -1976,7 +1971,6 @@ def apply( accelerator_constrained: bool | None = None, accelerator_summary: str | None = None, accelerator_count: int | None = None, - hyperparameters: Hyperparameters | None = None, artifact_type: str | None = None, compile_method: str | None = None, entrypoint: str | None = None, @@ -1985,12 +1979,9 @@ def apply( Sets the properties of a new AssetDetailedMLMExtensions Args: - name: name for the model architecture: A generic and well established architecture name of the model tasks: Specifies the Machine Learning tasks for which the model can be used for - input: Describes the transformation between the EO data and the model input - output: Describes each model output and how to interpret it. framework: Framework used to train the model framework_version: The ``framework`` library version memory_size: The in-memory size of the model on the accelerator during @@ -2008,7 +1999,6 @@ def apply( accelerator_summary: A high level description of the ``accelerator`` accelerator_count: A minimum amount of ``accelerator`` instances required to run the model - hyperparameters: Additional hyperparameters relevant for the model artifact_type: Specifies the kind of model artifact, any string is allowed. Typically related to a particular ML framework. This property is required when ``mlm:model`` is listed as a role of this asset @@ -2017,26 +2007,21 @@ def apply( entrypoint: Specific entrypoint reference in the code to use for running model inference. """ - MLMExtension.apply( - self, - name=name, - architecture=architecture, - tasks=tasks, - input=input, - output=output, - framework=framework, - framework_version=framework_version, - memory_size=memory_size, - total_parameters=total_parameters, - pretrained=pretrained, - pretrained_source=pretrained_source, - batch_size_suggestion=batch_size_suggestion, - accelerator=accelerator, - accelerator_constrained=accelerator_constrained, - accelerator_summary=accelerator_summary, - accelerator_count=accelerator_count, - hyperparameters=hyperparameters, - ) + + self.architecture = architecture + self.tasks = tasks + self.framework = framework + self.framework_version = framework_version + self.memory_size = memory_size + self.total_parameters = total_parameters + self.pretrained = pretrained + self.pretrained_source = pretrained_source + self.batch_size_suggestion = batch_size_suggestion + self.accelerator = accelerator + self.accelerator_constrained = accelerator_constrained + self.accelerator_summary = accelerator_summary + self.accelerator_count = accelerator_count + self.artifact_type = artifact_type self.compile_method = compile_method self.entrypoint = entrypoint From 04f6b327e8a522d886d2ee716e0f71d0628f1817 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 14:02:25 +0200 Subject: [PATCH 17/32] changed asset extension mechanism from name to architecture --- pystac/extensions/ext.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pystac/extensions/ext.py b/pystac/extensions/ext.py index 84f60c39d..fd2c7a646 100644 --- a/pystac/extensions/ext.py +++ b/pystac/extensions/ext.py @@ -406,7 +406,7 @@ def file(self) -> FileExtension[Asset]: @property def mlm(self) -> AssetGeneralMLMExtension[Asset] | AssetDetailedMLMExtension: - if "mlm:name" in self.stac_object.extra_fields: + if "mlm:architecture" in self.stac_object.extra_fields: return AssetDetailedMLMExtension.ext(self.stac_object) else: return AssetGeneralMLMExtension.ext(self.stac_object) From 14006e6867962426626241dfea1380b66ee06fb9 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 14:03:04 +0200 Subject: [PATCH 18/32] removed forbidden properties from detailled asset tests --- tests/extensions/test_mlm.py | 70 +----------------------------------- 1 file changed, 1 insertion(+), 69 deletions(-) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 00af52053..11130b16b 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -12,7 +12,6 @@ from pystac.extensions.classification import Classification from pystac.extensions.mlm import ( ARCHITECTURE_PROP, - NAME_PROP, TASKS_PROP, AcceleratorType, AssetDetailedMLMExtension, @@ -770,20 +769,16 @@ def test_add_to_asset(plain_item: Item) -> None: MLMExtension.ext(plain_item, add_if_missing=True) asset = plain_item.assets["analytic"] - assert NAME_PROP not in asset.extra_fields.keys() assert ARCHITECTURE_PROP not in asset.extra_fields.keys() assert TASKS_PROP not in asset.extra_fields.keys() asset_ext = AssetDetailedMLMExtension.ext(asset) - asset_ext.mlm_name = "asdf" asset_ext.architecture = "ResNet" asset_ext.tasks = [TaskType.CLASSIFICATION] - assert NAME_PROP in asset.extra_fields.keys() assert ARCHITECTURE_PROP in asset.extra_fields.keys() assert TASKS_PROP in asset.extra_fields.keys() - assert asset.extra_fields[NAME_PROP] == "asdf" assert asset.extra_fields[ARCHITECTURE_PROP] == "ResNet" assert asset.extra_fields[TASKS_PROP] == [TaskType.CLASSIFICATION] @@ -866,21 +861,6 @@ def test_to_dict_asset_generic() -> None: def test_add_to_detailled_asset() -> None: - model_input = ModelInput.create( - name="model", - bands=["B02"], - input=InputStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - model_output = ModelOutput.create( - name="output", - tasks=[TaskType.CLASSIFICATION], - result=ResultStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - asset = pystac.Asset( href="http://example.com/test.tiff", title="image", @@ -888,11 +868,8 @@ def test_add_to_detailled_asset() -> None: media_type="application/tiff", roles=["mlm:model"], extra_fields={ - "mlm:name": "asdf", "mlm:architecture": "ResNet", "mlm:tasks": [TaskType.CLASSIFICATION], - "mlm:input": [model_input.to_dict()], - "mlm:output": [model_output.to_dict()], "mlm:artifact_type": "foo", "mlm:compile_method": "bar", "mlm:entrypoint": "baz", @@ -901,11 +878,8 @@ def test_add_to_detailled_asset() -> None: asset_ext = AssetDetailedMLMExtension.ext(asset, add_if_missing=False) - assert asset_ext.mlm_name == "asdf" assert asset_ext.architecture == "ResNet" assert asset_ext.tasks == [TaskType.CLASSIFICATION] - assert asset_ext.input == [model_input] - assert asset_ext.output == [model_output] assert asset_ext.artifact_type == "foo" assert asset_ext.compile_method == "bar" assert asset_ext.entrypoint == "baz" @@ -930,7 +904,7 @@ def test_correct_asset_extension_is_used() -> None: asset = Asset("https://example.com") assert isinstance(asset.ext.mlm, AssetGeneralMLMExtension) - asset.extra_fields["mlm:name"] = "asdf" + asset.extra_fields["mlm:architecture"] = "ResNet" assert isinstance(asset.ext.mlm, AssetDetailedMLMExtension) @@ -951,37 +925,16 @@ def test_apply_detailled_asset() -> None: ) asset_ext = AssetDetailedMLMExtension.ext(asset, add_if_missing=False) - model_input = ModelInput.create( - name="model", - bands=["B02"], - input=InputStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - model_output = ModelOutput.create( - name="output", - tasks=[TaskType.CLASSIFICATION], - result=ResultStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - asset_ext.apply( - "asdf", "ResNet", [TaskType.CLASSIFICATION], - [model_input], - [model_output], artifact_type="foo", compile_method="bar", entrypoint="baz", ) - assert asset_ext.mlm_name == "asdf" assert asset_ext.architecture == "ResNet" assert asset_ext.tasks == [TaskType.CLASSIFICATION] - assert asset_ext.input == [model_input] - assert asset_ext.output == [model_output] assert asset_ext.artifact_type == "foo" assert asset_ext.compile_method == "bar" assert asset_ext.entrypoint == "baz" @@ -997,38 +950,17 @@ def test_to_dict_detailed_asset() -> None: ) asset_ext = AssetDetailedMLMExtension.ext(asset, add_if_missing=False) - model_input = ModelInput.create( - name="model", - bands=["B02"], - input=InputStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - model_output = ModelOutput.create( - name="output", - tasks=[TaskType.CLASSIFICATION], - result=ResultStructure.create( - shape=[1], dim_order=["batch"], data_type=DataType.FLOAT64 - ), - ) - asset_ext.apply( - "asdf", "ResNet", [TaskType.CLASSIFICATION], - [model_input], - [model_output], artifact_type="foo", compile_method="bar", entrypoint="baz", ) d = { - "mlm:name": "asdf", "mlm:architecture": "ResNet", "mlm:tasks": [TaskType.CLASSIFICATION], - "mlm:input": [model_input.to_dict()], - "mlm:output": [model_output.to_dict()], "mlm:artifact_type": "foo", "mlm:compile_method": "bar", "mlm:entrypoint": "baz", From 84f40e88317fb123abba42e19cbc659a80af4301 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 15:40:40 +0200 Subject: [PATCH 19/32] enabled migration for Item, Collection, assets, item-assets --- pystac/extensions/mlm.py | 84 ++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index bd25ec9a9..506e5e2b2 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2050,40 +2050,56 @@ class MLMExtensionHooks(ExtensionHooks): @staticmethod def _migrate_1_0_to_1_1(obj: dict[str, Any]) -> None: - if "mlm:framework" in obj["properties"]: - framework = obj["properties"]["mlm:framework"] - # remove invalid characters at beginning and end - forbidden_chars = [".", "_", "-", " ", "\t", "\n", "\r", "\f", "\v"] - if framework[0] in forbidden_chars or framework[-1] in forbidden_chars: - warnings.warn( - "Value for mlm:framework is invalid in mlm>=1.1, as it must" - "not start or end with one of the following characters: " - "._- and whitespace. These characters are therefore removed while" - "migrating the STAC object to v1.1.", - SyntaxWarning, - ) - while obj["properties"]["mlm:framework"][0] in forbidden_chars: - new_str = obj["properties"]["mlm:framework"][1:] - obj["properties"]["mlm:framework"] = new_str - while obj["properties"]["mlm:framework"][-1] in forbidden_chars: - new_str = obj["properties"]["mlm:framework"][:-1] - obj["properties"]["mlm:framework"] = new_str - - # rename frameworks - if obj["properties"]["mlm:framework"] == "Scikit-learn": - obj["properties"]["mlm:framework"] = "scikit-learn" - warnings.warn( - "mlm:framework value Scikit-learn is no longer valid in mlm>=1.1. " - "Renaming it to scikit-learn", - SyntaxWarning, - ) - if obj["properties"]["mlm:framework"] == "Huggingface": - obj["properties"]["mlm:framework"] = "Hugging Face" - warnings.warn( - "mlm:framework value Huggingface is no longer valid in mlm>=1.1. " - "Renaming it to Hugging Face", - SyntaxWarning, - ) + def migrate(props_obj: dict[str, Any]) -> None: + if "mlm:framework" in props_obj: + framework = props_obj["mlm:framework"] + # remove invalid characters at beginning and end + forbidden_chars = [".", "_", "-", " ", "\t", "\n", "\r", "\f", "\v"] + if framework[0] in forbidden_chars or framework[-1] in forbidden_chars: + warnings.warn( + "Value for mlm:framework is invalid in mlm>=1.1, as it must" + "not start or end with one of the following characters: " + "._- and whitespace. These characters are therefore removed " + "while migrating the STAC object to v1.1.", + SyntaxWarning, + ) + while props_obj["mlm:framework"][0] in forbidden_chars: + new_str = props_obj["mlm:framework"][1:] + props_obj["mlm:framework"] = new_str + while props_obj["mlm:framework"][-1] in forbidden_chars: + new_str = props_obj["mlm:framework"][:-1] + props_obj["mlm:framework"] = new_str + + # rename frameworks + if props_obj["mlm:framework"] == "Scikit-learn": + props_obj["mlm:framework"] = "scikit-learn" + warnings.warn( + "mlm:framework value Scikit-learn is no longer valid in " + "mlm>=1.1. Renaming it to scikit-learn", + SyntaxWarning, + ) + if props_obj["mlm:framework"] == "Huggingface": + props_obj["mlm:framework"] = "Hugging Face" + warnings.warn( + "mlm:framework value Huggingface is no longer valid in " + "mlm>=1.1. Renaming it to Hugging Face", + SyntaxWarning, + ) + + if obj["type"] == "Feature": + migrate(obj["properties"]) + if obj["type"] == "Collection": + migrate(obj) + + if "assets" in obj: + for asset_name in obj["assets"]: + asset = obj["assets"][asset_name] + migrate(asset) + + if obj["type"] == "Collection" and "item_assets" in obj: + for asset_name in obj["item_assets"]: + asset = obj["item_assets"][asset_name] + migrate(asset) @staticmethod def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: From 35800e2cb00ebcd97994edd574fee9671e4dd70d Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 17:34:30 +0200 Subject: [PATCH 20/32] added more version migrations --- pystac/extensions/mlm.py | 125 ++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index 506e5e2b2..f0ffbb471 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2103,52 +2103,76 @@ def migrate(props_obj: dict[str, Any]) -> None: @staticmethod def _migrate_1_1_to_1_2(obj: dict[str, Any]) -> None: - if "assets" not in obj: - return - assets = obj["assets"] - model_in_assets = any( - ["mlm:model" in assets[asset]["roles"] for asset in assets] - ) - if not model_in_assets: - raise pystac.errors.STACError( - 'Error migrating stac:mlm version: An asset with role "mlm:model" is ' - "required in mlm>=1.2. Include at least one asset with role " - '"mlm:model" ' + def migrate(obj_assets: dict[str, Any]) -> None: + model_in_assets = any( + ["mlm:model" in obj_assets[asset]["roles"] for asset in obj_assets] ) + if not model_in_assets: + raise pystac.errors.STACError( + 'Error migrating stac:mlm version: An asset with role "mlm:model" ' + "is required in mlm>=1.2. Include at least one asset with role " + '"mlm:model" ' + ) + + if "assets" in obj: + migrate(obj["assets"]) + if "item_assets" in obj: + migrate(obj["item_assets"]) @staticmethod def _migrate_1_2_to_1_3(obj: dict[str, Any]) -> None: - bands_obj = obj["properties"]["mlm:input"] + def migrate(props_obj: dict[str, Any]) -> None: + if "mlm:input" not in props_obj: + return - if not bands_obj: - return + bands_objs_present = any("bands" in inp for inp in props_obj["mlm:input"]) - if "raster:bands" not in obj["properties"]: - return - raster_bands = obj["properties"]["raster:bands"] + if not bands_objs_present: + return - # make sure all raster_bands have a name prop with length>0 - names_properties_valid = all( - "name" in band and len(band["name"]) > 0 for band in raster_bands - ) - if not names_properties_valid: - raise STACError( - "Error migrating stac:mlm version: In mlm>=1.3, each band in " - 'raster:bands is required to have a property "name"' + if "raster:bands" not in props_obj: + return + raster_bands = props_obj["raster:bands"] + + # make sure all raster_bands have a name prop with length>0 + names_properties_valid = all( + "name" in band and len(band["name"]) > 0 for band in raster_bands ) + if not names_properties_valid: + raise STACError( + "Error migrating stac:mlm version: In mlm>=1.3, each band in " + 'raster:bands is required to have a property "name"' + ) + + # no need to perform the actions below if props_obj is an asset + # this is checked by the presence of "roles" prop + if "roles" in props_obj: + return - # copy the raster:bands to assets - for asset_name in obj["assets"]: - asset = obj["assets"][asset_name] - if "mlm:model" not in asset["roles"]: - continue - asset["raster:bands"] = raster_bands + # copy the raster:bands to assets + for inner_asset_name in obj["assets"]: + inner_asset = obj["assets"][inner_asset_name] + if "mlm:model" not in inner_asset["roles"]: + continue + inner_asset["raster:bands"] = raster_bands + + if obj["type"] == "Feature" and "mlm:input" in obj["properties"]: + migrate(obj["properties"]) + if obj["type"] == "Collection": + migrate(obj) + if "assets" in obj: + for asset_name in obj["assets"]: + asset = obj["assets"][asset_name] + migrate(asset) @staticmethod def _migrate_1_3_to_1_4(obj: dict[str, Any]) -> None: - # Migrate to value_scaling - if "mlm:input" in obj["properties"]: - for input_obj in obj["properties"]["mlm:input"]: + def migrate(props_obj: dict[str, Any]) -> None: + if "mlm:input" not in props_obj: + return + + # Migrate to value_scaling + for input_obj in props_obj["mlm:input"]: if "norm_type" in input_obj and input_obj["norm_type"] is not None: norm_type = input_obj["norm_type"] value_scaling_list = [] @@ -2189,22 +2213,43 @@ def _migrate_1_3_to_1_4(obj: dict[str, Any]) -> None: input_obj.pop("norm_clip", None) input_obj.pop("statistics", None) + if obj["type"] == "Feature": + migrate(obj["properties"]) + if obj["type"] == "Collection": + migrate(obj) + if "assets" in obj: for asset in obj["assets"]: + migrate(obj["assets"][asset]) + # move forbidden fields from asset to properties if "mlm:name" in obj["assets"][asset]: - obj["properties"]["mlm:name"] = obj["assets"][asset]["mlm:name"] + mlm_name = obj["assets"][asset]["mlm:name"] + if obj["type"] == "Feature": + obj["properties"]["mlm:name"] = mlm_name + if obj["type"] == "Collection": + obj["mlm:name"] = mlm_name obj["assets"][asset].pop("mlm:name") if "mlm:input" in obj["assets"][asset]: - obj["properties"]["mlm:input"] = obj["assets"][asset]["mlm:input"] + inp = obj["assets"][asset]["mlm:input"] + if obj["type"] == "Feature": + obj["properties"]["mlm:input"] = inp + if obj["type"] == "Collection": + obj["mlm:input"] = inp obj["assets"][asset].pop("mlm:input") if "mlm:output" in obj["assets"][asset]: - obj["properties"]["mlm:output"] = obj["assets"][asset]["mlm:output"] + outp = obj["assets"][asset]["mlm:output"] + if obj["type"] == "Feature": + obj["properties"]["mlm:output"] = outp + if obj["type"] == "Collection": + obj["mlm:output"] = outp obj["assets"][asset].pop("mlm:output") if "mlm:hyperparameters" in obj["assets"][asset]: - obj["properties"]["mlm:hyperparameters"] = obj["assets"][asset][ - "mlm:hyperparameters" - ] + hyp = obj["assets"][asset]["mlm:hyperparameters"] + if obj["type"] == "Feature": + obj["properties"]["mlm:hyperparameters"] = hyp + if obj["type"] == "Collection": + obj["mlm:hyperparameters"] = hyp obj["assets"][asset].pop("mlm:hyperparameters") # add new REQUIRED proretie mlm:artifact_type to asset From f9b576ebb30066d8a652d63e64e0cb583c8e5372 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 28 Apr 2025 17:40:16 +0200 Subject: [PATCH 21/32] test new migrations --- tests/extensions/test_mlm.py | 495 ++++++++++++++++++++++++++++++++++- 1 file changed, 481 insertions(+), 14 deletions(-) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 11130b16b..51e4ea4b6 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1018,10 +1018,10 @@ def test_raise_exception_on_mlm_extension_and_asset() -> None: ("test_framework", "test_framework", True), ), ) -def test_migration_1_0_to_1_1( +def test_migration_1_0_to_1_1_item( framework_old: None | str, framework_new: None | str, valid: bool ) -> None: - data: dict[str, Any] = {"properties": {}} + data: dict[str, Any] = {"type": "Feature", "properties": {}} MLMExtensionHooks._migrate_1_0_to_1_1(data) assert "mlm:framework" not in data["properties"] @@ -1039,16 +1039,116 @@ def test_migration_1_0_to_1_1( assert bool(re.match(pattern, data["properties"]["mlm:framework"])) -def test_migration_1_1_to_1_2() -> None: +@pytest.mark.parametrize( + "framework_old, framework_new, valid", + ( + ("Scikit-learn", "scikit-learn", False), + ("Huggingface", "Hugging Face", False), + ("-_ .asdf", "asdf", False), + ("asdf-_ .", "asdf", False), + ("-._ asdf-.", "asdf", False), + ("test_framework", "test_framework", True), + ), +) +def test_migration_1_0_to_1_1_collection( + framework_old: None | str, framework_new: None | str, valid: bool +) -> None: + data: dict[str, Any] = {"type": "Collection"} + + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert "mlm:framework" not in data + + pattern = r"^(?=[^\s._\-]).*[^\s._\-]$" + data["mlm:framework"] = framework_old + + if valid: + MLMExtensionHooks._migrate_1_0_to_1_1(data) + else: + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + + assert data["mlm:framework"] == framework_new + assert bool(re.match(pattern, data["mlm:framework"])) + + +@pytest.mark.parametrize( + "framework_old, framework_new, valid", + ( + ("Scikit-learn", "scikit-learn", False), + ("Huggingface", "Hugging Face", False), + ("-_ .asdf", "asdf", False), + ("asdf-_ .", "asdf", False), + ("-._ asdf-.", "asdf", False), + ("test_framework", "test_framework", True), + ), +) +def test_migration_1_0_to_1_1_asset( + framework_old: None | str, framework_new: None | str, valid: bool +) -> None: + data: dict[str, Any] = { + "type": "Item", + "assets": {"asset1": Asset("https://asdf.com").to_dict()}, + } + + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert "mlm:framework" not in data["assets"]["asset1"] + + pattern = r"^(?=[^\s._\-]).*[^\s._\-]$" + data["assets"]["asset1"]["mlm:framework"] = framework_old + + if valid: + MLMExtensionHooks._migrate_1_0_to_1_1(data) + else: + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + + assert data["assets"]["asset1"]["mlm:framework"] == framework_new + assert bool(re.match(pattern, data["assets"]["asset1"]["mlm:framework"])) + + +@pytest.mark.parametrize( + "framework_old, framework_new, valid", + ( + ("Scikit-learn", "scikit-learn", False), + ("Huggingface", "Hugging Face", False), + ("-_ .asdf", "asdf", False), + ("asdf-_ .", "asdf", False), + ("-._ asdf-.", "asdf", False), + ("test_framework", "test_framework", True), + ), +) +def test_migration_1_0_to_1_1_item_assets( + framework_old: None | str, framework_new: None | str, valid: bool +) -> None: + data: dict[str, Any] = {"type": "Collection", "item_assets": {"asset1": {}}} + + MLMExtensionHooks._migrate_1_0_to_1_1(data) + assert "mlm:framework" not in data + + pattern = r"^(?=[^\s._\-]).*[^\s._\-]$" + data["item_assets"]["asset1"]["mlm:framework"] = framework_old + + if valid: + MLMExtensionHooks._migrate_1_0_to_1_1(data) + else: + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + + assert data["item_assets"]["asset1"]["mlm:framework"] == framework_new + assert bool(re.match(pattern, data["item_assets"]["asset1"]["mlm:framework"])) + + +@pytest.mark.parametrize("asset_type", ("assets", "item_assets")) +def test_migration_1_1_to_1_2(asset_type: str) -> None: data: dict[str, Any] = {} MLMExtensionHooks._migrate_1_1_to_1_2(data) - data["assets"] = {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["labels"]}} + data[asset_type] = {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["labels"]}} with pytest.raises(pystac.errors.STACError): MLMExtensionHooks._migrate_1_1_to_1_2(data) - data["assets"]["asset3"] = {"roles": ["mlm:model"]} + data[asset_type]["asset3"] = {"roles": ["mlm:model"]} MLMExtensionHooks._migrate_1_1_to_1_2(data) @@ -1094,16 +1194,17 @@ def test_migration_1_1_to_1_2() -> None: (["B02", "B03"], [{"data_type": "float64"}, {"data_type": "float64"}], False), ), ) -def test_migration_1_2_to_1_3( +def test_migration_1_2_to_1_3_item( inp_bands: list[str], raster_bands: list[dict[str, Any]], valid: bool ) -> None: data: dict[str, Any] = { - "properties": {"mlm:input": {}}, + "type": "Feature", + "properties": {"mlm:input": [{}]}, "assets": {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["mlm:model"]}}, } - if inp_bands: - data["properties"]["mlm:input"]["bands"] = inp_bands + data["properties"]["mlm:input"][0]["bands"] = inp_bands + if raster_bands: data["properties"]["raster:bands"] = raster_bands if valid: @@ -1116,6 +1217,137 @@ def test_migration_1_2_to_1_3( MLMExtensionHooks._migrate_1_2_to_1_3(data) +@pytest.mark.parametrize( + "inp_bands, raster_bands, valid", + ( + ([], None, True), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "B03", "data_type": "float64"}, + ], + True, + ), + ( + ["B02", "B03"], + [ + {"name": "", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [{"name": "B02", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + ( + ["B02", "B03"], + [{"name": "", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + (["B02", "B03"], [{"data_type": "float64"}, {"data_type": "float64"}], False), + ), +) +def test_migration_1_2_to_1_3_collection( + inp_bands: list[str], raster_bands: list[dict[str, Any]], valid: bool +) -> None: + data: dict[str, Any] = { + "type": "Collection", + "mlm:input": [{}], + "assets": {"asset1": {"roles": ["data"]}, "asset2": {"roles": ["mlm:model"]}}, + } + + data["mlm:input"][0]["bands"] = inp_bands + if raster_bands: + data["raster:bands"] = raster_bands + + if valid: + MLMExtensionHooks._migrate_1_2_to_1_3(data) + if raster_bands: + assert "raster:bands" not in data["assets"]["asset1"] + assert "raster:bands" in data["assets"]["asset2"] + else: + with pytest.raises(STACError): + MLMExtensionHooks._migrate_1_2_to_1_3(data) + + +@pytest.mark.parametrize( + "inp_bands, raster_bands, valid", + ( + ([], None, True), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "B03", "data_type": "float64"}, + ], + True, + ), + ( + ["B02", "B03"], + [ + {"name": "", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [ + {"name": "B02", "data_type": "float64"}, + {"name": "", "data_type": "float64"}, + ], + False, + ), + ( + ["B02", "B03"], + [{"name": "B02", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + ( + ["B02", "B03"], + [{"name": "", "data_type": "float64"}, {"data_type": "float64"}], + False, + ), + (["B02", "B03"], [{"data_type": "float64"}, {"data_type": "float64"}], False), + ), +) +def test_migration_1_2_to_1_3_asset( + inp_bands: list[str], raster_bands: list[dict[str, Any]], valid: bool +) -> None: + data: dict[str, Any] = { + "type": "Feature", + "properties": [], + "assets": { + "asset1": {"roles": ["data"]}, + "asset2": {"roles": ["mlm:model"], "mlm:input": [{}]}, + }, + } + + data["assets"]["asset2"]["mlm:input"][0]["bands"] = inp_bands + if raster_bands: + data["assets"]["asset2"]["raster:bands"] = raster_bands + + if valid: + MLMExtensionHooks._migrate_1_2_to_1_3(data) + if raster_bands: + assert "raster:bands" not in data["assets"]["asset1"] + assert "raster:bands" in data["assets"]["asset2"] + else: + with pytest.raises(STACError): + MLMExtensionHooks._migrate_1_2_to_1_3(data) + + @pytest.mark.parametrize( ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), ( @@ -1175,14 +1407,14 @@ def test_migration_1_2_to_1_3( ), ), ) -def test_migration_1_3_to_1_4_value_scaling( +def test_migration_1_3_to_1_4_value_scaling_item( norm_by_channel: bool | None, norm_type: str | None, norm_clip: list[int] | None, statistics: list[dict[str, Any]] | None, value_scaling: list[ValueScaling] | None, ) -> None: - data: dict[str, Any] = {"properties": {"mlm:input": []}} + data: dict[str, Any] = {"type": "Feature", "properties": {"mlm:input": []}} MLMExtensionHooks._migrate_1_3_to_1_4(data) # nothing is supposed to happen here input_obj: dict[str, Any] = {} @@ -1205,7 +1437,206 @@ def test_migration_1_3_to_1_4_value_scaling( obj.to_dict() for obj in value_scaling ] - new_input_obj = data["properties"]["mlm:input"] + new_input_obj = data["properties"]["mlm:input"][0] + assert "norm_by_channel" not in new_input_obj + assert "norm_type" not in new_input_obj + assert "norm_clip" not in new_input_obj + assert "statistics" not in new_input_obj + + +@pytest.mark.parametrize( + ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), + ( + (None, None, None, None, None), + (False, None, None, None, None), + ( + False, + "z-score", + None, + [{"mean": 5, "stddev": 2}], + [ValueScaling.create(ValueScalingType.Z_SCORE, mean=5, stddev=2)], + ), + ( + False, + "min-max", + None, + [{"minimum": 10, "maximum": 20}], + [ValueScaling.create(ValueScalingType.MIN_MAX, minimum=10, maximum=20)], + ), + ( + True, + "z-score", + None, + [ + {"mean": 5, "stddev": 2}, + {"mean": 6, "stddev": 3}, + {"mean": 10, "stddev": 1}, + ], + [ + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=5, stddev=2), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=6, stddev=3), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=10, stddev=1), + ], + ), + ( + True, + "clip", + [3, 4, 5], + None, + [ + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 3, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 4, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 5, 0, 1)", + ), + ], + ), + ), +) +def test_migration_1_3_to_1_4_value_scaling_collection( + norm_by_channel: bool | None, + norm_type: str | None, + norm_clip: list[int] | None, + statistics: list[dict[str, Any]] | None, + value_scaling: list[ValueScaling] | None, +) -> None: + data: dict[str, Any] = {"type": "Collection", "mlm:input": []} + MLMExtensionHooks._migrate_1_3_to_1_4(data) # nothing is supposed to happen here + + input_obj: dict[str, Any] = {} + if norm_by_channel is not None: + input_obj["norm_by_channel"] = norm_by_channel + if norm_type is not None: + input_obj["norm_type"] = norm_type + if norm_clip is not None: + input_obj["norm_clip"] = norm_clip + if statistics is not None: + input_obj["statistics"] = statistics + data["mlm:input"].append(input_obj) + + MLMExtensionHooks._migrate_1_3_to_1_4(data) + if norm_type is not None and value_scaling is not None: + assert len(data["mlm:input"][0]["value_scaling"]) == len(value_scaling) + assert data["mlm:input"][0]["value_scaling"] == [ + obj.to_dict() for obj in value_scaling + ] + + new_input_obj = data["mlm:input"][0] + assert "norm_by_channel" not in new_input_obj + assert "norm_type" not in new_input_obj + assert "norm_clip" not in new_input_obj + assert "statistics" not in new_input_obj + + +@pytest.mark.parametrize( + ("norm_by_channel", "norm_type", "norm_clip", "statistics", "value_scaling"), + ( + (None, None, None, None, None), + (False, None, None, None, None), + ( + False, + "z-score", + None, + [{"mean": 5, "stddev": 2}], + [ValueScaling.create(ValueScalingType.Z_SCORE, mean=5, stddev=2)], + ), + ( + False, + "min-max", + None, + [{"minimum": 10, "maximum": 20}], + [ValueScaling.create(ValueScalingType.MIN_MAX, minimum=10, maximum=20)], + ), + ( + True, + "z-score", + None, + [ + {"mean": 5, "stddev": 2}, + {"mean": 6, "stddev": 3}, + {"mean": 10, "stddev": 1}, + ], + [ + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=5, stddev=2), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=6, stddev=3), + ValueScaling.create(type=ValueScalingType.Z_SCORE, mean=10, stddev=1), + ], + ), + ( + True, + "clip", + [3, 4, 5], + None, + [ + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 3, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 4, 0, 1)", + ), + ValueScaling.create( + type=ValueScalingType.PROCESSING, + format="gdal-calc", + expression="numpy.clip(A / 5, 0, 1)", + ), + ], + ), + ), +) +def test_migration_1_3_to_1_4_value_scaling_asset( + norm_by_channel: bool | None, + norm_type: str | None, + norm_clip: list[int] | None, + statistics: list[dict[str, Any]] | None, + value_scaling: list[ValueScaling] | None, +) -> None: + data: dict[str, Any] = { + "type": "Feature", + "properties": {}, + "assets": {"asset1": {"href": "https://example.com", "roles": ["mlm:model"]}}, + } + MLMExtensionHooks._migrate_1_3_to_1_4(data) # nothing is supposed to happen here + + input_obj: dict[str, Any] = {} + if norm_by_channel is not None: + input_obj["norm_by_channel"] = norm_by_channel + if norm_type is not None: + input_obj["norm_type"] = norm_type + if norm_clip is not None: + input_obj["norm_clip"] = norm_clip + if statistics is not None: + input_obj["statistics"] = statistics + + data["assets"]["asset1"]["mlm:input"] = [] + data["assets"]["asset1"]["mlm:input"].append(input_obj) + + MLMExtensionHooks._migrate_1_3_to_1_4(data) + + assert "mlm:input" not in data["assets"]["asset1"] + + if norm_type is not None and value_scaling is not None: + assert len(data["properties"]["mlm:input"][0]["value_scaling"]) == len( + value_scaling + ) + assert data["properties"]["mlm:input"][0]["value_scaling"] == [ + obj.to_dict() for obj in value_scaling + ] + + new_input_obj = data["properties"]["mlm:input"][0] assert "norm_by_channel" not in new_input_obj assert "norm_type" not in new_input_obj assert "norm_clip" not in new_input_obj @@ -1217,14 +1648,19 @@ def test_migration_1_3_to_1_4_value_scaling( ("l1", "l2", "l2sqr", "hamming", "hamming2", "type-mask", "relative", "inf"), ) def test_migration_1_3_to_1_4_failure(norm_type: str) -> None: - data: dict[str, Any] = {"properties": {"mlm:input": [{"norm_type": norm_type}]}} + # test that previously supported but now unsupported types raise an error + data: dict[str, Any] = { + "type": "Feature", + "properties": {"mlm:input": [{"norm_type": norm_type}]}, + } with pytest.raises(NotImplementedError): MLMExtensionHooks._migrate_1_3_to_1_4(data) -def test_migration_1_3_to_1_4_assets() -> None: +def test_migration_1_3_to_1_4_assets_item() -> None: data: dict[str, Any] = { + "type": "Feature", "properties": {}, "assets": { "asset1": { @@ -1252,3 +1688,34 @@ def test_migration_1_3_to_1_4_assets() -> None: assert "mlm:hyperparameters" in data["properties"] assert "mlm:artifact_type" in data["assets"]["asset1"] + + +def test_migration_1_3_to_1_4_collection() -> None: + data: dict[str, Any] = { + "type": "Collection", + "assets": { + "asset1": { + "mlm:name": "asdf", + "mlm:input": {}, + "mlm:output": {}, + "mlm:hyperparameters": {}, + "roles": ["mlm:model"], + } + }, + } + + MLMExtensionHooks._migrate_1_3_to_1_4(data) + + assert "mlm:name" not in data["assets"]["asset1"] + assert "mlm:name" in data + + assert "mlm:input" not in data["assets"]["asset1"] + assert "mlm:input" in data + + assert "mlm:output" not in data["assets"]["asset1"] + assert "mlm:output" in data + + assert "mlm:hyperparameters" not in data["assets"]["asset1"] + assert "mlm:hyperparameters" in data + + assert "mlm:artifact_type" in data["assets"]["asset1"] From a919888b287ae9ccfab1b1f526c67f7bee1f5672 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Apr 2025 10:59:04 +0200 Subject: [PATCH 22/32] added types-requests --- pyproject.toml | 1 + uv.lock | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 51f7bcbc4..2fdc76787 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ dev = [ "types-jsonschema>=4.23.0.20240813", "types-orjson>=3.6.2", "types-python-dateutil>=2.9.0.20241003", + "types-requests>=2.32.0.20250328", "types-urllib3>=1.26.25.14", "urllib3>=2.3.0", "virtualenv>=20.26.6", diff --git a/uv.lock b/uv.lock index 6a4da2834..92bb1ba26 100644 --- a/uv.lock +++ b/uv.lock @@ -2143,6 +2143,7 @@ dev = [ { name = "types-jsonschema" }, { name = "types-orjson" }, { name = "types-python-dateutil" }, + { name = "types-requests" }, { name = "types-urllib3" }, { name = "urllib3" }, { name = "virtualenv" }, @@ -2196,6 +2197,7 @@ dev = [ { name = "types-jsonschema", specifier = ">=4.23.0.20240813" }, { name = "types-orjson", specifier = ">=3.6.2" }, { name = "types-python-dateutil", specifier = ">=2.9.0.20241003" }, + { name = "types-requests", specifier = ">=2.32.0.20250328" }, { name = "types-urllib3", specifier = ">=1.26.25.14" }, { name = "urllib3", specifier = ">=2.3.0" }, { name = "virtualenv", specifier = ">=20.26.6" }, @@ -3117,6 +3119,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/72/52/43e70a8e57fefb172c22a21000b03ebcc15e47e97f5cb8495b9c2832efb4/types_python_dateutil-2.9.0.20250708-py3-none-any.whl", hash = "sha256:4d6d0cc1cc4d24a2dc3816024e502564094497b713f7befda4d5bc7a8e3fd21f", size = 17724, upload-time = "2025-07-08T03:14:02.593Z" }, ] +[[package]] +name = "types-requests" +version = "2.32.0.20250328" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/7d/eb174f74e3f5634eaacb38031bbe467dfe2e545bc255e5c90096ec46bc46/types_requests-2.32.0.20250328.tar.gz", hash = "sha256:c9e67228ea103bd811c96984fac36ed2ae8da87a36a633964a21f199d60baf32", size = 22995 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/15/3700282a9d4ea3b37044264d3e4d1b1f0095a4ebf860a99914fd544e3be3/types_requests-2.32.0.20250328-py3-none-any.whl", hash = "sha256:72ff80f84b15eb3aa7a8e2625fffb6a93f2ad5a0c20215fc1dcfa61117bcb2a2", size = 20663 }, +] + [[package]] name = "types-urllib3" version = "1.26.25.14" From 659a2b698f6fe8ba8772d08f4e97be3f136e7f2e Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Apr 2025 10:59:27 +0200 Subject: [PATCH 23/32] added tests for migration --- ...sion}-examples-item_basic.json-1.0.0].yaml | 110 ++++++++ ...sion}-examples-item_basic.json-1.1.0].yaml | 110 ++++++++ ...sion}-examples-item_basic.json-1.2.0].yaml | 110 ++++++++ ...sion}-examples-item_basic.json-1.3.0].yaml | 110 ++++++++ ...n}-examples-item_eo_bands.json-1.0.0].yaml | 255 ++++++++++++++++++ ...n}-examples-item_eo_bands.json-1.1.0].yaml | 209 ++++++++++++++ ...n}-examples-item_eo_bands.json-1.2.0].yaml | 209 ++++++++++++++ ...n}-examples-item_eo_bands.json-1.3.0].yaml | 209 ++++++++++++++ ...n}-examples-item_multi_io.json-1.0.0].yaml | 156 +++++++++++ ...n}-examples-item_multi_io.json-1.1.0].yaml | 162 +++++++++++ ...n}-examples-item_multi_io.json-1.2.0].yaml | 162 +++++++++++ ...n}-examples-item_multi_io.json-1.3.0].yaml | 166 ++++++++++++ ...xamples-item_raster_bands.json-1.0.0].yaml | 194 +++++++++++++ ...xamples-item_raster_bands.json-1.1.0].yaml | 194 +++++++++++++ ...xamples-item_raster_bands.json-1.2.0].yaml | 194 +++++++++++++ ...xamples-item_raster_bands.json-1.3.0].yaml | 201 ++++++++++++++ tests/extensions/test_mlm.py | 43 +++ 17 files changed, 2794 insertions(+) create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml create mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml new file mode 100644 index 000000000..6a337b634 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml @@ -0,0 +1,110 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.0.0/examples/item_basic.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"example-model\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Basic STAC Item with only the + MLM extension and no other extension cross-references.\",\n \"datetime\": + null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": + \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"example-model\",\n \"mlm:tasks\": + [\n \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:input\": [\n {\n \"name\": \"Model with RGB input that + does not refer to any band.\",\n \"bands\": [],\n \"input\": + {\n \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n }\n }\n ],\n + \ \"mlm:output\": [\n {\n \"name\": \"classification\",\n \"tasks\": + [\n \"classification\"\n ],\n \"result\": {\n \"shape\": + [\n -1,\n 1\n ],\n \"dim_order\": + [\n \"batch\",\n \"class\"\n ],\n \"data_type\": + \"uint8\"\n },\n \"classification_classes\": [\n {\n + \ \"value\": 0,\n \"name\": \"BACKGROUND\",\n \"description\": + \"Background non-city.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 0\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"CITY\",\n \"description\": + \"A city is detected.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 255\n ]\n }\n ]\n + \ }\n ]\n },\n \"assets\": {\n \"model\": {\n \"href\": \"https://huggingface.co/example/model-card\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"Example + model.\",\n \"type\": \"text/html\",\n \"roles\": [\n \"mlm:model\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_basic.json\",\n + \ \"type\": \"application/geo+json\"\n }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '931' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:25 GMT + ETag: + - W/"06b55e576e4efab26350d8d7551913db9419014d18bff024af7e5818a2366f4b" + Expires: + - Tue, 29 Apr 2025 08:35:25 GMT + Source-Age: + - '120' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - cbb71f87565b003068eeb6cf1d44e3e92f0b75fb + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - EAA8:1C62A6:B8FA8E:D1A987:681087C4 + X-Served-By: + - cache-fra-etou8220124-FRA + X-Timer: + - S1745915426.697783,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml new file mode 100644 index 000000000..572c95588 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml @@ -0,0 +1,110 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.1.0/examples/item_basic.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.1.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"example-model\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Basic STAC Item with only the + MLM extension and no other extension cross-references.\",\n \"datetime\": + null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": + \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"example-model\",\n \"mlm:tasks\": + [\n \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:input\": [\n {\n \"name\": \"Model with RGB input that + does not refer to any band.\",\n \"bands\": [],\n \"input\": + {\n \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n }\n }\n ],\n + \ \"mlm:output\": [\n {\n \"name\": \"classification\",\n \"tasks\": + [\n \"classification\"\n ],\n \"result\": {\n \"shape\": + [\n -1,\n 1\n ],\n \"dim_order\": + [\n \"batch\",\n \"class\"\n ],\n \"data_type\": + \"uint8\"\n },\n \"classification_classes\": [\n {\n + \ \"value\": 0,\n \"name\": \"BACKGROUND\",\n \"description\": + \"Background non-city.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 0\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"CITY\",\n \"description\": + \"A city is detected.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 255\n ]\n }\n ]\n + \ }\n ]\n },\n \"assets\": {\n \"model\": {\n \"href\": \"https://huggingface.co/example/model-card\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"Example + model.\",\n \"type\": \"text/html\",\n \"roles\": [\n \"mlm:model\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_basic.json\",\n + \ \"type\": \"application/geo+json\"\n }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '933' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:25 GMT + ETag: + - W/"60cdf768894e2f4eaafeb01906736c2bb03903640b6615f1cea0dd4ace03a6d3" + Expires: + - Tue, 29 Apr 2025 08:35:25 GMT + Source-Age: + - '120' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - fdaeae3f7f917f5f4c801f2719acdc47c172defb + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 5BEA:6EEED:C4E1E6:DE2B23:68108DA9 + X-Served-By: + - cache-fra-etou8220128-FRA + X-Timer: + - S1745915426.768525,VS0,VE2 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml new file mode 100644 index 000000000..d209d5ba6 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml @@ -0,0 +1,110 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.2.0/examples/item_basic.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.2.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"example-model\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Basic STAC Item with only the + MLM extension and no other extension cross-references.\",\n \"datetime\": + null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": + \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"example-model\",\n \"mlm:tasks\": + [\n \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:input\": [\n {\n \"name\": \"Model with RGB input that + does not refer to any band.\",\n \"bands\": [],\n \"input\": + {\n \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n }\n }\n ],\n + \ \"mlm:output\": [\n {\n \"name\": \"classification\",\n \"tasks\": + [\n \"classification\"\n ],\n \"result\": {\n \"shape\": + [\n -1,\n 1\n ],\n \"dim_order\": + [\n \"batch\",\n \"class\"\n ],\n \"data_type\": + \"uint8\"\n },\n \"classification_classes\": [\n {\n + \ \"value\": 0,\n \"name\": \"BACKGROUND\",\n \"description\": + \"Background non-city.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 0\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"CITY\",\n \"description\": + \"A city is detected.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 255\n ]\n }\n ]\n + \ }\n ]\n },\n \"assets\": {\n \"model\": {\n \"href\": \"https://huggingface.co/example/model-card\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"Example + model.\",\n \"type\": \"text/html\",\n \"roles\": [\n \"mlm:model\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_basic.json\",\n + \ \"type\": \"application/geo+json\"\n }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '934' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:25 GMT + ETag: + - W/"4214e4c8a7e047eaff361f43a1e2ce58d4e403d064c4a0a9fc870a0f02f3ffd4" + Expires: + - Tue, 29 Apr 2025 08:35:25 GMT + Source-Age: + - '119' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - dea14443ef6f269978dd64c2bb7cf0811dcd3102 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 6822:112C:B53704:CD19F6:68108DA9 + X-Served-By: + - cache-fra-etou8220154-FRA + X-Timer: + - S1745915426.841928,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml new file mode 100644 index 000000000..6e9c29315 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml @@ -0,0 +1,110 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.3.0/examples/item_basic.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.3.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"example-model\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Basic STAC Item with only the + MLM extension and no other extension cross-references.\",\n \"datetime\": + null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": + \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"example-model\",\n \"mlm:tasks\": + [\n \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:input\": [\n {\n \"name\": \"Model with RGB input that + does not refer to any band.\",\n \"bands\": [],\n \"input\": + {\n \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n }\n }\n ],\n + \ \"mlm:output\": [\n {\n \"name\": \"classification\",\n \"tasks\": + [\n \"classification\"\n ],\n \"result\": {\n \"shape\": + [\n -1,\n 1\n ],\n \"dim_order\": + [\n \"batch\",\n \"class\"\n ],\n \"data_type\": + \"uint8\"\n },\n \"classification_classes\": [\n {\n + \ \"value\": 0,\n \"name\": \"BACKGROUND\",\n \"description\": + \"Background non-city.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 0\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"CITY\",\n \"description\": + \"A city is detected.\",\n \"color_hint\": [\n 0,\n + \ 0,\n 255\n ]\n }\n ]\n + \ }\n ]\n },\n \"assets\": {\n \"model\": {\n \"href\": \"https://huggingface.co/example/model-card\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"Example + model.\",\n \"type\": \"text/html\",\n \"roles\": [\n \"mlm:model\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_basic.json\",\n + \ \"type\": \"application/geo+json\"\n }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '934' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:25 GMT + ETag: + - W/"2cdd4c4b8a96681920b5e858cc552b3b19ca2a40e211d9ef29e3863f040782c2" + Expires: + - Tue, 29 Apr 2025 08:35:25 GMT + Source-Age: + - '118' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - d9048815950a3df8944faf506270689c94e931a6 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 6444:183F83:C9B8F0:E30245:68108DA9 + X-Served-By: + - cache-fra-etou8220020-FRA + X-Timer: + - S1745915426.908529,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml new file mode 100644 index 000000000..47ab3e239 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml @@ -0,0 +1,255 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.0.0/examples/item_eo_bands.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": + true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n + \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n + \ \"stddev\": 245.71762908\n },\n {\n \"mean\": + 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n + \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n + \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": + 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n + \ \"stddev\": 566.4170017\n },\n {\n \"mean\": + 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n + \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n + \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": + 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n + \ \"stddev\": 404.91978886\n },\n {\n \"mean\": + 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n + \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n + \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": + 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n + \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ],\n \"eo:bands\": [\n {\n \"name\": \"B01\",\n + \ \"common_name\": \"coastal\",\n \"description\": \"Coastal + aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": + 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": + \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": + 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": + \"B03\",\n \"common_name\": \"green\",\n \"description\": \"Green + (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": + 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": + \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": + 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n \"name\": + \"B05\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": + 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": + \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": + 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": + \"B07\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": + 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": + \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": + 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n \"name\": + \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": \"NIR + 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": + 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": + \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": + 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n \"name\": + \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": \"SWIR + - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": + 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": + \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": + 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": + \"B12\",\n \"common_name\": \"swir22\",\n \"description\": \"SWIR + 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": + 0.242\n }\n ],\n \"raster:bands\": [\n {\n \"name\": + \"B01\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B02\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B05\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B06\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B07\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B8A\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B09\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B10\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B11\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B12\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil + schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n + \ \"name\": \"coastal\"\n },\n {\n \"name\": + \"blue\"\n },\n {\n \"name\": \"green\"\n },\n + \ {\n \"name\": \"red\"\n },\n {\n \"name\": + \"rededge1\"\n },\n {\n \"name\": \"rededge2\"\n },\n + \ {\n \"name\": \"rededge3\"\n },\n {\n \"name\": + \"nir\"\n },\n {\n \"name\": \"nir08\"\n },\n + \ {\n \"name\": \"nir09\"\n },\n {\n \"name\": + \"cirrus\"\n },\n {\n \"name\": \"swir16\"\n },\n + \ {\n \"name\": \"swir22\"\n }\n ]\n },\n \"source_code\": + {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": + \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '2632' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:25 GMT + ETag: + - W/"550b55c5cc7ce92969a64bfa5a8325141386d01c7b097671b9d659f7c70764b5" + Expires: + - Tue, 29 Apr 2025 08:35:25 GMT + Source-Age: + - '118' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 044807e148068029fbd9f42554c471a3460a5b19 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - EF89:6EEED:B9770B:D225ED:681087C7 + X-Served-By: + - cache-fra-etou8220031-FRA + X-Timer: + - S1745915426.975329,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml new file mode 100644 index 000000000..7a6c18763 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml @@ -0,0 +1,209 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.1.0/examples/item_eo_bands.json + response: + body: + string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, + with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n + \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": + true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n + \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n + \ \"stddev\": 245.71762908\n },\n {\n \"mean\": + 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n + \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n + \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": + 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n + \ \"stddev\": 566.4170017\n },\n {\n \"mean\": + 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n + \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n + \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": + 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n + \ \"stddev\": 404.91978886\n },\n {\n \"mean\": + 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n + \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n + \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": + 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n + \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": + \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil + schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n + \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": + \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": + 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": + \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": + 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": + \"B03\",\n \"common_name\": \"green\",\n \"description\": + \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": + 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": + \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": + 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n + \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": + 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": + \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": + 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": + \"B07\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": + 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": + \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": + 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n + \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": + \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": + 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": + \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": + 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n + \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": + \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": + 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": + \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": + 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": + \"B12\",\n \"common_name\": \"swir22\",\n \"description\": + \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": + 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": + \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": + \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '2476' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"538e8345f63973b9ad1ad9f7aaaa0dacd3ab3ffeea7255d6da75ff0299bd8896" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '118' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 24eec2b921a253b550ede66e2a1d9adc7bd2de44 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 5E94:6EEED:C4E611:DE2F9E:68108DAB + X-Served-By: + - cache-fra-etou8220158-FRA + X-Timer: + - S1745915426.042527,VS0,VE2 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml new file mode 100644 index 000000000..b9de4ecf5 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml @@ -0,0 +1,209 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.2.0/examples/item_eo_bands.json + response: + body: + string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, + with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n + \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.2.0/schema.json\",\n + \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": + true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n + \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n + \ \"stddev\": 245.71762908\n },\n {\n \"mean\": + 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n + \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n + \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": + 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n + \ \"stddev\": 566.4170017\n },\n {\n \"mean\": + 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n + \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n + \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": + 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n + \ \"stddev\": 404.91978886\n },\n {\n \"mean\": + 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n + \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n + \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": + 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n + \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": + \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil + schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n + \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": + \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": + 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": + \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": + 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": + \"B03\",\n \"common_name\": \"green\",\n \"description\": + \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": + 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": + \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": + 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n + \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": + 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": + \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": + 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": + \"B07\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": + 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": + \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": + 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n + \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": + \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": + 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": + \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": + 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n + \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": + \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": + 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": + \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": + 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": + \"B12\",\n \"common_name\": \"swir22\",\n \"description\": + \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": + 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": + \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": + \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '2478' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"90ccd29b9b5252a7bbcc61aa942d67f941d72bd60900fe3ecbc41c4afc124914" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '118' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 87443c348f0fef4024b71e8a678690f98fce5dc3 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 8A6E:1A88C7:CA3CAF:E38650:68108DAC + X-Served-By: + - cache-fra-etou8220022-FRA + X-Timer: + - S1745915426.110658,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml new file mode 100644 index 000000000..b96072e8c --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml @@ -0,0 +1,209 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.3.0/examples/item_eo_bands.json + response: + body: + string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, + with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n + \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.3.0/schema.json\",\n + \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": + true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n + \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n + \ \"stddev\": 245.71762908\n },\n {\n \"mean\": + 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n + \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n + \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": + 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n + \ \"stddev\": 566.4170017\n },\n {\n \"mean\": + 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n + \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n + \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": + 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n + \ \"stddev\": 404.91978886\n },\n {\n \"mean\": + 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n + \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n + \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": + 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n + \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": + \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil + schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n + \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": + \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": + 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": + \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": + 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": + \"B03\",\n \"common_name\": \"green\",\n \"description\": + \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": + 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": + \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": + 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n + \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": + 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": + \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": + 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": + \"B07\",\n \"common_name\": \"rededge\",\n \"description\": + \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": + 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": + \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": + 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n + \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": + \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": + 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": + \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": + 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n + \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": + \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": + 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": + \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": + 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": + \"B12\",\n \"common_name\": \"swir22\",\n \"description\": + \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": + 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": + \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:source_code\",\n \"code\",\n \"metadata\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '2481' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"a8e548ba2f956af68d095ed3395f558cd02489363df3b2b44052cc4a5a15653e" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '118' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 9f483102ad1f4e924b4bcd84a00606d99516dc4a + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - FCEF:117E:6F0439:7ED11A:68108DAC + X-Served-By: + - cache-fra-etou8220123-FRA + X-Timer: + - S1745915426.179302,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml new file mode 100644 index 000000000..4339f6716 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml @@ -0,0 +1,156 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.0.0/examples/item_multi_io.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"RGB\",\n \"bands\": + [\n \"B04\",\n \"B03\",\n \"B02\"\n ],\n + \ \"input\": {\n \"shape\": [\n -1,\n 3,\n + \ 64,\n 64\n ],\n \"dim_order\": [\n + \ \"batch\",\n \"channel\",\n \"height\",\n + \ \"width\"\n ],\n \"data_type\": \"uint16\"\n + \ },\n \"norm_by_channel\": false,\n \"norm_type\": null,\n + \ \"resize_type\": null\n },\n {\n \"name\": \"NDVI\",\n + \ \"bands\": [\n \"B04\",\n \"B08\"\n ],\n + \ \"pre_processing_function\": {\n \"format\": \"gdal-calc\",\n + \ \"expression\": \"(A - B) / (A + B)\"\n },\n \"input\": + {\n \"shape\": [\n -1,\n 1,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"ndvi\",\n \"height\",\n \"width\"\n ],\n + \ \"data_type\": \"uint16\"\n }\n }\n ],\n \"mlm:output\": + [\n {\n \"name\": \"vegetation-segmentation\",\n \"tasks\": + [\n \"semantic-segmentation\"\n ],\n \"result\": {\n + \ \"shape\": [\n -1,\n 1\n ],\n \"dim_order\": + [\n \"batch\",\n \"class\"\n ],\n \"data_type\": + \"uint8\"\n },\n \"classification_classes\": [\n {\n + \ \"value\": 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": null\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 255,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": null\n },\n {\n + \ \"name\": \"inverse-mask\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": [\n 255,\n + \ 255,\n 255\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 0,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"logical_not(A)\"\n }\n + \ }\n ],\n \"raster:bands\": [\n {\n \"name\": \"B02 + - blue\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03 - + green\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04 - + red\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08 - + nir\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet50_sentinel2_rgb_moco/blob/main/resnet50_sentinel2_rgb_moco.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-50 classification model trained on Sentinel-2 RGB imagery with torchgeo.\",\n + \ \"type\": \"application/octet-stream; application=pytorch\",\n \"roles\": + [\n \"mlm:model\",\n \"mlm:weights\"\n ]\n }\n },\n + \ \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": \"./collection.json\",\n + \ \"type\": \"application/json\"\n },\n {\n \"rel\": \"self\",\n + \ \"href\": \"./item_multi_io.json\",\n \"type\": \"application/geo+json\"\n + \ },\n {\n \"rel\": \"derived_from\",\n \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1572' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"b8e68364828f14a588c33c8a9e49382d8e69c2bbe5052e997e7a039f612178aa" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '117' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 34f627f96ddccc8c605c63326973840c9edb02a9 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 7B49:230D29:B4D608:CD825C:681087AA + X-Served-By: + - cache-fra-etou8220118-FRA + X-Timer: + - S1745915426.247149,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml new file mode 100644 index 000000000..1ca0e4513 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml @@ -0,0 +1,162 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.1.0/examples/item_multi_io.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"model-multi-input\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Generic model that employs multiple + input sources with different combination of bands.\",\n \"datetime\": null,\n + \ \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": \"9999-12-31T23:59:59Z\",\n + \ \"mlm:name\": \"Resnet-18 Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n + \ \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:framework\": \"pytorch\",\n \"mlm:framework_version\": \"2.1.2+cu121\",\n + \ \"file:size\": 43000000,\n \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": + 11700000,\n \"mlm:pretrained_source\": \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": + \"cuda\",\n \"mlm:accelerator_constrained\": false,\n \"mlm:accelerator_summary\": + \"Unknown\",\n \"mlm:batch_size_suggestion\": 256,\n \"mlm:input\": + [\n {\n \"name\": \"RGB\",\n \"bands\": [\n \"B04\",\n + \ \"B03\",\n \"B02\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"uint16\"\n },\n \"norm_by_channel\": + false,\n \"norm_type\": null,\n \"resize_type\": null\n },\n + \ {\n \"name\": \"NDVI\",\n \"bands\": [\n \"B04\",\n + \ \"B08\"\n ],\n \"pre_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"(A - B) / (A + B)\"\n },\n + \ \"input\": {\n \"shape\": [\n -1,\n 1,\n + \ 64,\n 64\n ],\n \"dim_order\": [\n + \ \"batch\",\n \"ndvi\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"uint16\"\n }\n },\n {\n + \ \"name\": \"DEM\",\n \"description\": \"Digital elevation model. + Comes from another source than the Sentinel bands. Therefore, no 'bands' associated + to it.\",\n \"bands\": [],\n \"input\": {\n \"shape\": + [\n -1,\n 1,\n 64,\n 64\n ],\n + \ \"dim_order\": [\n \"batch\",\n \"ndvi\",\n + \ \"height\",\n \"width\"\n ],\n \"data_type\": + \"float32\"\n }\n }\n ],\n \"mlm:output\": [\n {\n + \ \"name\": \"vegetation-segmentation\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": null\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 255,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": null\n },\n {\n + \ \"name\": \"inverse-mask\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": [\n 255,\n + \ 255,\n 255\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 0,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"logical_not(A)\"\n }\n + \ }\n ],\n \"raster:bands\": [\n {\n \"name\": \"B02 + - blue\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03 - + green\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04 - + red\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08 - + nir\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet50_sentinel2_rgb_moco/blob/main/resnet50_sentinel2_rgb_moco.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-50 classification model trained on Sentinel-2 RGB imagery with torchgeo.\",\n + \ \"type\": \"application/octet-stream; application=pytorch\",\n \"roles\": + [\n \"mlm:model\",\n \"mlm:weights\"\n ]\n }\n },\n + \ \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": \"./collection.json\",\n + \ \"type\": \"application/json\"\n },\n {\n \"rel\": \"self\",\n + \ \"href\": \"./item_multi_io.json\",\n \"type\": \"application/geo+json\"\n + \ },\n {\n \"rel\": \"derived_from\",\n \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1657' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"ec315329c9c65996484f1dab9aa184c19906db9ce90cb2300b05235d2c2faddb" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '117' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - d1512db233f19b44296c533246a0494b557881f9 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 2968:1A88C7:CA3EAE:E38854:68108DAC + X-Served-By: + - cache-fra-etou8220163-FRA + X-Timer: + - S1745915426.311474,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml new file mode 100644 index 000000000..c9f57f8bb --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml @@ -0,0 +1,162 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.2.0/examples/item_multi_io.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.2.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"model-multi-input\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Generic model that employs multiple + input sources with different combination of bands.\",\n \"datetime\": null,\n + \ \"start_datetime\": \"1900-01-01T00:00:00Z\",\n \"end_datetime\": \"9999-12-31T23:59:59Z\",\n + \ \"mlm:name\": \"Resnet-18 Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n + \ \"classification\"\n ],\n \"mlm:architecture\": \"ResNet\",\n + \ \"mlm:framework\": \"pytorch\",\n \"mlm:framework_version\": \"2.1.2+cu121\",\n + \ \"file:size\": 43000000,\n \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": + 11700000,\n \"mlm:pretrained_source\": \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": + \"cuda\",\n \"mlm:accelerator_constrained\": false,\n \"mlm:accelerator_summary\": + \"Unknown\",\n \"mlm:batch_size_suggestion\": 256,\n \"mlm:input\": + [\n {\n \"name\": \"RGB\",\n \"bands\": [\n \"B04\",\n + \ \"B03\",\n \"B02\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 3,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"uint16\"\n },\n \"norm_by_channel\": + false,\n \"norm_type\": null,\n \"resize_type\": null\n },\n + \ {\n \"name\": \"NDVI\",\n \"bands\": [\n \"B04\",\n + \ \"B08\"\n ],\n \"pre_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"(A - B) / (A + B)\"\n },\n + \ \"input\": {\n \"shape\": [\n -1,\n 1,\n + \ 64,\n 64\n ],\n \"dim_order\": [\n + \ \"batch\",\n \"ndvi\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"uint16\"\n }\n },\n {\n + \ \"name\": \"DEM\",\n \"description\": \"Digital elevation model. + Comes from another source than the Sentinel bands. Therefore, no 'bands' associated + to it.\",\n \"bands\": [],\n \"input\": {\n \"shape\": + [\n -1,\n 1,\n 64,\n 64\n ],\n + \ \"dim_order\": [\n \"batch\",\n \"ndvi\",\n + \ \"height\",\n \"width\"\n ],\n \"data_type\": + \"float32\"\n }\n }\n ],\n \"mlm:output\": [\n {\n + \ \"name\": \"vegetation-segmentation\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": null\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 255,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": null\n },\n {\n + \ \"name\": \"inverse-mask\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": [\n 255,\n + \ 255,\n 255\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 0,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"logical_not(A)\"\n }\n + \ }\n ],\n \"raster:bands\": [\n {\n \"name\": \"B02 + - blue\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03 - + green\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04 - + red\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08 - + nir\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet50_sentinel2_rgb_moco/blob/main/resnet50_sentinel2_rgb_moco.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-50 classification model trained on Sentinel-2 RGB imagery with torchgeo.\",\n + \ \"type\": \"application/octet-stream; application=pytorch\",\n \"roles\": + [\n \"mlm:model\",\n \"mlm:weights\"\n ]\n }\n },\n + \ \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": \"./collection.json\",\n + \ \"type\": \"application/json\"\n },\n {\n \"rel\": \"self\",\n + \ \"href\": \"./item_multi_io.json\",\n \"type\": \"application/geo+json\"\n + \ },\n {\n \"rel\": \"derived_from\",\n \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1659' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"2615bf01905ff85470ba440bcbe17f54614988b43e703b01bcc24b09a5cba5df" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '117' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 618e8a2e789630ca9088426bec20bd24148f0408 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 8060:1BD2FE:C7A2CC:E0EC97:68108DA9 + X-Served-By: + - cache-fra-etou8220084-FRA + X-Timer: + - S1745915426.372021,VS0,VE1 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml new file mode 100644 index 000000000..3522b97cb --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml @@ -0,0 +1,166 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.3.0/examples/item_multi_io.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.3.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"model-multi-input\",\n \"collection\": + \"ml-model-examples\",\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": + [\n [\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 58.21798141355221\n + \ ],\n [\n 27.911651652899923,\n 37.13739173208318\n + \ ],\n [\n -7.882190080512502,\n 37.13739173208318\n + \ ]\n ]\n ]\n },\n \"bbox\": [\n -7.882190080512502,\n + \ 37.13739173208318,\n 27.911651652899923,\n 58.21798141355221\n ],\n + \ \"properties\": {\n \"description\": \"Generic model that employs multiple + input sources with different combination of bands, and some inputs without + any band at all.\",\n \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"RGB\",\n \"bands\": + [\n \"B04\",\n \"B03\",\n \"B02\"\n ],\n + \ \"input\": {\n \"shape\": [\n -1,\n 3,\n + \ 64,\n 64\n ],\n \"dim_order\": [\n + \ \"batch\",\n \"channel\",\n \"height\",\n + \ \"width\"\n ],\n \"data_type\": \"uint16\"\n + \ },\n \"norm_by_channel\": false,\n \"norm_type\": null,\n + \ \"resize_type\": null\n },\n {\n \"name\": \"NDVI\",\n + \ \"bands\": [\n \"B04\",\n \"B08\"\n ],\n + \ \"pre_processing_function\": {\n \"format\": \"gdal-calc\",\n + \ \"expression\": \"(A - B) / (A + B)\"\n },\n \"input\": + {\n \"shape\": [\n -1,\n 1,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"ndvi\",\n \"height\",\n \"width\"\n ],\n + \ \"data_type\": \"uint16\"\n }\n },\n {\n \"name\": + \"DEM\",\n \"description\": \"Digital elevation model. Comes from another + source than the Sentinel bands. Therefore, no 'bands' associated to it.\",\n + \ \"bands\": [],\n \"input\": {\n \"shape\": [\n -1,\n + \ 1,\n 64,\n 64\n ],\n \"dim_order\": + [\n \"batch\",\n \"ndvi\",\n \"height\",\n + \ \"width\"\n ],\n \"data_type\": \"float32\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"vegetation-segmentation\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": null\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 255,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": null\n },\n {\n + \ \"name\": \"inverse-mask\",\n \"tasks\": [\n \"semantic-segmentation\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 1\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"uint8\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"NON_VEGETATION\",\n \"description\": + \"background pixels\",\n \"color_hint\": [\n 255,\n + \ 255,\n 255\n ]\n },\n {\n + \ \"value\": 1,\n \"name\": \"VEGETATION\",\n \"description\": + \"pixels where vegetation was detected\",\n \"color_hint\": [\n + \ 0,\n 0,\n 0\n ]\n }\n + \ ],\n \"post_processing_function\": {\n \"format\": + \"gdal-calc\",\n \"expression\": \"logical_not(A)\"\n }\n + \ }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": + \"https://huggingface.co/torchgeo/resnet50_sentinel2_rgb_moco/blob/main/resnet50_sentinel2_rgb_moco.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-50 classification model trained on Sentinel-2 RGB imagery with torchgeo.\",\n + \ \"type\": \"application/octet-stream; application=pytorch\",\n \"roles\": + [\n \"mlm:model\",\n \"mlm:weights\"\n ],\n \"raster:bands\": + [\n {\n \"name\": \"B02 - blue\",\n \"nodata\": 0,\n + \ \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B03 - green\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 10,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B04 - red\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B08 - nir\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 10,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n }\n ]\n }\n },\n \"links\": [\n {\n \"rel\": + \"collection\",\n \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_multi_io.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1688' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"8a7f7c7f98bd63496692bef25107288160f2763f8618048b0a4516885afcdd1d" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '116' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 4938841ea8995faf87ddb8a113c0a9870e55984a + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 1E08:5B0FB:C3A5C2:DCEFDB:68108DAD + X-Served-By: + - cache-fra-etou8220064-FRA + X-Timer: + - S1745915426.436633,VS0,VE7 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml new file mode 100644 index 000000000..0711a31b0 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml @@ -0,0 +1,194 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.0.0/examples/item_raster_bands.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_type\": + null,\n \"resize_type\": null,\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ],\n \"raster:bands\": [\n {\n \"name\": + \"B01\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B02\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B05\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B06\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B07\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B8A\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B09\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B10\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B11\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B12\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ]\n },\n \"source_code\": {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_raster_bands.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1785' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:26 GMT + ETag: + - W/"27c40ee3df9fd2dbdd00cea8e1d17b857c904ad289a6c2c0a9fe0cf407d24bf0" + Expires: + - Tue, 29 Apr 2025 08:35:26 GMT + Source-Age: + - '0' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 7a36ae34b722807e93dfe3f48c400e27363eb6c9 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - A91B:10BA70:79A76D:8B30B1:681087AC + X-Served-By: + - cache-fra-etou8220051-FRA + X-Timer: + - S1745915427.502040,VS0,VE227 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml new file mode 100644 index 000000000..551738ac0 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml @@ -0,0 +1,194 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.1.0/examples/item_raster_bands.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.1.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_type\": + null,\n \"resize_type\": null,\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ],\n \"raster:bands\": [\n {\n \"name\": + \"B01\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B02\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B05\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B06\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B07\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B8A\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B09\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B10\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B11\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B12\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ]\n },\n \"source_code\": {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_raster_bands.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1786' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:27 GMT + ETag: + - W/"5c22d84a039a443127d9a87f0dbfdee885ebebdcfd2e1ee13a7ade60744f8d7f" + Expires: + - Tue, 29 Apr 2025 08:35:27 GMT + Source-Age: + - '0' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - MISS + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - b542ececad89b84b1b8a4a56f77a9f239ae2b83b + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 47BB:112C:B623DB:CE12ED:68108E20 + X-Served-By: + - cache-fra-etou8220107-FRA + X-Timer: + - S1745915427.782391,VS0,VE241 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml new file mode 100644 index 000000000..da2c6d7dd --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml @@ -0,0 +1,194 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.2.0/examples/item_raster_bands.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.2.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_type\": + null,\n \"resize_type\": null,\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ],\n \"raster:bands\": [\n {\n \"name\": + \"B01\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B02\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B05\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B06\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B07\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B8A\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B09\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B10\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B11\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B12\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": + {\n \"href\": \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ]\n },\n \"source_code\": {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n + \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": + \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n + \ \"rel\": \"self\",\n \"href\": \"./item_raster_bands.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1788' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:29 GMT + ETag: + - W/"610fc710cdb0bf17cbf12e94e38d37a3c0111ca0df0c43ce55494f377c599a06" + Expires: + - Tue, 29 Apr 2025 08:35:29 GMT + Source-Age: + - '0' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - MISS + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 5a178a4473df1ba0e3f07ad649af698a1176e9d6 + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - EF74:230D29:C11A4E:DA7002:68108E23 + X-Served-By: + - cache-fra-etou8220096-FRA + X-Timer: + - S1745915427.183779,VS0,VE1942 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml new file mode 100644 index 000000000..87b445e48 --- /dev/null +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml @@ -0,0 +1,201 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.32.3 + method: GET + uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.3.0/examples/item_raster_bands.json + response: + body: + string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.3.0/schema.json\",\n + \ \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n + \ \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n ],\n + \ \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n + \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": + \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n + \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n + \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": + [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n + \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced + from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n + \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n + \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 + Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n + \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n + \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n + \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": + \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": + false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": + 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 + Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n + \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n + \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n + \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n + \ \"shape\": [\n -1,\n 13,\n 64,\n + \ 64\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"channel\",\n \"height\",\n \"width\"\n + \ ],\n \"data_type\": \"float32\"\n },\n \"norm_type\": + null,\n \"resize_type\": null,\n \"pre_processing_function\": + {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n + \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": + \"classification\",\n \"tasks\": [\n \"classification\"\n + \ ],\n \"result\": {\n \"shape\": [\n -1,\n + \ 10\n ],\n \"dim_order\": [\n \"batch\",\n + \ \"class\"\n ],\n \"data_type\": \"float32\"\n + \ },\n \"classification_classes\": [\n {\n \"value\": + 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n + \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 1,\n \"name\": + \"Forest\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 2,\n \"name\": \"Herbaceous + Vegetation\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 3,\n \"name\": + \"Highway\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 4,\n \"name\": \"Industrial + Buildings\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n },\n {\n \"value\": + 6,\n \"name\": \"Permanent Crop\",\n \"description\": + null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": + false\n },\n {\n \"value\": 7,\n \"name\": + \"Residential Buildings\",\n \"description\": null,\n \"title\": + null,\n \"color_hint\": null,\n \"nodata\": false\n + \ },\n {\n \"value\": 8,\n \"name\": + \"River\",\n \"description\": null,\n \"title\": null,\n + \ \"color_hint\": null,\n \"nodata\": false\n },\n + \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n + \ \"description\": null,\n \"title\": null,\n \"color_hint\": + null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": + null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": + \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n + \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A + Resnet-18 classification model trained on normalized Sentinel-2 imagery with + Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; + application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n + \ ],\n \"raster:bands\": [\n {\n \"name\": \"B01\",\n + \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": + 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n + \ \"offset\": 0,\n \"unit\": \"m\"\n },\n {\n + \ \"name\": \"B02\",\n \"nodata\": 0,\n \"data_type\": + \"uint16\",\n \"bits_per_sample\": 15,\n \"spatial_resolution\": + 10,\n \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B03\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B04\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 10,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B05\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B06\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 20,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B07\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B08\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 10,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B8A\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B09\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 60,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B10\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n },\n {\n \"name\": + \"B11\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n + \ \"bits_per_sample\": 15,\n \"spatial_resolution\": 20,\n + \ \"scale\": 0.0001,\n \"offset\": 0,\n \"unit\": + \"m\"\n },\n {\n \"name\": \"B12\",\n \"nodata\": + 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": 15,\n + \ \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": + 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"source_code\": + {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n + \ \"title\": \"Model implementation.\",\n \"description\": \"Source + code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": + [\n \"mlm:source_code\",\n \"code\",\n \"metadata\"\n + \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n + \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n + \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_raster_bands.json\",\n + \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n + \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n + \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n + \ }\n ]\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Cache-Control: + - max-age=300 + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Length: + - '1803' + Content-Security-Policy: + - default-src 'none'; style-src 'unsafe-inline'; sandbox + Content-Type: + - text/plain; charset=utf-8 + Cross-Origin-Resource-Policy: + - cross-origin + Date: + - Tue, 29 Apr 2025 08:30:29 GMT + ETag: + - W/"a27ee1f30298ca82fea5f599426403c50df7b1da816b19a0b602af5649b1531b" + Expires: + - Tue, 29 Apr 2025 08:35:29 GMT + Source-Age: + - '0' + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization,Accept-Encoding,Origin + Via: + - 1.1 varnish + X-Cache: + - MISS + X-Cache-Hits: + - '0' + X-Content-Type-Options: + - nosniff + X-Fastly-Request-ID: + - 540e6adbd74fc013400f20084d209c94f3eb67ea + X-Frame-Options: + - deny + X-GitHub-Request-Id: + - 45A5:5B0FB:C4898F:DDDFF6:68108E25 + X-Served-By: + - cache-fra-etou8220178-FRA + X-Timer: + - S1745915429.237875,VS0,VE295 + X-XSS-Protection: + - 1; mode=block + status: + code: 200 + message: OK +version: 1 diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 51e4ea4b6..4edaedf85 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1,3 +1,4 @@ +import itertools import json import logging import re @@ -5,6 +6,7 @@ from typing import Any, cast import pytest +import requests import pystac.errors from pystac import Asset, Collection, Item, ItemAssetDefinition @@ -1719,3 +1721,44 @@ def test_migration_1_3_to_1_4_collection() -> None: assert "mlm:hyperparameters" in data assert "mlm:artifact_type" in data["assets"]["asset1"] + + +@pytest.mark.vcr +@pytest.mark.parametrize( + "url_template, version", + tuple( + itertools.product( + ( + "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" + "v{version}/examples/item_basic.json", + "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" + "v{version}/examples/item_eo_bands.json", + "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" + "v{version}/examples/item_multi_io.json", + "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" + "v{version}/examples/item_raster_bands.json", + ), + ("1.0.0", "1.1.0", "1.2.0", "1.3.0"), + ) + ), +) +def test_migrate(url_template: str, version: str) -> None: + url = url_template.format(version=version) + r = requests.get(url) + data = r.json() + + old_uri = f"https://crim-ca.github.io/mlm-extension/v{version}/schema.json" + new_uri = f"https://stac-extensions.github.io/mlm/v{version}/schema.json" + + try: + i = data["stac_extensions"].index(old_uri) + data["stac_extensions"][i] = new_uri + except ValueError: + if new_uri not in data["stac_extensions"]: + raise Exception("Stac object does not list stac:mlm as extension") + + item = pystac.Item.from_dict(data) + + assert MLMExtension.get_schema_uri() in item.stac_extensions + assert old_uri not in item.stac_extensions + assert new_uri not in item.stac_extensions From 9002c87fc3d5fab07438252c5007de9f0b385833 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Apr 2025 16:36:35 +0200 Subject: [PATCH 24/32] added migration --- pystac/extensions/mlm.py | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index f0ffbb471..bec45be56 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2086,6 +2086,59 @@ def migrate(props_obj: dict[str, Any]) -> None: SyntaxWarning, ) + # if no bands definition is given in mlm:input (bands=[]), + # raster definitions are not allowed to be in the assets object that is + # stac:mlm + if "mlm:input" in props_obj: + no_bands_present = all( + not inp["bands"] for inp in props_obj["mlm:input"] + ) + + if no_bands_present: + for inner_asset_name in obj["assets"]: + inner_asset = obj["assets"][inner_asset_name] + + if "mlm:model" not in inner_asset["roles"]: + continue + + if "raster:bands" in inner_asset: + bands_obj = inner_asset["raster:bands"] + + warnings.warn( + "stac:mlm does not allow 'raster:bands' in mlm:model " + "asset if mlm:input.bands is empty. Moving it to " + "properties if it contains values, or deleting it if " + "it does not contain any values.", + SyntaxWarning, + ) + + # move the bands_obj if it is not an empty list + if bands_obj: + if obj["type"] == "Feature": + obj["properties"]["raster:bands"] = bands_obj + if obj["type"] == "Collection": + obj["raster:bands"] = bands_obj + inner_asset.pop("raster:bands") + + if "eo:bands" in inner_asset: + bands_obj = inner_asset["eo:bands"] + + warnings.warn( + "stac:mlm does not allow 'raster:bands' in mlm:model " + "asset if mlm:input.bands is empty. Moving it to " + "properties if it contains values, or deleting it if " + "it does not contain any values.", + SyntaxWarning, + ) + + # move the bands_obj if it is not an empty list + if bands_obj: + if obj["type"] == "Feature": + obj["properties"]["eo:bands"] = bands_obj + if obj["type"] == "Collection": + obj["eo:bands"] = bands_obj + inner_asset.pop("eo:bands") + if obj["type"] == "Feature": migrate(obj["properties"]) if obj["type"] == "Collection": From 817ac78a5c598b97093c68a508dd0af159fe9260 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 29 Apr 2025 16:36:43 +0200 Subject: [PATCH 25/32] added tests --- tests/extensions/test_mlm.py | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 4edaedf85..ebbe09cb5 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1140,6 +1140,92 @@ def test_migration_1_0_to_1_1_item_assets( assert bool(re.match(pattern, data["item_assets"]["asset1"]["mlm:framework"])) +@pytest.mark.parametrize( + "bands_obj_name, bands_obj", + ( + ("raster:bands", {"raster:bands": []}), + ("raster:bands", {"raster:bands": [{"name": "B01"}, {"name": "B02"}]}), + ("eo:bands", {"eo:bands": []}), + ("eo:bands", {"eo:bands": [{"name": "B01"}, {"name": "B02"}]}), + ), +) +def test_migration_1_0_to_1_1_asset_bands_item( + bands_obj_name: str, bands_obj: dict[str, Any] +) -> None: + data: dict[str, Any] = { + "type": "Feature", + "properties": {"mlm:input": [{"bands": []}]}, + "assets": { + "asset1": {"href": "https://example.com", "roles": ["analytic"]}, + "asset2": { + "href": "https://example.com", + "roles": ["analytic"], + **bands_obj, + }, + "asset3": { + "href": "https://example.com", + "roles": ["mlm:model"], + **bands_obj, + }, + }, + } + + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + + if bands_obj[bands_obj_name]: + assert bands_obj_name in data["assets"]["asset2"] + assert bands_obj_name not in data["assets"]["asset3"] + assert bands_obj_name in data["properties"] + else: + assert bands_obj_name in data["assets"]["asset2"] + assert bands_obj_name not in data["assets"]["asset3"] + assert bands_obj_name not in data["properties"] + + +@pytest.mark.parametrize( + "bands_obj_name, bands_obj", + ( + ("raster:bands", {"raster:bands": []}), + ("raster:bands", {"raster:bands": [{"name": "B01"}, {"name": "B02"}]}), + ("eo:bands", {"eo:bands": []}), + ("eo:bands", {"eo:bands": [{"name": "B01"}, {"name": "B02"}]}), + ), +) +def test_migration_1_0_to_1_1_asset_bands_collection( + bands_obj_name: str, bands_obj: dict[str, Any] +) -> None: + data: dict[str, Any] = { + "type": "Collection", + "mlm:input": [{"bands": []}], + "assets": { + "asset1": {"href": "https://example.com", "roles": ["analytic"]}, + "asset2": { + "href": "https://example.com", + "roles": ["analytic"], + **bands_obj, + }, + "asset3": { + "href": "https://example.com", + "roles": ["mlm:model"], + **bands_obj, + }, + }, + } + + with pytest.warns(SyntaxWarning): + MLMExtensionHooks._migrate_1_0_to_1_1(data) + + if bands_obj[bands_obj_name]: + assert bands_obj_name in data["assets"]["asset2"] + assert bands_obj_name not in data["assets"]["asset3"] + assert bands_obj_name in data + else: + assert bands_obj_name in data["assets"]["asset2"] + assert bands_obj_name not in data["assets"]["asset3"] + assert bands_obj_name not in data + + @pytest.mark.parametrize("asset_type", ("assets", "item_assets")) def test_migration_1_1_to_1_2(asset_type: str) -> None: data: dict[str, Any] = {} From 18ae927aea1b1fc1232e08b13d3ad2a5d851e23a Mon Sep 17 00:00:00 2001 From: = Date: Wed, 30 Apr 2025 10:50:33 +0200 Subject: [PATCH 26/32] updated tests --- ...sion}-examples-item_basic.json-1.0.0].yaml | 665 ++++++++++- ...sion}-examples-item_basic.json-1.1.0].yaml | 665 ++++++++++- ...sion}-examples-item_basic.json-1.2.0].yaml | 665 ++++++++++- ...sion}-examples-item_basic.json-1.3.0].yaml | 665 ++++++++++- ...n}-examples-item_eo_bands.json-1.0.0].yaml | 255 ---- ...n}-examples-item_eo_bands.json-1.1.0].yaml | 209 ---- ...n}-examples-item_eo_bands.json-1.2.0].yaml | 209 ---- ...n}-examples-item_eo_bands.json-1.3.0].yaml | 209 ---- ...n}-examples-item_multi_io.json-1.0.0].yaml | 1054 ++++++++++++++++- ...n}-examples-item_multi_io.json-1.1.0].yaml | 1054 ++++++++++++++++- ...n}-examples-item_multi_io.json-1.2.0].yaml | 1054 ++++++++++++++++- ...n}-examples-item_multi_io.json-1.3.0].yaml | 1054 ++++++++++++++++- ...xamples-item_raster_bands.json-1.0.0].yaml | 1052 +++++++++++++++- ...xamples-item_raster_bands.json-1.1.0].yaml | 1050 +++++++++++++++- ...xamples-item_raster_bands.json-1.2.0].yaml | 1050 +++++++++++++++- ...xamples-item_raster_bands.json-1.3.0].yaml | 1050 +++++++++++++++- tests/extensions/test_mlm.py | 4 +- 17 files changed, 10991 insertions(+), 973 deletions(-) delete mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml delete mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml delete mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml delete mode 100644 tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml index 6a337b634..6833292b2 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.0.0].yaml @@ -73,13 +73,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:25 GMT + - Wed, 30 Apr 2025 08:48:43 GMT ETag: - W/"06b55e576e4efab26350d8d7551913db9419014d18bff024af7e5818a2366f4b" Expires: - - Tue, 29 Apr 2025 08:35:25 GMT + - Wed, 30 Apr 2025 08:53:43 GMT Source-Age: - - '120' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -87,24 +87,673 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - cbb71f87565b003068eeb6cf1d44e3e92f0b75fb + - fe2615757ad9d5339688e39fb8c970b71f222932 X-Frame-Options: - deny X-GitHub-Request-Id: - - EAA8:1C62A6:B8FA8E:D1A987:681087C4 + - 7E10:242658:8C51EB:96C1B3:6811E3EA X-Served-By: - - cache-fra-etou8220124-FRA + - cache-fra-etou8220138-FRA X-Timer: - - S1745915426.697783,VS0,VE1 + - S1746002923.164423,VS0,VE198 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:43 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - MISS + X-Cache-Hits: + - '0' + X-Fastly-Request-ID: + - 585f28d624a7b4f5c9c871c09fd669aa472f58fd + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220055-FRA + X-Timer: + - S1746002924.509723,VS0,VE112 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '356' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:43 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - bb24e9c9ded013b390fc64ccd78acbbad3385dae + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220084-FRA + X-Timer: + - S1746002924.793418,VS0,VE3 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml index 572c95588..d0dd017c3 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.1.0].yaml @@ -73,13 +73,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:25 GMT + - Wed, 30 Apr 2025 08:48:44 GMT ETag: - W/"60cdf768894e2f4eaafeb01906736c2bb03903640b6615f1cea0dd4ace03a6d3" Expires: - - Tue, 29 Apr 2025 08:35:25 GMT + - Wed, 30 Apr 2025 08:53:44 GMT Source-Age: - - '120' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -87,24 +87,673 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - fdaeae3f7f917f5f4c801f2719acdc47c172defb + - bf6693b35b4566740830843d786c128a9675bbab X-Frame-Options: - deny X-GitHub-Request-Id: - - 5BEA:6EEED:C4E1E6:DE2B23:68108DA9 + - 8CA2:119D:9A5F86:A5AD73:6811E3E9 X-Served-By: - - cache-fra-etou8220128-FRA + - cache-fra-etou8220112-FRA X-Timer: - - S1745915426.768525,VS0,VE2 + - S1746002924.883973,VS0,VE172 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:44 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 52f5131bf4481a9ca075ab040545a8acd55f1b35 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220176-FRA + X-Timer: + - S1746002924.192519,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '356' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:44 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 85f9d20bac6ba5cae559ab4d282fbbccab0c0ff4 + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220116-FRA + X-Timer: + - S1746002924.334339,VS0,VE2 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml index d209d5ba6..ddefcd3ec 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.2.0].yaml @@ -73,13 +73,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:25 GMT + - Wed, 30 Apr 2025 08:48:44 GMT ETag: - W/"4214e4c8a7e047eaff361f43a1e2ce58d4e403d064c4a0a9fc870a0f02f3ffd4" Expires: - - Tue, 29 Apr 2025 08:35:25 GMT + - Wed, 30 Apr 2025 08:53:44 GMT Source-Age: - - '119' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -87,24 +87,673 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - dea14443ef6f269978dd64c2bb7cf0811dcd3102 + - d88738ce45c7c7ca88a02eb8b695fa53f146e42e X-Frame-Options: - deny X-GitHub-Request-Id: - - 6822:112C:B53704:CD19F6:68108DA9 + - 8E2D:1D50CE:2AE04ED:2EA689B:6811E3EC X-Served-By: - - cache-fra-etou8220154-FRA + - cache-fra-etou8220034-FRA X-Timer: - - S1745915426.841928,VS0,VE1 + - S1746002924.433248,VS0,VE164 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:44 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - c781a0966d4eada9d4e33c7e9601a23b9c43f7f9 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220157-FRA + X-Timer: + - S1746002925.743663,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '357' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:44 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 13aab05cd7ea17b8fc8c9084d6789922b1108b77 + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220106-FRA + X-Timer: + - S1746002925.852991,VS0,VE2 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml index 6e9c29315..2642bdfff 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_basic.json-1.3.0].yaml @@ -73,13 +73,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:25 GMT + - Wed, 30 Apr 2025 08:48:45 GMT ETag: - W/"2cdd4c4b8a96681920b5e858cc552b3b19ca2a40e211d9ef29e3863f040782c2" Expires: - - Tue, 29 Apr 2025 08:35:25 GMT + - Wed, 30 Apr 2025 08:53:45 GMT Source-Age: - - '118' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -87,24 +87,673 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - d9048815950a3df8944faf506270689c94e931a6 + - c47fe1bd7eb6e2683b454f2e4dab7077cef1508b X-Frame-Options: - deny X-GitHub-Request-Id: - - 6444:183F83:C9B8F0:E30245:68108DA9 + - 0F29:112C:2960BD2:2D10907:6811E3EC X-Served-By: - - cache-fra-etou8220020-FRA + - cache-fra-etou8220083-FRA X-Timer: - - S1745915426.908529,VS0,VE1 + - S1746002925.933909,VS0,VE204 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:45 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - c9f3ae052220e429bc406f0dec0d36a862b0f614 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220069-FRA + X-Timer: + - S1746002925.331941,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '357' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:45 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 3177e6d1a3ce1848ca4ef432ae3e0f1d13ec176e + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220059-FRA + X-Timer: + - S1746002925.456796,VS0,VE1 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml deleted file mode 100644 index 47ab3e239..000000000 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.0.0].yaml +++ /dev/null @@ -1,255 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - python-requests/2.32.3 - method: GET - uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.0.0/examples/item_eo_bands.json - response: - body: - string: "{\n \"stac_version\": \"1.0.0\",\n \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.0.0/schema.json\",\n - \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n - \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n - \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n - \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": - \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": - [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced - from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n - \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n - \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 - Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n - \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n - \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n - \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": - \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": - false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": - 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 - Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n - \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n - \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n - \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n - \ \"shape\": [\n -1,\n 13,\n 64,\n - \ 64\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"channel\",\n \"height\",\n \"width\"\n - \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": - true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n - \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n - \ \"stddev\": 245.71762908\n },\n {\n \"mean\": - 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n - \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n - \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": - 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n - \ \"stddev\": 566.4170017\n },\n {\n \"mean\": - 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n - \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n - \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": - 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n - \ \"stddev\": 404.91978886\n },\n {\n \"mean\": - 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n - \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n - \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": - 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n - \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": - {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n - \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": - \"classification\",\n \"tasks\": [\n \"classification\"\n - \ ],\n \"result\": {\n \"shape\": [\n -1,\n - \ 10\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"class\"\n ],\n \"data_type\": \"float32\"\n - \ },\n \"classification_classes\": [\n {\n \"value\": - 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n - \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 1,\n \"name\": - \"Forest\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 2,\n \"name\": \"Herbaceous - Vegetation\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 3,\n \"name\": - \"Highway\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 4,\n \"name\": \"Industrial - Buildings\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n },\n {\n \"value\": - 6,\n \"name\": \"Permanent Crop\",\n \"description\": - null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 7,\n \"name\": - \"Residential Buildings\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 8,\n \"name\": - \"River\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": - null\n }\n ],\n \"eo:bands\": [\n {\n \"name\": \"B01\",\n - \ \"common_name\": \"coastal\",\n \"description\": \"Coastal - aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": - 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": - \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": - 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": - \"B03\",\n \"common_name\": \"green\",\n \"description\": \"Green - (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": - 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": - \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": - 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n \"name\": - \"B05\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": - 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": - \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": - 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": - \"B07\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": - 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": - \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": - 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n \"name\": - \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": \"NIR - 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": - 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": - \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": - 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n \"name\": - \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": \"SWIR - - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": - 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": - \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": - 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": - \"B12\",\n \"common_name\": \"swir22\",\n \"description\": \"SWIR - 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": - 0.242\n }\n ],\n \"raster:bands\": [\n {\n \"name\": - \"B01\",\n \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B02\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B03\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B04\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B05\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B06\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B07\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B08\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 10,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B8A\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B09\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B10\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 60,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B11\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n },\n {\n \"name\": \"B12\",\n - \ \"nodata\": 0,\n \"data_type\": \"uint16\",\n \"bits_per_sample\": - 15,\n \"spatial_resolution\": 20,\n \"scale\": 0.0001,\n \"offset\": - 0,\n \"unit\": \"m\"\n }\n ]\n },\n \"assets\": {\n \"weights\": - {\n \"href\": \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n - \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A - Resnet-18 classification model trained on normalized Sentinel-2 imagery with - Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; - application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n - \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil - schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n - \ \"name\": \"coastal\"\n },\n {\n \"name\": - \"blue\"\n },\n {\n \"name\": \"green\"\n },\n - \ {\n \"name\": \"red\"\n },\n {\n \"name\": - \"rededge1\"\n },\n {\n \"name\": \"rededge2\"\n },\n - \ {\n \"name\": \"rededge3\"\n },\n {\n \"name\": - \"nir\"\n },\n {\n \"name\": \"nir08\"\n },\n - \ {\n \"name\": \"nir09\"\n },\n {\n \"name\": - \"cirrus\"\n },\n {\n \"name\": \"swir16\"\n },\n - \ {\n \"name\": \"swir22\"\n }\n ]\n },\n \"source_code\": - {\n \"href\": \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n - \ \"title\": \"Model implementation.\",\n \"description\": \"Source - code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": - [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n - \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": - \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n - \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": - \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n - \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n - \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n - \ }\n ]\n}\n" - headers: - Accept-Ranges: - - bytes - Access-Control-Allow-Origin: - - '*' - Cache-Control: - - max-age=300 - Connection: - - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '2632' - Content-Security-Policy: - - default-src 'none'; style-src 'unsafe-inline'; sandbox - Content-Type: - - text/plain; charset=utf-8 - Cross-Origin-Resource-Policy: - - cross-origin - Date: - - Tue, 29 Apr 2025 08:30:25 GMT - ETag: - - W/"550b55c5cc7ce92969a64bfa5a8325141386d01c7b097671b9d659f7c70764b5" - Expires: - - Tue, 29 Apr 2025 08:35:25 GMT - Source-Age: - - '118' - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Authorization,Accept-Encoding,Origin - Via: - - 1.1 varnish - X-Cache: - - HIT - X-Cache-Hits: - - '0' - X-Content-Type-Options: - - nosniff - X-Fastly-Request-ID: - - 044807e148068029fbd9f42554c471a3460a5b19 - X-Frame-Options: - - deny - X-GitHub-Request-Id: - - EF89:6EEED:B9770B:D225ED:681087C7 - X-Served-By: - - cache-fra-etou8220031-FRA - X-Timer: - - S1745915426.975329,VS0,VE1 - X-XSS-Protection: - - 1; mode=block - status: - code: 200 - message: OK -version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml deleted file mode 100644 index 7a6c18763..000000000 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.1.0].yaml +++ /dev/null @@ -1,209 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - python-requests/2.32.3 - method: GET - uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.1.0/examples/item_eo_bands.json - response: - body: - string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, - with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n - \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.1.0/schema.json\",\n - \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n - \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n - \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n - \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": - \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": - [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced - from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n - \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n - \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 - Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n - \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n - \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n - \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": - \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": - false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": - 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 - Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n - \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n - \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n - \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n - \ \"shape\": [\n -1,\n 13,\n 64,\n - \ 64\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"channel\",\n \"height\",\n \"width\"\n - \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": - true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n - \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n - \ \"stddev\": 245.71762908\n },\n {\n \"mean\": - 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n - \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n - \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": - 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n - \ \"stddev\": 566.4170017\n },\n {\n \"mean\": - 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n - \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n - \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": - 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n - \ \"stddev\": 404.91978886\n },\n {\n \"mean\": - 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n - \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n - \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": - 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n - \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": - {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n - \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": - \"classification\",\n \"tasks\": [\n \"classification\"\n - \ ],\n \"result\": {\n \"shape\": [\n -1,\n - \ 10\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"class\"\n ],\n \"data_type\": \"float32\"\n - \ },\n \"classification_classes\": [\n {\n \"value\": - 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n - \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 1,\n \"name\": - \"Forest\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 2,\n \"name\": \"Herbaceous - Vegetation\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 3,\n \"name\": - \"Highway\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 4,\n \"name\": \"Industrial - Buildings\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n },\n {\n \"value\": - 6,\n \"name\": \"Permanent Crop\",\n \"description\": - null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 7,\n \"name\": - \"Residential Buildings\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 8,\n \"name\": - \"River\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": - null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": - \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n - \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A - Resnet-18 classification model trained on normalized Sentinel-2 imagery with - Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; - application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n - \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil - schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n - \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": - \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": - 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": - \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": - 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": - \"B03\",\n \"common_name\": \"green\",\n \"description\": - \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": - 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": - \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": - 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n - \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": - 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": - \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": - 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": - \"B07\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": - 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": - \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": - 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n - \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": - \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": - 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": - \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": - 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n - \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": - \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": - 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": - \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": - 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": - \"B12\",\n \"common_name\": \"swir22\",\n \"description\": - \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": - 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": - \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n - \ \"title\": \"Model implementation.\",\n \"description\": \"Source - code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": - [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n - \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": - \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n - \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": - \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n - \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n - \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n - \ }\n ]\n}\n" - headers: - Accept-Ranges: - - bytes - Access-Control-Allow-Origin: - - '*' - Cache-Control: - - max-age=300 - Connection: - - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '2476' - Content-Security-Policy: - - default-src 'none'; style-src 'unsafe-inline'; sandbox - Content-Type: - - text/plain; charset=utf-8 - Cross-Origin-Resource-Policy: - - cross-origin - Date: - - Tue, 29 Apr 2025 08:30:26 GMT - ETag: - - W/"538e8345f63973b9ad1ad9f7aaaa0dacd3ab3ffeea7255d6da75ff0299bd8896" - Expires: - - Tue, 29 Apr 2025 08:35:26 GMT - Source-Age: - - '118' - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Authorization,Accept-Encoding,Origin - Via: - - 1.1 varnish - X-Cache: - - HIT - X-Cache-Hits: - - '0' - X-Content-Type-Options: - - nosniff - X-Fastly-Request-ID: - - 24eec2b921a253b550ede66e2a1d9adc7bd2de44 - X-Frame-Options: - - deny - X-GitHub-Request-Id: - - 5E94:6EEED:C4E611:DE2F9E:68108DAB - X-Served-By: - - cache-fra-etou8220158-FRA - X-Timer: - - S1745915426.042527,VS0,VE2 - X-XSS-Protection: - - 1; mode=block - status: - code: 200 - message: OK -version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml deleted file mode 100644 index b9de4ecf5..000000000 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.2.0].yaml +++ /dev/null @@ -1,209 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - python-requests/2.32.3 - method: GET - uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.2.0/examples/item_eo_bands.json - response: - body: - string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, - with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n - \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.2.0/schema.json\",\n - \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n - \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n - \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n - \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": - \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": - [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced - from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n - \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n - \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 - Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n - \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n - \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n - \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": - \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": - false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": - 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 - Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n - \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n - \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n - \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n - \ \"shape\": [\n -1,\n 13,\n 64,\n - \ 64\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"channel\",\n \"height\",\n \"width\"\n - \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": - true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n - \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n - \ \"stddev\": 245.71762908\n },\n {\n \"mean\": - 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n - \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n - \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": - 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n - \ \"stddev\": 566.4170017\n },\n {\n \"mean\": - 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n - \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n - \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": - 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n - \ \"stddev\": 404.91978886\n },\n {\n \"mean\": - 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n - \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n - \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": - 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n - \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": - {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n - \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": - \"classification\",\n \"tasks\": [\n \"classification\"\n - \ ],\n \"result\": {\n \"shape\": [\n -1,\n - \ 10\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"class\"\n ],\n \"data_type\": \"float32\"\n - \ },\n \"classification_classes\": [\n {\n \"value\": - 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n - \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 1,\n \"name\": - \"Forest\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 2,\n \"name\": \"Herbaceous - Vegetation\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 3,\n \"name\": - \"Highway\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 4,\n \"name\": \"Industrial - Buildings\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n },\n {\n \"value\": - 6,\n \"name\": \"Permanent Crop\",\n \"description\": - null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 7,\n \"name\": - \"Residential Buildings\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 8,\n \"name\": - \"River\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": - null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": - \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n - \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A - Resnet-18 classification model trained on normalized Sentinel-2 imagery with - Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; - application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n - \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil - schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n - \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": - \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": - 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": - \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": - 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": - \"B03\",\n \"common_name\": \"green\",\n \"description\": - \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": - 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": - \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": - 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n - \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": - 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": - \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": - 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": - \"B07\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": - 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": - \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": - 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n - \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": - \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": - 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": - \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": - 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n - \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": - \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": - 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": - \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": - 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": - \"B12\",\n \"common_name\": \"swir22\",\n \"description\": - \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": - 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": - \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n - \ \"title\": \"Model implementation.\",\n \"description\": \"Source - code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": - [\n \"mlm:model\",\n \"code\",\n \"metadata\"\n ]\n - \ }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n \"href\": - \"./collection.json\",\n \"type\": \"application/json\"\n },\n {\n - \ \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n \"type\": - \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n - \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n - \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n - \ }\n ]\n}\n" - headers: - Accept-Ranges: - - bytes - Access-Control-Allow-Origin: - - '*' - Cache-Control: - - max-age=300 - Connection: - - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '2478' - Content-Security-Policy: - - default-src 'none'; style-src 'unsafe-inline'; sandbox - Content-Type: - - text/plain; charset=utf-8 - Cross-Origin-Resource-Policy: - - cross-origin - Date: - - Tue, 29 Apr 2025 08:30:26 GMT - ETag: - - W/"90ccd29b9b5252a7bbcc61aa942d67f941d72bd60900fe3ecbc41c4afc124914" - Expires: - - Tue, 29 Apr 2025 08:35:26 GMT - Source-Age: - - '118' - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Authorization,Accept-Encoding,Origin - Via: - - 1.1 varnish - X-Cache: - - HIT - X-Cache-Hits: - - '0' - X-Content-Type-Options: - - nosniff - X-Fastly-Request-ID: - - 87443c348f0fef4024b71e8a678690f98fce5dc3 - X-Frame-Options: - - deny - X-GitHub-Request-Id: - - 8A6E:1A88C7:CA3CAF:E38650:68108DAC - X-Served-By: - - cache-fra-etou8220022-FRA - X-Timer: - - S1745915426.110658,VS0,VE1 - X-XSS-Protection: - - 1; mode=block - status: - code: 200 - message: OK -version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml deleted file mode 100644 index b96072e8c..000000000 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_eo_bands.json-1.3.0].yaml +++ /dev/null @@ -1,209 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - '*/*' - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - python-requests/2.32.3 - method: GET - uri: https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/v1.3.0/examples/item_eo_bands.json - response: - body: - string: "{\n \"$comment\": \"Demonstrate the use of MLM and EO for bands description, - with EO bands directly in the Model Asset.\",\n \"stac_version\": \"1.0.0\",\n - \ \"stac_extensions\": [\n \"https://crim-ca.github.io/mlm-extension/v1.3.0/schema.json\",\n - \ \"https://stac-extensions.github.io/eo/v1.1.0/schema.json\",\n \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\",\n - \ \"https://stac-extensions.github.io/file/v1.0.0/schema.json\",\n \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n - \ ],\n \"type\": \"Feature\",\n \"id\": \"resnet-18_sentinel-2_all_moco_classification\",\n - \ \"collection\": \"ml-model-examples\",\n \"geometry\": {\n \"type\": - \"Polygon\",\n \"coordinates\": [\n [\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n [\n 27.911651652899923,\n - \ 37.13739173208318\n ],\n [\n -7.882190080512502,\n - \ 37.13739173208318\n ]\n ]\n ]\n },\n \"bbox\": - [\n -7.882190080512502,\n 37.13739173208318,\n 27.911651652899923,\n - \ 58.21798141355221\n ],\n \"properties\": {\n \"description\": \"Sourced - from torchgeo python library, identifier is ResNet18_Weights.SENTINEL2_ALL_MOCO\",\n - \ \"datetime\": null,\n \"start_datetime\": \"1900-01-01T00:00:00Z\",\n - \ \"end_datetime\": \"9999-12-31T23:59:59Z\",\n \"mlm:name\": \"Resnet-18 - Sentinel-2 ALL MOCO\",\n \"mlm:tasks\": [\n \"classification\"\n ],\n - \ \"mlm:architecture\": \"ResNet\",\n \"mlm:framework\": \"pytorch\",\n - \ \"mlm:framework_version\": \"2.1.2+cu121\",\n \"file:size\": 43000000,\n - \ \"mlm:memory_size\": 1,\n \"mlm:total_parameters\": 11700000,\n \"mlm:pretrained_source\": - \"EuroSat Sentinel-2\",\n \"mlm:accelerator\": \"cuda\",\n \"mlm:accelerator_constrained\": - false,\n \"mlm:accelerator_summary\": \"Unknown\",\n \"mlm:batch_size_suggestion\": - 256,\n \"mlm:input\": [\n {\n \"name\": \"13 Band Sentinel-2 - Batch\",\n \"bands\": [\n \"B01\",\n \"B02\",\n \"B03\",\n - \ \"B04\",\n \"B05\",\n \"B06\",\n \"B07\",\n - \ \"B08\",\n \"B8A\",\n \"B09\",\n \"B10\",\n - \ \"B11\",\n \"B12\"\n ],\n \"input\": {\n - \ \"shape\": [\n -1,\n 13,\n 64,\n - \ 64\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"channel\",\n \"height\",\n \"width\"\n - \ ],\n \"data_type\": \"float32\"\n },\n \"norm_by_channel\": - true,\n \"norm_type\": \"z-score\",\n \"resize_type\": null,\n - \ \"statistics\": [\n {\n \"mean\": 1354.40546513,\n - \ \"stddev\": 245.71762908\n },\n {\n \"mean\": - 1118.24399958,\n \"stddev\": 333.00778264\n },\n {\n - \ \"mean\": 1042.92983953,\n \"stddev\": 395.09249139\n - \ },\n {\n \"mean\": 947.62620298,\n \"stddev\": - 593.75055589\n },\n {\n \"mean\": 1199.47283961,\n - \ \"stddev\": 566.4170017\n },\n {\n \"mean\": - 1999.79090914,\n \"stddev\": 861.18399006\n },\n {\n - \ \"mean\": 2369.22292565,\n \"stddev\": 1086.63139075\n - \ },\n {\n \"mean\": 2296.82608323,\n \"stddev\": - 1117.98170791\n },\n {\n \"mean\": 732.08340178,\n - \ \"stddev\": 404.91978886\n },\n {\n \"mean\": - 12.11327804,\n \"stddev\": 4.77584468\n },\n {\n - \ \"mean\": 1819.01027855,\n \"stddev\": 1002.58768311\n - \ },\n {\n \"mean\": 1118.92391149,\n \"stddev\": - 761.30323499\n },\n {\n \"mean\": 2594.14080798,\n - \ \"stddev\": 1231.58581042\n }\n ],\n \"pre_processing_function\": - {\n \"format\": \"python\",\n \"expression\": \"torchgeo.datamodules.eurosat.EuroSATDataModule.collate_fn\"\n - \ }\n }\n ],\n \"mlm:output\": [\n {\n \"name\": - \"classification\",\n \"tasks\": [\n \"classification\"\n - \ ],\n \"result\": {\n \"shape\": [\n -1,\n - \ 10\n ],\n \"dim_order\": [\n \"batch\",\n - \ \"class\"\n ],\n \"data_type\": \"float32\"\n - \ },\n \"classification_classes\": [\n {\n \"value\": - 0,\n \"name\": \"Annual Crop\",\n \"description\": null,\n - \ \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 1,\n \"name\": - \"Forest\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 2,\n \"name\": \"Herbaceous - Vegetation\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 3,\n \"name\": - \"Highway\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 4,\n \"name\": \"Industrial - Buildings\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 5,\n \"name\": \"Pasture\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n },\n {\n \"value\": - 6,\n \"name\": \"Permanent Crop\",\n \"description\": - null,\n \"title\": null,\n \"color_hint\": null,\n \"nodata\": - false\n },\n {\n \"value\": 7,\n \"name\": - \"Residential Buildings\",\n \"description\": null,\n \"title\": - null,\n \"color_hint\": null,\n \"nodata\": false\n - \ },\n {\n \"value\": 8,\n \"name\": - \"River\",\n \"description\": null,\n \"title\": null,\n - \ \"color_hint\": null,\n \"nodata\": false\n },\n - \ {\n \"value\": 9,\n \"name\": \"SeaLake\",\n - \ \"description\": null,\n \"title\": null,\n \"color_hint\": - null,\n \"nodata\": false\n }\n ],\n \"post_processing_function\": - null\n }\n ]\n },\n \"assets\": {\n \"weights\": {\n \"href\": - \"https://huggingface.co/torchgeo/resnet18_sentinel2_all_moco/resolve/main/resnet18_sentinel2_all_moco-59bfdff9.pth\",\n - \ \"title\": \"Pytorch weights checkpoint\",\n \"description\": \"A - Resnet-18 classification model trained on normalized Sentinel-2 imagery with - Eurosat landcover labels with torchgeo\",\n \"type\": \"application/octet-stream; - application=pytorch\",\n \"roles\": [\n \"mlm:model\",\n \"mlm:weights\"\n - \ ],\n \"$comment\": \"Following 'eo:bands' is required to fulfil - schema validation of 'eo' extension.\",\n \"eo:bands\": [\n {\n - \ \"name\": \"B01\",\n \"common_name\": \"coastal\",\n \"description\": - \"Coastal aerosol (band 1)\",\n \"center_wavelength\": 0.443,\n \"full_width_half_max\": - 0.027\n },\n {\n \"name\": \"B02\",\n \"common_name\": - \"blue\",\n \"description\": \"Blue (band 2)\",\n \"center_wavelength\": - 0.49,\n \"full_width_half_max\": 0.098\n },\n {\n \"name\": - \"B03\",\n \"common_name\": \"green\",\n \"description\": - \"Green (band 3)\",\n \"center_wavelength\": 0.56,\n \"full_width_half_max\": - 0.045\n },\n {\n \"name\": \"B04\",\n \"common_name\": - \"red\",\n \"description\": \"Red (band 4)\",\n \"center_wavelength\": - 0.665,\n \"full_width_half_max\": 0.038\n },\n {\n - \ \"name\": \"B05\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 1 (band 5)\",\n \"center_wavelength\": 0.704,\n \"full_width_half_max\": - 0.019\n },\n {\n \"name\": \"B06\",\n \"common_name\": - \"rededge\",\n \"description\": \"Red edge 2 (band 6)\",\n \"center_wavelength\": - 0.74,\n \"full_width_half_max\": 0.018\n },\n {\n \"name\": - \"B07\",\n \"common_name\": \"rededge\",\n \"description\": - \"Red edge 3 (band 7)\",\n \"center_wavelength\": 0.783,\n \"full_width_half_max\": - 0.028\n },\n {\n \"name\": \"B08\",\n \"common_name\": - \"nir\",\n \"description\": \"NIR 1 (band 8)\",\n \"center_wavelength\": - 0.842,\n \"full_width_half_max\": 0.145\n },\n {\n - \ \"name\": \"B8A\",\n \"common_name\": \"nir08\",\n \"description\": - \"NIR 2 (band 8A)\",\n \"center_wavelength\": 0.865,\n \"full_width_half_max\": - 0.033\n },\n {\n \"name\": \"B09\",\n \"common_name\": - \"nir09\",\n \"description\": \"NIR 3 (band 9)\",\n \"center_wavelength\": - 0.945,\n \"full_width_half_max\": 0.026\n },\n {\n - \ \"name\": \"B10\",\n \"common_name\": \"cirrus\",\n \"description\": - \"SWIR - Cirrus (band 10)\",\n \"center_wavelength\": 1.375,\n \"full_width_half_max\": - 0.026\n },\n {\n \"name\": \"B11\",\n \"common_name\": - \"swir16\",\n \"description\": \"SWIR 1 (band 11)\",\n \"center_wavelength\": - 1.61,\n \"full_width_half_max\": 0.143\n },\n {\n \"name\": - \"B12\",\n \"common_name\": \"swir22\",\n \"description\": - \"SWIR 2 (band 12)\",\n \"center_wavelength\": 2.19,\n \"full_width_half_max\": - 0.242\n }\n ]\n },\n \"source_code\": {\n \"href\": - \"https://github.com/microsoft/torchgeo/blob/61efd2e2c4df7ebe3bd03002ebbaeaa3cfe9885a/torchgeo/models/resnet.py#L207\",\n - \ \"title\": \"Model implementation.\",\n \"description\": \"Source - code to run the model.\",\n \"type\": \"text/x-python\",\n \"roles\": - [\n \"mlm:source_code\",\n \"code\",\n \"metadata\"\n - \ ]\n }\n },\n \"links\": [\n {\n \"rel\": \"collection\",\n - \ \"href\": \"./collection.json\",\n \"type\": \"application/json\"\n - \ },\n {\n \"rel\": \"self\",\n \"href\": \"./item_eo_bands.json\",\n - \ \"type\": \"application/geo+json\"\n },\n {\n \"rel\": \"derived_from\",\n - \ \"href\": \"https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a\",\n - \ \"type\": \"application/json\",\n \"ml-aoi:split\": \"train\"\n - \ }\n ]\n}\n" - headers: - Accept-Ranges: - - bytes - Access-Control-Allow-Origin: - - '*' - Cache-Control: - - max-age=300 - Connection: - - keep-alive - Content-Encoding: - - gzip - Content-Length: - - '2481' - Content-Security-Policy: - - default-src 'none'; style-src 'unsafe-inline'; sandbox - Content-Type: - - text/plain; charset=utf-8 - Cross-Origin-Resource-Policy: - - cross-origin - Date: - - Tue, 29 Apr 2025 08:30:26 GMT - ETag: - - W/"a8e548ba2f956af68d095ed3395f558cd02489363df3b2b44052cc4a5a15653e" - Expires: - - Tue, 29 Apr 2025 08:35:26 GMT - Source-Age: - - '118' - Strict-Transport-Security: - - max-age=31536000 - Vary: - - Authorization,Accept-Encoding,Origin - Via: - - 1.1 varnish - X-Cache: - - HIT - X-Cache-Hits: - - '0' - X-Content-Type-Options: - - nosniff - X-Fastly-Request-ID: - - 9f483102ad1f4e924b4bcd84a00606d99516dc4a - X-Frame-Options: - - deny - X-GitHub-Request-Id: - - FCEF:117E:6F0439:7ED11A:68108DAC - X-Served-By: - - cache-fra-etou8220123-FRA - X-Timer: - - S1745915426.179302,VS0,VE1 - X-XSS-Protection: - - 1; mode=block - status: - code: 200 - message: OK -version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml index 4339f6716..5deed6eab 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.0.0].yaml @@ -119,13 +119,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:26 GMT + - Wed, 30 Apr 2025 08:48:45 GMT ETag: - W/"b8e68364828f14a588c33c8a9e49382d8e69c2bbe5052e997e7a039f612178aa" Expires: - - Tue, 29 Apr 2025 08:35:26 GMT + - Wed, 30 Apr 2025 08:53:45 GMT Source-Age: - - '117' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -133,24 +133,1062 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 34f627f96ddccc8c605c63326973840c9edb02a9 + - 60aa8b326adae43581693904cc35d310511edb79 X-Frame-Options: - deny X-GitHub-Request-Id: - - 7B49:230D29:B4D608:CD825C:681087AA + - 4B88:184A0:8D6654:97D80C:6811E3ED X-Served-By: - - cache-fra-etou8220118-FRA + - cache-fra-etou8220024-FRA X-Timer: - - S1745915426.247149,VS0,VE1 + - S1746002926.544023,VS0,VE166 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:45 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - e1ab6a7104f41a450de16e24abf6f0a5cd19a07b + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220106-FRA + X-Timer: + - S1746002926.835542,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '358' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:45 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 8954eba3dc7f240928f66419c526b8d7e8b8746f + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220178-FRA + X-Timer: + - S1746002926.936132,VS0,VE1 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '353' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:46 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 8ee10dec29ee3c117655023143b03f82c4fbcfc1 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220040-FRA + X-Timer: + - S1746002926.064746,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '0' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:46 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - MISS + X-Cache-Hits: + - '0' + X-Fastly-Request-ID: + - 0ab859df17885b144bb25675b1710468e436264f + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220062-FRA + X-Timer: + - S1746002926.175468,VS0,VE109 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '337' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:46 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - ea574301be2f279231d07243f6c9787ea2afdedd + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220022-FRA + X-Timer: + - S1746002926.458421,VS0,VE2 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml index 1ca0e4513..f67393032 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.1.0].yaml @@ -125,13 +125,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:26 GMT + - Wed, 30 Apr 2025 08:48:46 GMT ETag: - W/"ec315329c9c65996484f1dab9aa184c19906db9ce90cb2300b05235d2c2faddb" Expires: - - Tue, 29 Apr 2025 08:35:26 GMT + - Wed, 30 Apr 2025 08:53:46 GMT Source-Age: - - '117' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -139,24 +139,1062 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - d1512db233f19b44296c533246a0494b557881f9 + - 60852f9e73c043dc33915063b3f3495986ca1952 X-Frame-Options: - deny X-GitHub-Request-Id: - - 2968:1A88C7:CA3EAE:E38854:68108DAC + - DB77:FDDB1:89859E:93F5CA:6811E3ED X-Served-By: - - cache-fra-etou8220163-FRA + - cache-fra-etou8220111-FRA X-Timer: - - S1745915426.311474,VS0,VE1 + - S1746002927.558899,VS0,VE189 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:46 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 612e2b2c6d6962315cf558c9dd8d132051fbbd8e + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220143-FRA + X-Timer: + - S1746002927.864726,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '359' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:46 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 0d1cc605497f003af298f9686c95a693894bb27e + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220045-FRA + X-Timer: + - S1746002927.979422,VS0,VE1 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '354' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 17b4fdbccdfb010cfbfebe30cc4b6eaf8bfad393 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220046-FRA + X-Timer: + - S1746002927.091214,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '1' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - b4f4a197a7d5f9b79be3559f46485c0e3bb2a4f2 + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220075-FRA + X-Timer: + - S1746002927.202749,VS0,VE1 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '338' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 0756264fd0e2e5c2e043b281e9806e161b07d218 + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220173-FRA + X-Timer: + - S1746002927.292189,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml index c9f57f8bb..c8012b511 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.2.0].yaml @@ -125,13 +125,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:26 GMT + - Wed, 30 Apr 2025 08:48:47 GMT ETag: - W/"2615bf01905ff85470ba440bcbe17f54614988b43e703b01bcc24b09a5cba5df" Expires: - - Tue, 29 Apr 2025 08:35:26 GMT + - Wed, 30 Apr 2025 08:53:47 GMT Source-Age: - - '117' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -139,24 +139,1062 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 618e8a2e789630ca9088426bec20bd24148f0408 + - 96b38bddced809799ad7c28e40c74626a0516540 X-Frame-Options: - deny X-GitHub-Request-Id: - - 8060:1BD2FE:C7A2CC:E0EC97:68108DA9 + - A31C:1BD2FE:2AD2784:2E98B62:6811E3EE X-Served-By: - - cache-fra-etou8220084-FRA + - cache-fra-etou8220060-FRA X-Timer: - - S1745915426.372021,VS0,VE1 + - S1746002927.379240,VS0,VE167 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 793b5e819c50caeb7902e42d41e402d7bcf32330 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220156-FRA + X-Timer: + - S1746002928.680619,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '360' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 68ef10efb4cb5bba88b5a9cf4cc437d8a2fe0616 + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220163-FRA + X-Timer: + - S1746002928.778665,VS0,VE2 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '355' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 1ec804b265fe231750b3793c321964ba4d80c60e + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220117-FRA + X-Timer: + - S1746002928.883978,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '2' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:47 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 665a01e30fd27bed3a134d2784f684a9bea7f423 + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220086-FRA + X-Timer: + - S1746002928.985252,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '339' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 028298b99f1f646e52f32118f290378188cd86a6 + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220064-FRA + X-Timer: + - S1746002928.078278,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml index 3522b97cb..88596d164 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_multi_io.json-1.3.0].yaml @@ -129,13 +129,13 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:26 GMT + - Wed, 30 Apr 2025 08:48:48 GMT ETag: - W/"8a7f7c7f98bd63496692bef25107288160f2763f8618048b0a4516885afcdd1d" Expires: - - Tue, 29 Apr 2025 08:35:26 GMT + - Wed, 30 Apr 2025 08:53:48 GMT Source-Age: - - '116' + - '0' Strict-Transport-Security: - max-age=31536000 Vary: @@ -143,24 +143,1062 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 4938841ea8995faf87ddb8a113c0a9870e55984a + - c7fb1566a7b001b7b7c9a719b61918039f2610bb X-Frame-Options: - deny X-GitHub-Request-Id: - - 1E08:5B0FB:C3A5C2:DCEFDB:68108DAD + - FFE5:11B6:128191D:140375C:6811E3F0 X-Served-By: - - cache-fra-etou8220064-FRA + - cache-fra-etou8220095-FRA X-Timer: - - S1745915426.436633,VS0,VE7 + - S1746002928.154086,VS0,VE202 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - f806de900570c5302cf282e37cfa39752bdc3ba0 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220127-FRA + X-Timer: + - S1746002929.503033,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '361' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - e93d25a3dfb739c905b0c40843dd991f984459ae + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220054-FRA + X-Timer: + - S1746002929.609425,VS0,VE1 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '356' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 567ba9fbfb6ce06933aa025adaa32c70ac853d03 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220152-FRA + X-Timer: + - S1746002929.708216,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 0feb186679670da798be6438865740d1fea5c6c9 + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220152-FRA + X-Timer: + - S1746002929.807178,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '339' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:48 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - d1098e090c1293ff0ba5541890bea8b1f0aff54b + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220042-FRA + X-Timer: + - S1746002929.898510,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml index 0711a31b0..ecbfcfa3b 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.0.0].yaml @@ -157,11 +157,11 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:26 GMT + - Wed, 30 Apr 2025 08:48:49 GMT ETag: - W/"27c40ee3df9fd2dbdd00cea8e1d17b857c904ad289a6c2c0a9fe0cf407d24bf0" Expires: - - Tue, 29 Apr 2025 08:35:26 GMT + - Wed, 30 Apr 2025 08:53:49 GMT Source-Age: - '0' Strict-Transport-Security: @@ -171,24 +171,1062 @@ interactions: Via: - 1.1 varnish X-Cache: - - HIT + - MISS X-Cache-Hits: - '0' X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 7a36ae34b722807e93dfe3f48c400e27363eb6c9 + - 42924440e215af557ead5eb020696d90b55955e4 X-Frame-Options: - deny X-GitHub-Request-Id: - - A91B:10BA70:79A76D:8B30B1:681087AC + - 9532:116B:1004257:11531F8:6811E3F0 X-Served-By: - - cache-fra-etou8220051-FRA + - cache-fra-etou8220132-FRA X-Timer: - - S1745915427.502040,VS0,VE227 + - S1746002929.984751,VS0,VE162 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:49 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 708cb79a28fa037030bc1e5de3f35490d37104da + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220045-FRA + X-Timer: + - S1746002929.246087,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '362' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:49 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '2' + X-Fastly-Request-ID: + - 764a946d642365a7a59b2e3993b21439a1688631 + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220163-FRA + X-Timer: + - S1746002929.351571,VS0,VE0 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '356' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:49 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 4138c397ae89b08d84976e1a791abd866a9bbcd9 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220149-FRA + X-Timer: + - S1746002929.450482,VS0,VE3 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '3' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:49 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - afaeb47490c7efd66feea509e5725cc12c46f39b + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220111-FRA + X-Timer: + - S1746002930.558707,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '340' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:49 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 1c079335dbdc15d572963f7af233e656c95abe7e + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220080-FRA + X-Timer: + - S1746002930.653546,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml index 551738ac0..b7cdb4409 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.1.0].yaml @@ -157,11 +157,11 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:27 GMT + - Wed, 30 Apr 2025 08:48:49 GMT ETag: - W/"5c22d84a039a443127d9a87f0dbfdee885ebebdcfd2e1ee13a7ade60744f8d7f" Expires: - - Tue, 29 Apr 2025 08:35:27 GMT + - Wed, 30 Apr 2025 08:53:49 GMT Source-Age: - '0' Strict-Transport-Security: @@ -177,18 +177,1056 @@ interactions: X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - b542ececad89b84b1b8a4a56f77a9f239ae2b83b + - 7d02b19c5255e71303e5a9a17d3ca4cbf586f3d1 X-Frame-Options: - deny X-GitHub-Request-Id: - - 47BB:112C:B623DB:CE12ED:68108E20 + - 8E28:119D:9A69F9:A5B877:6811E3EA X-Served-By: - - cache-fra-etou8220107-FRA + - cache-fra-etou8220093-FRA X-Timer: - - S1745915427.782391,VS0,VE241 + - S1746002930.731532,VS0,VE228 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '7' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:50 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 64619ac3a14801dae3ba320141c3292efbd07f0f + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220146-FRA + X-Timer: + - S1746002930.135895,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '362' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:50 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 56da344255d88d52ca78446397cbbfb293a7c6a1 + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220174-FRA + X-Timer: + - S1746002930.255407,VS0,VE3 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '357' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:50 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 90a0f8fd55b659570222b66862330ef3a01285da + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220131-FRA + X-Timer: + - S1746002930.354278,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '4' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:50 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - fba5b86249978d66056d486954749b1ea8239951 + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220024-FRA + X-Timer: + - S1746002930.455185,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '341' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:50 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - d5af0da6e63063b949d9f49e364f6f7fc6265f84 + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220076-FRA + X-Timer: + - S1746002931.549027,VS0,VE2 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml index da2c6d7dd..f5ca376e6 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.2.0].yaml @@ -157,11 +157,11 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:29 GMT + - Wed, 30 Apr 2025 08:48:50 GMT ETag: - W/"610fc710cdb0bf17cbf12e94e38d37a3c0111ca0df0c43ce55494f377c599a06" Expires: - - Tue, 29 Apr 2025 08:35:29 GMT + - Wed, 30 Apr 2025 08:53:50 GMT Source-Age: - '0' Strict-Transport-Security: @@ -177,18 +177,1056 @@ interactions: X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 5a178a4473df1ba0e3f07ad649af698a1176e9d6 + - faf2b1cf573dfb9718ebf90228830b598b126a4f X-Frame-Options: - deny X-GitHub-Request-Id: - - EF74:230D29:C11A4E:DA7002:68108E23 + - 9218:112C:29614DE:2D11292:6811E3F2 X-Served-By: - - cache-fra-etou8220096-FRA + - cache-fra-etou8220143-FRA X-Timer: - - S1745915427.183779,VS0,VE1942 + - S1746002931.636231,VS0,VE250 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '7' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 116508e56e051bcfe7643603eaacfa375680f997 + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220034-FRA + X-Timer: + - S1746002931.058296,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '363' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - d8ac3f8ec147e9347656651254db60b62600c79f + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220145-FRA + X-Timer: + - S1746002931.164839,VS0,VE2 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '358' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 6846c831ed987c00ff57b367aa6fb3b155feeba3 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220107-FRA + X-Timer: + - S1746002931.270275,VS0,VE1 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '5' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 621c46e23b749c062dd42088f4b1753f39c89c75 + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220135-FRA + X-Timer: + - S1746002931.364711,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '342' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 8aa1e689200e323ce6042a89abe6c327347ed31e + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220037-FRA + X-Timer: + - S1746002931.458632,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml index 87b445e48..a3c0321d0 100644 --- a/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml +++ b/tests/extensions/cassettes/test_mlm/test_migrate[https---raw.githubusercontent.com-stac-extensions-mlm-refs-tags-v{version}-examples-item_raster_bands.json-1.3.0].yaml @@ -164,11 +164,11 @@ interactions: Cross-Origin-Resource-Policy: - cross-origin Date: - - Tue, 29 Apr 2025 08:30:29 GMT + - Wed, 30 Apr 2025 08:48:51 GMT ETag: - W/"a27ee1f30298ca82fea5f599426403c50df7b1da816b19a0b602af5649b1531b" Expires: - - Tue, 29 Apr 2025 08:35:29 GMT + - Wed, 30 Apr 2025 08:53:51 GMT Source-Age: - '0' Strict-Transport-Security: @@ -184,18 +184,1056 @@ interactions: X-Content-Type-Options: - nosniff X-Fastly-Request-ID: - - 540e6adbd74fc013400f20084d209c94f3eb67ea + - 3990d560c254fad46e7869359cc67e9ac0180f01 X-Frame-Options: - deny X-GitHub-Request-Id: - - 45A5:5B0FB:C4898F:DDDFF6:68108E25 + - 4FE1:242658:8C60AA:96D16F:6811E3F3 X-Served-By: - - cache-fra-etou8220178-FRA + - cache-fra-etou8220110-FRA X-Timer: - - S1745915429.237875,VS0,VE295 + - S1746002932.545537,VS0,VE179 X-XSS-Protection: - 1; mode=block status: code: 200 message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/mlm/v1.4.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\",\n \"title\": + \"Machine Learning Model STAC Extension Schema\",\n \"description\": \"This + object represents the metadata for a Machine Learning Model (MLM) used in + STAC documents.\",\n \"$comment\": \"Use 'allOf+if/then' for each 'type' + to allow implementations to report more specific messages about the exact + case in error (if any). Using only a 'oneOf/allOf' with the 'type' caused + any incompatible 'type' to be reported first with a minimal and poorly described + error by 'pystac'.\",\n \"allOf\": [\n {\n \"description\": \"This + is the schema for STAC extension MLM in Items.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"description\": + \"Schema to validate the MLM fields permitted under Item properties or Assets + properties.\",\n \"type\": \"object\",\n \"required\": + [\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"properties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Item properties.\",\n + \ \"$ref\": \"#/$defs/mlmItemFields\"\n },\n \"assets\": + {\n \"additionalProperties\": {\n \"$comment\": + \"Schema to validate the MLM fields permitted under Asset properties.\",\n + \ \"$ref\": \"#/$defs/mlmAssetFields\"\n }\n + \ }\n }\n },\n {\n \"$ref\": + \"#/$defs/stac_extensions_mlm\"\n },\n {\n \"$comment\": + \"Schema to validate cross-references of bands between MLM inputs and any + 'bands'-compliant section describing them using another STAC definition.\",\n + \ \"$ref\": \"#/$defs/AnyBandsRef\"\n },\n {\n + \ \"$comment\": \"Schema to validate that at least one Asset defines + a model role.\",\n \"$ref\": \"#/$defs/AssetModelRoleMinimumOneDefinition\"\n + \ },\n {\n \"$comment\": \"Schema to validate + that the Asset model properties are mutually exclusive to the model role.\",\n + \ \"$ref\": \"#/$defs/AssetModelRequiredProperties\"\n }\n + \ ]\n }\n },\n {\n \"description\": \"This is the schema + for STAC extension MLM in Collections.\",\n \"if\": {\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n }\n }\n },\n + \ \"then\": {\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"properties\": {\n \"summaries\": {\n + \ \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/$defs/mlmCollectionFields\"\n }\n + \ },\n \"assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/$defs/mlmAssetFields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/$defs/mlmAssetFields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_mlm\"\n + \ }\n ]\n }\n }\n ],\n \"$defs\": {\n \"stac_extensions_mlm\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/mlm/v1.4.0/schema.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/eo/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_item\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition, + which describes the STAC-Item field named 'properties' containing 'eo:bands' + as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"properties\": {\n \"required\": + [\n \"eo:bands\"\n ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": + {\n \"type\": \"object\"\n }\n }\n + \ }\n }\n }\n },\n \"stac_extensions_eo_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Asset + containing 'eo:bands' as described in [https://github.com/stac-extensions/eo#item-properties-or-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"eo:bands\"\n + \ ],\n \"properties\": {\n \"eo:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\"\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_extensions_raster\": {\n \"type\": + \"object\",\n \"required\": [\n \"stac_extensions\"\n ],\n + \ \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"string\",\n + \ \"pattern\": \"https://stac-extensions\\\\.github\\\\.io/raster/v1(\\\\.[0-9]+){2}/schema\\\\.json\"\n + \ }\n }\n }\n },\n \"stac_extensions_raster_bands_asset\": + {\n \"required\": [\n \"assets\"\n ],\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + at least one Asset field containing 'raster:bands' as described in [https://github.com/stac-extensions/raster/tree/v1.1.0#item-asset-fields].\",\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"required\": [\n \"raster:bands\"\n + \ ],\n \"properties\": {\n \"raster:bands\": + {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"$comment\": \"Raster + extension does not explicitly indicate a 'name', but one is needed for MLM.\",\n + \ \"type\": \"object\",\n \"required\": + [\n \"name\"\n ],\n \"properties\": + {\n \"name\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n }\n }\n + \ }\n }\n }\n }\n }\n + \ }\n }\n },\n \"stac_version_1.1\": {\n \"$comment\": + \"Requirement for STAC 1.1 or above.\",\n \"type\": \"object\",\n \"required\": + [\n \"stac_version\"\n ],\n \"properties\": {\n \"stac_version\": + {\n \"pattern\": \"1\\\\.[1-9][0-9]*\\\\.[0-9]+(-.*)?\"\n }\n + \ }\n },\n \"fields\": {\n \"description\": \"All possible + MLM fields regardless of the level they apply (Collection, Item, Asset, Link).\",\n + \ \"type\": \"object\",\n \"properties\": {\n \"mlm:name\": + {\n \"$ref\": \"#/$defs/mlm:name\"\n },\n \"mlm:architecture\": + {\n \"$ref\": \"#/$defs/mlm:architecture\"\n },\n \"mlm:tasks\": + {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n \"mlm:framework\": + {\n \"$ref\": \"#/$defs/mlm:framework\"\n },\n \"mlm:framework_version\": + {\n \"$ref\": \"#/$defs/mlm:framework_version\"\n },\n \"mlm:memory_size\": + {\n \"$ref\": \"#/$defs/mlm:memory_size\"\n },\n \"mlm:total_parameters\": + {\n \"$ref\": \"#/$defs/mlm:total_parameters\"\n },\n \"mlm:pretrained\": + {\n \"$ref\": \"#/$defs/mlm:pretrained\"\n },\n \"mlm:pretrained_source\": + {\n \"$ref\": \"#/$defs/mlm:pretrained_source\"\n },\n \"mlm:batch_size_suggestion\": + {\n \"$ref\": \"#/$defs/mlm:batch_size_suggestion\"\n },\n + \ \"mlm:accelerator\": {\n \"$ref\": \"#/$defs/mlm:accelerator\"\n + \ },\n \"mlm:accelerator_constrained\": {\n \"$ref\": + \"#/$defs/mlm:accelerator_constrained\"\n },\n \"mlm:accelerator_summary\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_summary\"\n },\n \"mlm:accelerator_count\": + {\n \"$ref\": \"#/$defs/mlm:accelerator_count\"\n },\n \"mlm:input\": + {\n \"$ref\": \"#/$defs/mlm:input\"\n },\n \"mlm:output\": + {\n \"$ref\": \"#/$defs/mlm:output\"\n },\n \"mlm:hyperparameters\": + {\n \"$ref\": \"#/$defs/mlm:hyperparameters\"\n },\n \"mlm:artifact_type\": + {\n \"$ref\": \"#/$defs/mlm:artifact_type\"\n },\n \"mlm:compile_method\": + {\n \"$ref\": \"#/$defs/mlm:compile_method\"\n }\n },\n + \ \"$comment\": \"Allow properties not defined by MLM prefix to work with + other extensions and attributes, but disallow undefined MLM fields.\",\n \"patternProperties\": + {\n \"^(?!mlm:)\": {}\n },\n \"additionalProperties\": false\n + \ },\n \"mlmCollectionFields\": {\n \"description\": \"Schema to + validate the MLM fields permitted under Collection summaries.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Collection summaries.\",\n \"type\": \"object\",\n \"required\": + []\n },\n {\n \"description\": \"Fields that are disallowed + under the Collection summaries.\",\n \"not\": {\n \"required\": + [\n \"mlm:input\",\n \"mlm:output\",\n \"mlm:artifact_type\",\n + \ \"mlm:compile_method\"\n ]\n }\n },\n + \ {\n \"description\": \"Field with known definitions that + must be validated.\",\n \"$ref\": \"#/$defs/fields\"\n }\n + \ ]\n },\n \"mlmItemFields\": {\n \"description\": \"Schema + to validate the MLM fields permitted under Item properties.\",\n \"allOf\": + [\n {\n \"description\": \"Fields that are mandatory under + the Item properties.\",\n \"required\": [\n \"mlm:name\",\n + \ \"mlm:architecture\",\n \"mlm:tasks\",\n \"mlm:input\",\n + \ \"mlm:output\"\n ]\n },\n {\n \"description\": + \"Fields that are disallowed under the Item properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\"required\": + [\"mlm:artifact_type\"]},\n {\"required\": [\"mlm:compile_method\"]}\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlmAssetFields\": {\n + \ \"description\": \"Schema to validate the MLM fields permitted under + Assets properties.\",\n \"allOf\": [\n {\n \"description\": + \"Fields that are disallowed under the Asset properties.\",\n \"$comment\": + \"Particularity of the 'not/required' approach: they must be tested one by + one. Otherwise, it validates that they are all (simultaneously) not present.\",\n + \ \"not\": {\n \"anyOf\": [\n {\n \"required\": + [\n \"mlm:name\"\n ]\n },\n {\n + \ \"required\": [\n \"mlm:input\"\n ]\n + \ },\n {\n \"required\": [\n \"mlm:output\"\n + \ ]\n },\n {\n \"required\": + [\n \"mlm:hyperparameters\"\n ]\n }\n + \ ]\n }\n },\n {\n \"description\": + \"Field with known definitions that must be validated.\",\n \"$ref\": + \"#/$defs/fields\"\n }\n ]\n },\n \"mlm:name\": {\n \"type\": + \"string\",\n \"pattern\": \"^[a-zA-Z][a-zA-Z0-9_.\\\\-\\\\s]+[a-zA-Z0-9]$\"\n + \ },\n \"mlm:architecture\": {\n \"type\": \"string\",\n \"title\": + \"Model Architecture\",\n \"description\": \"A descriptive name of the + model architecture, typically a common name from the literature.\",\n \"examples\": + [\n \"ResNet\",\n \"VGG\",\n \"GAN\",\n \"Vision + Transformer\"\n ]\n },\n \"mlm:framework\": {\n \"title\": + \"Name of the machine learning framework used.\",\n \"anyOf\": [\n {\n + \ \"$comment\": \"Add more entries here as needed, and repeat them + in the README.\",\n \"description\": \"Notable predefined framework + names.\",\n \"type\": \"string\",\n \"enum\": [\n \"PyTorch\",\n + \ \"TensorFlow\",\n \"scikit-learn\",\n \"Hugging + Face\",\n \"Keras\",\n \"ONNX\",\n \"rgee\",\n + \ \"spatialRF\",\n \"JAX\",\n \"MXNet\",\n + \ \"Caffe\",\n \"PyMC\",\n \"Weka\"\n ]\n + \ },\n {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"pattern\": \"^(?=[^\\\\s._\\\\-]).*[^\\\\s._\\\\-]$\",\n \"description\": + \"Any other framework name to allow extension. Enum names should be preferred + when possible to allow better portability.\"\n }\n ]\n },\n + \ \"mlm:framework_version\": {\n \"title\": \"Framework version\",\n + \ \"type\": \"string\",\n \"pattern\": \"^(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)\\\\.(0|[1-9]\\\\d*)(?:-((?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\\\.(?:0|[1-9]\\\\d*|\\\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\\\+([0-9a-zA-Z-]+(?:\\\\.[0-9a-zA-Z-]+)*))?$\"\n + \ },\n \"mlm:artifact_type\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"torch.save\",\n \"torch.jit.save\",\n + \ \"torch.export.save\",\n \"tf.keras.Model.save\",\n \"tf.keras.Model.save_weights\",\n + \ \"tf.saved_model.export(format='tf_saved_model')\"\n ]\n },\n + \ \"mlm:compile_method\": {\n \"type\": \"string\",\n \"minLength\": + 1,\n \"examples\": [\n \"aot\",\n \"jit\"\n ]\n },\n + \ \"mlm:tasks\": {\n \"type\": \"array\",\n \"uniqueItems\": true,\n + \ \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"regression\",\n + \ \"classification\",\n \"scene-classification\",\n \"detection\",\n + \ \"object-detection\",\n \"segmentation\",\n \"semantic-segmentation\",\n + \ \"instance-segmentation\",\n \"panoptic-segmentation\",\n + \ \"similarity-search\",\n \"generative\",\n \"image-captioning\",\n + \ \"super-resolution\"\n ]\n }\n },\n \"mlm:memory_size\": + {\n \"description\": \"Memory size (in bytes) required to load the model + with the specified accelerator.\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:total_parameters\": {\n \"description\": \"Total + number of model parameters (weights).\",\n \"type\": \"integer\",\n \"minimum\": + 0\n },\n \"mlm:pretrained\": {\n \"type\": \"boolean\",\n \"$comment\": + \"If trained from scratch, the source should be explicitly 'null'. However, + omitting the source if pretrained is allowed.\",\n \"if\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"properties\": {\n + \ \"mlm:pretrained\": {\n \"const\": false\n }\n + \ }\n }\n }\n },\n \"then\": {\n \"$comment\": + \"This is the JSON-object 'properties' definition, which describes the STAC-Item + field named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"$comment\": \"This is the JSON-object 'properties' definition + for the STAC MLM pretraining reference.\",\n \"required\": [\n + \ \"mlm:pretrained_source\"\n ],\n \"properties\": + {\n \"mlm:pretrained_source\": {\n \"const\": + null\n }\n }\n }\n }\n }\n },\n + \ \"mlm:pretrained_source\": {\n \"description\": \"Pre-training dataset + reference or training from scratch definition.\",\n \"oneOf\": [\n {\n + \ \"type\": \"string\",\n \"description\": \"The name or + URI of the dataset used for pretraining the model.\",\n \"examples\": + [\n \"ImageNet\",\n \"EuroSAT\"\n ]\n },\n + \ {\n \"type\": \"null\",\n \"description\": \"Explicit + mention that the model is trained from scratch.\"\n }\n ]\n },\n + \ \"mlm:batch_size_suggestion\": {\n \"description\": \"Recommended + batch size to employ the model with the accelerator.\",\n \"type\": \"integer\",\n + \ \"minimum\": 0\n },\n \"mlm:accelerator\": {\n \"oneOf\": + [\n {\n \"type\": \"string\",\n \"enum\": [\n \"amd64\",\n + \ \"cuda\",\n \"xla\",\n \"amd-rocm\",\n \"intel-ipex-cpu\",\n + \ \"intel-ipex-gpu\",\n \"macos-arm\"\n ]\n + \ },\n {\n \"type\": \"null\"\n }\n ],\n + \ \"default\": null\n },\n \"mlm:accelerator_constrained\": {\n + \ \"type\": \"boolean\",\n \"default\": false\n },\n \"mlm:accelerator_summary\": + {\n \"type\": \"string\"\n },\n \"mlm:accelerator_count\": {\n + \ \"type\": \"integer\",\n \"minimum\": 1\n },\n \"mlm:input\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": \"#/$defs/ModelInput\"\n + \ }\n },\n \"ModelInput\": {\n \"title\": \"Model Input Object\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\",\n \"bands\",\n + \ \"input\"\n ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"bands\": {\n \"$ref\": \"#/$defs/ModelBands\"\n },\n + \ \"input\": {\n \"$ref\": \"#/$defs/InputStructure\"\n },\n + \ \"description\": {\n \"type\": \"string\",\n \"minLength\": + 1\n },\n \"value_scaling\": {\n \"$ref\": \"#/$defs/ValueScaling\"\n + \ },\n \"resize_type\": {\n \"$ref\": \"#/$defs/ResizeType\"\n + \ },\n \"pre_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n },\n \"mlm:output\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"title\": \"Model Output Object\",\n \"type\": + \"object\",\n \"required\": [\n \"name\",\n \"tasks\",\n + \ \"result\"\n ],\n \"properties\": {\n \"name\": + {\n \"type\": \"string\",\n \"minLength\": 1\n },\n + \ \"tasks\": {\n \"$ref\": \"#/$defs/mlm:tasks\"\n },\n + \ \"result\": {\n \"$ref\": \"#/$defs/ResultStructure\"\n + \ },\n \"description\": {\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n \"classification:classes\": + {\n \"$ref\": \"#/$defs/ClassificationClasses\"\n },\n + \ \"post_processing_function\": {\n \"$ref\": \"#/$defs/ProcessingExpression\"\n + \ }\n }\n }\n },\n \"mlm:hyperparameters\": {\n + \ \"type\": \"object\",\n \"minProperties\": 1,\n \"patternProperties\": + {\n \"^[0-9a-zA-Z_.-]+$\": true\n },\n \"additionalProperties\": + false\n },\n \"InputStructure\": {\n \"title\": \"Input Structure + Object\",\n \"type\": \"object\",\n \"required\": [\n \"shape\",\n + \ \"dim_order\",\n \"data_type\"\n ],\n \"properties\": + {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"ResultStructure\": {\n \"title\": \"Result + Structure Object\",\n \"type\": \"object\",\n \"required\": [\n + \ \"shape\",\n \"dim_order\",\n \"data_type\"\n ],\n + \ \"properties\": {\n \"shape\": {\n \"$ref\": \"#/$defs/DimensionShape\"\n + \ },\n \"dim_order\": {\n \"$ref\": \"#/$defs/DimensionOrder\"\n + \ },\n \"data_type\": {\n \"$ref\": \"#/$defs/DataType\"\n + \ }\n }\n },\n \"DimensionShape\": {\n \"type\": \"array\",\n + \ \"minItems\": 1,\n \"items\": {\n \"type\": \"integer\",\n + \ \"minimum\": -1\n }\n },\n \"DimensionOrder\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"uniqueItems\": true,\n \"items\": + {\n \"type\": \"string\",\n \"minLength\": 1,\n \"pattern\": + \"^[a-z-_]+$\",\n \"examples\": [\n \"batch\",\n \"channel\",\n + \ \"time\",\n \"height\",\n \"width\",\n \"depth\",\n + \ \"token\",\n \"class\",\n \"score\",\n \"confidence\"\n + \ ]\n }\n },\n \"ValueScaling\": {\n \"oneOf\": [\n + \ {\n \"type\": \"null\"\n },\n {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"$ref\": + \"#/$defs/ValueScalingObject\"\n }\n }\n ]\n },\n + \ \"ValueScalingObject\": {\n \"oneOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\",\n + \ \"maximum\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"min-max\"\n },\n \"minimum\": + {\n \"type\": \"number\"\n },\n \"maximum\": + {\n \"type\": \"number\"\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n + \ \"mean\",\n \"stddev\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"z-score\"\n },\n + \ \"mean\": {\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"type\": \"number\"\n }\n + \ }\n },\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"minimum\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"minimum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-min\"\n },\n \"minimum\": {\n \"type\": + \"number\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"maximum\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"clip-max\"\n },\n \"maximum\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"offset\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"value\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"scale\"\n },\n \"value\": {\n \"type\": + \"number\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ValueScalingProcessingExpression\"\n }\n ]\n },\n + \ \"ValueScalingProcessingExpression\": {\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"processing\"\n }\n }\n },\n {\n \"$ref\": + \"#/$defs/ProcessingExpression\"\n }\n ]\n },\n \"ResizeType\": + {\n \"oneOf\": [\n {\n \"type\": \"string\",\n \"enum\": + [\n \"crop\",\n \"pad\",\n \"interpolation-nearest\",\n + \ \"interpolation-linear\",\n \"interpolation-cubic\",\n + \ \"interpolation-area\",\n \"interpolation-lanczos4\",\n + \ \"interpolation-max\",\n \"wrap-fill-outliers\",\n + \ \"wrap-inverse-map\"\n ]\n },\n {\n \"type\": + \"null\"\n }\n ]\n },\n \"ClassificationClasses\": {\n \"$comment\": + \"Must allow empty array for outputs that provide other predictions than classes.\",\n + \ \"oneOf\": [\n {\n \"$ref\": \"https://stac-extensions.github.io/classification/v1.1.0/schema.json#/definitions/fields/properties/classification:classes\"\n + \ },\n {\n \"type\": \"array\",\n \"maxItems\": + 0\n }\n ]\n },\n \"ProcessingExpression\": {\n \"oneOf\": + [\n {\n \"$ref\": \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#/definitions/fields/properties/processing:expression\"\n + \ },\n {\n \"type\": \"null\"\n }\n ]\n + \ },\n \"DataType\": {\n \"$ref\": \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#/definitions/bands/items/properties/data_type\"\n + \ },\n \"HasArtifactType\": {\n \"$comment\": \"Used to check the + artifact type property that is required by a Model Asset annotated by 'mlm:model' + role.\",\n \"type\": \"object\",\n \"required\": [\n \"mlm:artifact_type\"\n + \ ],\n \"properties\": {\n \"mlm:artifact_type\": {\n \"$ref\": + \"#/$defs/mlm:artifact_type\"\n }\n }\n },\n \"AssetModelRole\": + {\n \"$comment\": \"Used to check the presence of 'mlm:model' role required + by a Model Asset.\",\n \"type\": \"object\",\n \"required\": [\n + \ \"roles\"\n ],\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"contains\": {\n \"const\": + \"mlm:model\"\n },\n \"minItems\": 1\n }\n }\n + \ },\n \"AssetModelRequiredProperties\": {\n \"$comment\": \"Asset + containing the model definition must indicate both the 'mlm:model' role and + an artifact type.\",\n \"required\": [\n \"assets\"\n ],\n + \ \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"if\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ },\n \"then\": {\n \"$ref\": \"#/$defs/HasArtifactType\"\n + \ },\n \"else\": {\n \"not\": {\n \"$ref\": + \"#/$defs/HasArtifactType\"\n }\n }\n }\n + \ }\n }\n },\n \"AssetModelRoleMinimumOneDefinition\": {\n + \ \"$comment\": \"At least one Asset must provide the model definition + indicated by the 'mlm:model' role.\",\n \"required\": [\n \"assets\"\n + \ ],\n \"anyOf\": [\n {\n \"properties\": {\n \"assets\": + {\n \"additionalProperties\": {\n \"$ref\": \"#/$defs/AssetModelRole\"\n + \ }\n }\n }\n },\n {\n \"not\": + {\n \"properties\": {\n \"assets\": {\n \"additionalProperties\": + {\n \"properties\": {\n \"roles\": {\n + \ \"type\": \"array\",\n \"items\": + {\n \"type\": \"string\",\n \"not\": + {\n \"const\": \"mlm:model\"\n }\n + \ }\n }\n }\n }\n + \ }\n }\n }\n }\n ]\n },\n + \ \"ModelBands\": {\n \"description\": \"List of bands (if any) that + compose the input. Band order represents the index position of the bands.\",\n + \ \"$comment\": \"No 'minItems' here to support model inputs not using + any band (other data source).\",\n \"type\": \"array\",\n \"items\": + {\n \"oneOf\": [\n {\n \"description\": \"Implied + named-band with the name directly provided.\",\n \"type\": \"string\",\n + \ \"minLength\": 1\n },\n {\n \"description\": + \"Explicit named-band with optional derived expression to obtain it.\",\n + \ \"type\": \"object\",\n \"required\": [\n \"name\"\n + \ ],\n \"properties\": {\n \"name\": {\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"format\": {\n \"description\": + \"Format to interpret the specified expression used to obtain the band.\",\n + \ \"type\": \"string\",\n \"minLength\": 1\n + \ },\n \"expression\": {\n \"description\": + \"Any representation relevant for the specified 'format'.\"\n }\n + \ },\n \"dependencies\": {\n \"format\": + [\n \"expression\"\n ],\n \"expression\": + [\n \"format\"\n ]\n },\n \"additionalProperties\": + false\n }\n ]\n }\n },\n \"AnyBandsRef\": {\n \"$comment\": + \"This definition ensures that, if at least 1 named MLM input 'bands' is provided, + at least 1 of the supported references from EO, Raster or STAC Core 1.1 are + provided as well. Otherwise, 'bands' must be explicitly empty.\",\n \"if\": + {\n \"type\": \"object\",\n \"$comment\": \"This is the JSON-object + 'properties' definition, which describes the STAC-Item field named 'properties'.\",\n + \ \"properties\": {\n \"properties\": {\n \"type\": + \"object\",\n \"required\": [\n \"mlm:input\"\n ],\n + \ \"$comment\": \"This is the JSON-object 'properties' definition + for the MLM input with bands listing referring to at least one band name.\",\n + \ \"properties\": {\n \"mlm:input\": {\n \"type\": + \"array\",\n \"$comment\": \"Below 'minItems' ensures that + band check does not fail for explicitly empty 'mlm:inputs'.\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n + \ \"required\": [\n \"bands\"\n ],\n + \ \"$comment\": \"This is the 'Model Input Object' properties.\",\n + \ \"properties\": {\n \"bands\": {\n \"type\": + \"array\",\n \"minItems\": 1\n }\n + \ }\n }\n }\n }\n }\n + \ }\n },\n \"then\": {\n \"$comment\": \"Need at least + one 'bands' definition, but multiple are allowed.\",\n \"anyOf\": [\n + \ {\n \"$comment\": \"Bands described by raster extension.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_extensions_raster\"\n + \ },\n {\n \"$ref\": \"#/$defs/stac_extensions_raster_bands_asset\"\n + \ }\n ]\n },\n {\n \"$comment\": + \"Bands described by eo extension.\",\n \"allOf\": [\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo\"\n },\n + \ {\n \"anyOf\": [\n {\n \"$ref\": + \"#/$defs/stac_extensions_eo_bands_item\"\n },\n {\n + \ \"$ref\": \"#/$defs/stac_extensions_eo_bands_asset\"\n + \ }\n ]\n }\n ]\n },\n + \ {\n \"$comment\": \"Bands described by STAC Core 1.1.\",\n + \ \"allOf\": [\n {\n \"$ref\": \"#/$defs/stac_version_1.1\"\n + \ },\n {\n \"$comment\": \"This is + the JSON-object 'properties' definition, which describes the STAC-Item field + named 'properties'.\",\n \"properties\": {\n \"properties\": + {\n \"required\": [\n \"bands\"\n + \ ],\n \"$comment\": \"This is the JSON-object + 'properties' definition for the STAC Core 'bands' field defined by [https://github.com/radiantearth/stac-spec/blob/bands/item-spec/common-metadata.md#bands].\",\n + \ \"properties\": {\n \"bands\": {\n + \ \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": + \"object\"\n }\n }\n }\n + \ }\n }\n }\n ]\n }\n + \ ]\n },\n \"else\": {\n \"$comment\": \"Case where + no 'bands' (empty list) are referenced in the MLM input. Because models can + use a mixture of inputs with/without bands, we cannot enforce eo/raster/stac + bands references to be omitted. If bands are provided in the 'mlm:model', + it will simply be an odd case if none are used in any 'mlm:input' bands'.\"\n + \ }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '8' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '33494' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"67a12887-82d6"' + Last-Modified: + - Mon, 03 Feb 2025 20:35:19 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - ea3acb22572b1c15d3e138abfdd6eadd70d2934e + X-GitHub-Request-Id: + - A3CF:119E:933E42:94ABEA:6811E3EB + X-Served-By: + - cache-fra-etou8220096-FRA + X-Timer: + - S1746002932.850023,VS0,VE2 + expires: + - Wed, 30 Apr 2025 08:58:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/raster/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json#\",\n \"title\": + \"raster Extension\",\n \"description\": \"STAC Raster Extension for STAC + Items.\",\n \"oneOf\": [\n {\n \"$comment\": \"This is the schema + for STAC extension raster in Items.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\",\n \"assets\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Feature\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n }\n }\n + \ },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Collections.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/assetfields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/assetfields\"\n }\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/raster/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"assetfields\": {\n \"type\": \"object\",\n + \ \"properties\": {\n \"raster:bands\": {\n \"$ref\": + \"#/definitions/bands\"\n }\n },\n \"patternProperties\": + {\n \"^(?!raster:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n },\n \"bands\": {\n \"title\": \"Bands\",\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n \"title\": + \"Band\",\n \"type\": \"object\",\n \"minProperties\": 1,\n + \ \"additionalProperties\": true,\n \"properties\": {\n \"data_type\": + {\n \"title\": \"Data type of the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"int8\",\n \"int16\",\n + \ \"int32\",\n \"int64\",\n \"uint8\",\n + \ \"uint16\",\n \"uint32\",\n \"uint64\",\n + \ \"float16\",\n \"float32\",\n \"float64\",\n + \ \"cint16\",\n \"cint32\",\n \"cfloat32\",\n + \ \"cfloat64\",\n \"other\"\n ]\n },\n + \ \"unit\": {\n \"title\": \"Unit denomination of the pixel + value\",\n \"type\": \"string\"\n },\n \"bits_per_sample\": + {\n \"title\": \"The actual number of bits used for this band\",\n + \ \"type\": \"integer\"\n },\n \"sampling\": {\n + \ \"title\": \"Pixel sampling in the band\",\n \"type\": + \"string\",\n \"enum\": [\n \"area\",\n \"point\"\n + \ ]\n },\n \"nodata\": {\n \"title\": + \"No data pixel value\",\n \"oneOf\": [\n {\n \"type\": + \"number\"\n },\n {\n \"type\": \"string\",\n + \ \"enum\": [\n \"nan\",\n \"inf\",\n + \ \"-inf\"\n ]\n }\n ]\n + \ },\n \"scale\": {\n \"title\": \"multiplicator + factor of the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"offset\": {\n \"title\": + \"number to be added to the pixel value to transform into the value\",\n \"type\": + \"number\"\n },\n \"spatial_resolution\": {\n \"title\": + \"Average spatial resolution (in meters) of the pixels in the band\",\n \"type\": + \"number\"\n },\n \"statistics\": {\n \"title\": + \"Statistics\",\n \"type\": \"object\",\n \"minProperties\": + 1,\n \"additionalProperties\": false,\n \"properties\": + {\n \"mean\": {\n \"title\": \"Mean value of all + the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"minimum\": {\n \"title\": \"Minimum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"maximum\": {\n \"title\": \"Maximum value of + all the pixels in the band\",\n \"type\": \"number\"\n },\n + \ \"stddev\": {\n \"title\": \"Standard deviation + value of all the pixels in the band\",\n \"type\": \"number\"\n + \ },\n \"valid_percent\": {\n \"title\": + \"Percentage of valid (not nodata) pixel\",\n \"type\": \"number\"\n + \ }\n }\n },\n \"histogram\": {\n + \ \"title\": \"Histogram\",\n \"type\": \"object\",\n + \ \"additionalItems\": false,\n \"required\": [\n \"count\",\n + \ \"min\",\n \"max\",\n \"buckets\"\n + \ ],\n \"additionalProperties\": false,\n \"properties\": + {\n \"count\": {\n \"title\": \"number of buckets\",\n + \ \"type\": \"number\"\n },\n \"min\": + {\n \"title\": \"Minimum value of the buckets\",\n \"type\": + \"number\"\n },\n \"max\": {\n \"title\": + \"Maximum value of the buckets\",\n \"type\": \"number\"\n + \ },\n \"buckets\": {\n \"title\": + \"distribution buckets\",\n \"type\": \"array\",\n \"minItems\": + 3,\n \"items\": {\n \"title\": \"number of + pixels in the bucket\",\n \"type\": \"integer\"\n }\n + \ }\n }\n }\n }\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '364' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '6318' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:51 GMT + ETag: + - '"66df5c80-18ae"' + Last-Modified: + - Mon, 09 Sep 2024 20:37:20 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 2b02ba0c8898ac2e1e4ff998eb889de5117ca36d + X-GitHub-Request-Id: + - 64B5:6EDF6:28F2EAC:295801B:681184F8 + X-Served-By: + - cache-fra-etou8220160-FRA + X-Timer: + - S1746002932.950606,VS0,VE2 + expires: + - Wed, 30 Apr 2025 02:13:36 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/processing/v1.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json#\",\n \"title\": + \"Processing Extension\",\n \"description\": \"STAC Processing Extension + for STAC Items and STAC Collections.\",\n \"anyOf\": [\n {\n \"$comment\": + \"This is the schema for STAC Items.\",\n \"type\": \"object\",\n \"required\": + [\n \"type\",\n \"properties\",\n \"assets\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": \"Feature\"\n + \ },\n \"properties\": {\n \"allOf\": [\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n },\n + \ {\n \"$ref\": \"#/definitions/fields\"\n }\n + \ ]\n },\n \"assets\": {\n \"$comment\": \"This + validates the fields in Item Assets, but does not require them.\",\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n }\n },\n \"allOf\": + [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n }\n + \ ]\n },\n {\n \"$comment\": \"This is the schema for STAC + Collections.\",\n \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"providers\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"item_assets\": {\n \"type\": \"object\",\n + \ \"additionalProperties\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n },\n \"summaries\": {\n \"$comment\": + \"The values of summaries are not validated yet!\"\n },\n \"assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": {\n + \ \"$ref\": \"#/definitions/fields\"\n }\n }\n },\n + \ \"allOf\": [\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ],\n \"anyOf\": [\n {\n \"$comment\": + \"Requires at least one provider to contain processing fields.\",\n \"type\": + \"object\",\n \"required\": [\n \"providers\"\n ],\n + \ \"properties\": {\n \"providers\": {\n \"type\": + \"array\",\n \"contains\": {\n \"type\": \"object\",\n + \ \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n + \ ],\n \"properties\": {\n \"roles\": + {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n + \ \"processor\"\n ]\n }\n + \ }\n }\n },\n {\n + \ \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ ]\n }\n }\n }\n },\n + \ {\n \"$comment\": \"Requires at least one asset to contain + processing fields.\",\n \"type\": \"object\",\n \"required\": + [\n \"assets\"\n ],\n \"properties\": {\n \"assets\": + {\n \"type\": \"object\",\n \"not\": {\n \"additionalProperties\": + {\n \"not\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n }\n }\n + \ },\n {\n \"$comment\": \"Requires at least one item + asset definition to contain processing fields.\",\n \"type\": \"object\",\n + \ \"required\": [\n \"item_assets\"\n ],\n \"properties\": + {\n \"item_assets\": {\n \"type\": \"object\",\n \"not\": + {\n \"additionalProperties\": {\n \"not\": + {\n \"$ref\": \"#/definitions/require_any_field\"\n }\n + \ }\n }\n }\n }\n },\n + \ {\n \"type\": \"object\",\n \"$comment\": \"Requires + at least one summary to be a processing field.\",\n \"required\": + [\n \"summaries\"\n ],\n \"properties\": {\n + \ \"summaries\": {\n \"$ref\": \"#/definitions/require_any_field\"\n + \ }\n }\n }\n ]\n }\n ],\n \"definitions\": + {\n \"stac_extensions\": {\n \"type\": \"object\",\n \"required\": + [\n \"stac_extensions\"\n ],\n \"properties\": {\n \"stac_extensions\": + {\n \"type\": \"array\",\n \"contains\": {\n \"const\": + \"https://stac-extensions.github.io/processing/v1.1.0/schema.json\"\n }\n + \ }\n }\n },\n \"require_provider_role\": {\n \"type\": + \"object\",\n \"required\": [\n \"roles\"\n ],\n \"properties\": + {\n \"roles\": {\n \"type\": \"array\",\n \"contains\": + {\n \"enum\": [\n \"producer\",\n \"processor\"\n + \ ]\n }\n }\n }\n },\n \"require_any_field\": + {\n \"anyOf\": [\n {\"type\": \"object\", \"required\": [\"processing:expression\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:lineage\"]},\n + \ {\"type\": \"object\", \"required\": [\"processing:level\"]},\n {\"type\": + \"object\", \"required\": [\"processing:facility\"]},\n {\"type\": + \"object\", \"required\": [\"processing:software\"]}\n ]\n },\n \"fields\": + {\n \"type\": \"object\",\n \"properties\": {\n \"processing:expression\": + {\n \"title\": \"Processing Expression\",\n \"type\": \"object\",\n + \ \"required\": [\n \"format\",\n \"expression\"\n + \ ],\n \"properties\": {\n \"format\": {\n \"type\": + \"string\"\n },\n \"expression\": {\n \"description\": + \"Any data type, depending on the format chosen.\"\n }\n }\n + \ },\n \"processing:lineage\": {\n \"title\": \"Processing + Lineage Information\",\n \"type\": \"string\",\n \"examples\": + [\n \"Post Processing GRD\"\n ]\n },\n \"processing:level\": + {\n \"title\": \"Processing Level\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"RAW\",\n \"L1\",\n \"L1A\",\n + \ \"L1B\",\n \"L1C\",\n \"L2\",\n \"L2A\",\n + \ \"L3\",\n \"L4\"\n ]\n },\n \"processing:facility\": + {\n \"title\": \"Processing Facility\",\n \"type\": \"string\",\n + \ \"examples\": [\n \"Copernicus S1 Core Ground Segment + - DPA\"\n ]\n },\n \"processing:software\": {\n \"title\": + \"Processing Software Name / version\",\n \"type\": \"object\",\n + \ \"patternProperties\": {\n \".{1,}\": {\n \"type\": + \"string\"\n }\n },\n \"examples\": [\n {\n + \ \"Sentinel-1 IPF\": \"002.71\"\n }\n ]\n + \ }\n },\n \"patternProperties\": {\n \"^(?!processing:)\": + {}\n },\n \"additionalProperties\": false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '359' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '7146' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:52 GMT + ETag: + - '"663cfd3e-1bea"' + Last-Modified: + - Thu, 09 May 2024 16:43:42 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - e95607f0f6ec3b7e2cc08a772e10d0b1b55a5c09 + X-GitHub-Request-Id: + - CCB6:11BF:2646467:26A98A1:6811AA24 + X-Served-By: + - cache-fra-etou8220168-FRA + X-Timer: + - S1746002932.035253,VS0,VE2 + expires: + - Wed, 30 Apr 2025 04:52:12 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/file/v2.1.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/file/v2.1.0/schema.json#\",\n \"title\": + \"File Info Extension\",\n \"description\": \"STAC File Info Extension for + STAC Items, STAC Catalogs, and STAC Collections.\",\n \"oneOf\": [\n {\n + \ \"$comment\": \"This is the schema for STAC Items.\",\n \"allOf\": + [\n {\n \"type\": \"object\",\n \"required\": [\n + \ \"type\",\n \"assets\"\n ],\n \"properties\": + {\n \"type\": {\n \"const\": \"Feature\"\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"links\": {\n \"type\": \"array\",\n \"items\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Catalogs.\",\n \"allOf\": [\n {\n \"type\": + \"object\",\n \"required\": [\n \"type\"\n ],\n + \ \"properties\": {\n \"type\": {\n \"const\": + \"Catalog\"\n },\n \"links\": {\n \"type\": + \"array\",\n \"items\": {\n \"$ref\": \"#/definitions/fields\"\n + \ }\n }\n }\n },\n {\n \"$ref\": + \"#/definitions/stac_extensions\"\n }\n ]\n },\n {\n \"$comment\": + \"This is the schema for STAC Collections.\",\n \"allOf\": [\n {\n + \ \"type\": \"object\",\n \"required\": [\n \"type\"\n + \ ],\n \"properties\": {\n \"type\": {\n \"const\": + \"Collection\"\n },\n \"assets\": {\n \"type\": + \"object\",\n \"additionalProperties\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"links\": + {\n \"type\": \"array\",\n \"items\": {\n \"$ref\": + \"#/definitions/fields\"\n }\n },\n \"item_assets\": + {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/file/v2.1.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"$comment\": + \"Add your new fields here. Don't require them here, do that above in the + item schema.\",\n \"type\": \"object\",\n \"properties\": {\n \"file:byte_order\": + {\n \"type\": \"string\",\n \"enum\": [\n \"big-endian\",\n + \ \"little-endian\"\n ],\n \"title\": \"File Byte + Order\"\n },\n \"file:checksum\": {\n \"type\": \"string\",\n + \ \"pattern\": \"^[a-f0-9]+$\",\n \"title\": \"File Checksum + (Multihash)\"\n },\n \"file:header_size\": {\n \"type\": + \"integer\",\n \"minimum\": 0,\n \"title\": \"File Header + Size\"\n },\n \"file:size\": {\n \"type\": \"integer\",\n + \ \"minimum\": 0,\n \"title\": \"File Size\"\n },\n + \ \"file:values\": {\n \"type\": \"array\",\n \"minItems\": + 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": + [\n \"values\",\n \"summary\"\n ],\n + \ \"properties\": {\n \"values\": {\n \"type\": + \"array\",\n \"minItems\": 1,\n \"items\": {\n + \ \"description\": \"Any data type is allowed\"\n }\n + \ },\n \"summary\": {\n \"type\": + \"string\",\n \"minLength\": 1\n }\n }\n + \ }\n },\n \"file:local_path\": {\n \"type\": + \"string\",\n \"pattern\": \"^[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+(/[^\\\\r\\\\n\\\\t\\\\\\\\:'\\\"/]+)*/?$\",\n + \ \"title\": \"Relative File Path\"\n }\n },\n \"patternProperties\": + {\n \"^(?!file:)\": {\n \"$comment\": \"Above, change `template` + to the prefix of this extension\"\n }\n },\n \"additionalProperties\": + false\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '6' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '4536' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:52 GMT + ETag: + - '"61b4cf00-11b8"' + Last-Modified: + - Sat, 11 Dec 2021 16:17:04 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - 2fd6aeb2d6ee2a363a2f7c0678ba774b9ebdcfff + X-GitHub-Request-Id: + - 868B:11B5:DD2BB0:DF64F4:6811E3EE + X-Served-By: + - cache-fra-etou8220145-FRA + X-Timer: + - S1746002932.180129,VS0,VE1 + expires: + - Wed, 30 Apr 2025 08:58:46 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK +- request: + body: null + headers: + Connection: + - close + Host: + - stac-extensions.github.io + User-Agent: + - Python-urllib/3.10 + method: GET + uri: https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json + response: + body: + string: "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"$id\": + \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json#\",\n \"title\": + \"ML AOI Extension\",\n \"description\": \"ML AOI Extension for STAC definitions.\",\n + \ \"oneOf\": [\n {\n \"$comment\": \"This is the schema for STAC Collections.\",\n + \ \"allOf\": [\n {\n \"type\": \"object\",\n \"required\": + [\n \"type\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Collection\"\n },\n \"summaries\": + {\n \"type\": \"object\",\n \"properties\": {\n + \ \"ml-aoi:split\": {\n \"type\": \"array\",\n + \ \"items\": {\n \"$ref\": \"#/definitions/fields/properties/ml-aoi:split\"\n + \ }\n }\n }\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n },\n + \ \"item_assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n },\n {\n \"$comment\": \"This is the schema + for STAC Items.\",\n \"allOf\": [\n {\n \"type\": \"object\",\n + \ \"required\": [\n \"type\",\n \"properties\",\n + \ \"assets\"\n ],\n \"properties\": {\n \"type\": + {\n \"const\": \"Feature\"\n },\n \"properties\": + {\n \"allOf\": [\n {\n \"$ref\": + \"#/definitions/fields\"\n }\n ]\n },\n + \ \"assets\": {\n \"type\": \"object\",\n \"additionalProperties\": + {\n \"$ref\": \"#/definitions/fields\"\n }\n }\n + \ }\n },\n {\n \"$ref\": \"#/definitions/stac_extensions\"\n + \ }\n ]\n }\n ],\n \"definitions\": {\n \"stac_extensions\": + {\n \"type\": \"object\",\n \"required\": [\n \"stac_extensions\"\n + \ ],\n \"properties\": {\n \"stac_extensions\": {\n \"type\": + \"array\",\n \"contains\": {\n \"const\": \"https://stac-extensions.github.io/ml-aoi/v0.2.0/schema.json\"\n + \ }\n }\n }\n },\n \"fields\": {\n \"type\": + \"object\",\n \"properties\": {\n \"ml-aoi:split\": {\n \"type\": + \"string\",\n \"enum\": [\"train\", \"test\", \"validate\"]\n },\n + \ \"ml-aoi:role\": {\n \"type\": \"string\",\n \"enum\": + [\"label\", \"feature\"]\n },\n \"ml-aoi:reference-grid\": {\n + \ \"type\": \"boolean\"\n },\n \"ml-aoi:resampling-method\": + {\n \"$comment\": \"Supported GDAL resampling method (https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-r)\",\n + \ \"type\": \"string\",\n \"enum\": [\n \"near\",\n + \ \"bilinear\",\n \"cubic\",\n \"cubcspline\",\n + \ \"lanczos\",\n \"average\",\n \"rms\",\n + \ \"mode\",\n \"max\",\n \"min\",\n + \ \"med\",\n \"q1\",\n \"q3\",\n \"sum\"\n + \ ]\n }\n },\n \"patternProperties\": {\n \"^(?!ml-aoi:)\": + {}\n }\n }\n }\n}\n" + headers: + Accept-Ranges: + - bytes + Access-Control-Allow-Origin: + - '*' + Age: + - '343' + Cache-Control: + - max-age=600 + Connection: + - close + Content-Length: + - '3400' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 30 Apr 2025 08:48:52 GMT + ETag: + - '"6605925b-d48"' + Last-Modified: + - Thu, 28 Mar 2024 15:52:59 GMT + Server: + - GitHub.com + Strict-Transport-Security: + - max-age=31556952 + Vary: + - Accept-Encoding + Via: + - 1.1 varnish + X-Cache: + - HIT + X-Cache-Hits: + - '1' + X-Fastly-Request-ID: + - accce148756425d70a4443818f038623af3e340c + X-GitHub-Request-Id: + - E06D:14F99C:2DEDC77:2E61FB6:6811CF0F + X-Served-By: + - cache-fra-etou8220047-FRA + X-Timer: + - S1746002932.279262,VS0,VE1 + expires: + - Wed, 30 Apr 2025 07:29:43 GMT + permissions-policy: + - interest-cohort=() + x-proxy-cache: + - MISS + status: + code: 200 + message: OK version: 1 diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index ebbe09cb5..9717c658c 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1818,8 +1818,6 @@ def test_migration_1_3_to_1_4_collection() -> None: "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" "v{version}/examples/item_basic.json", "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" - "v{version}/examples/item_eo_bands.json", - "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" "v{version}/examples/item_multi_io.json", "https://raw.githubusercontent.com/stac-extensions/mlm/refs/tags/" "v{version}/examples/item_raster_bands.json", @@ -1848,3 +1846,5 @@ def test_migrate(url_template: str, version: str) -> None: assert MLMExtension.get_schema_uri() in item.stac_extensions assert old_uri not in item.stac_extensions assert new_uri not in item.stac_extensions + + item.validate() From 90f37eefdc90eff6ab08f8e6c5bd82b205eb1cf6 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 30 Apr 2025 11:00:19 +0200 Subject: [PATCH 27/32] update exception message --- tests/extensions/test_mlm.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 9717c658c..50a9a8200 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1839,7 +1839,9 @@ def test_migrate(url_template: str, version: str) -> None: data["stac_extensions"][i] = new_uri except ValueError: if new_uri not in data["stac_extensions"]: - raise Exception("Stac object does not list stac:mlm as extension") + raise Exception( + f"Stac object does not list stac:mlm v{version} as extension" + ) item = pystac.Item.from_dict(data) From 3f37e957e295c02dcd35d63bff11e64b8a08f7d4 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 2 May 2025 12:54:45 +0200 Subject: [PATCH 28/32] added raster migration --- pystac/extensions/mlm.py | 77 ++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index bec45be56..eba45cfe2 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2178,36 +2178,67 @@ def migrate(props_obj: dict[str, Any]) -> None: if "mlm:input" not in props_obj: return - bands_objs_present = any("bands" in inp for inp in props_obj["mlm:input"]) + # check if mlm:input.bands is present and contains items + bands_objs_present = [ + "bands" in inp and len(inp["bands"]) > 0 + for inp in props_obj["mlm:input"] + ] - if not bands_objs_present: + if not any(bands_objs_present): return - if "raster:bands" not in props_obj: + if "eo:bands" in props_obj or "bands" in props_obj: return - raster_bands = props_obj["raster:bands"] - # make sure all raster_bands have a name prop with length>0 - names_properties_valid = all( - "name" in band and len(band["name"]) > 0 for band in raster_bands - ) - if not names_properties_valid: - raise STACError( - "Error migrating stac:mlm version: In mlm>=1.3, each band in " - 'raster:bands is required to have a property "name"' + if ( + "raster:bands" in props_obj + and "eo:bands" not in props_obj + and "bands" not in props_obj + ): + raster_bands = props_obj["raster:bands"] + + bands_valid = all( + "name" in band and len(band["name"]) > 0 for band in raster_bands ) - # no need to perform the actions below if props_obj is an asset - # this is checked by the presence of "roles" prop - if "roles" in props_obj: - return + if not bands_valid: + raise STACError( + "Error migrating stac:mlm version: In mlm>=1.3, each band in " + 'raster:bands is required to have a property "name" with ' + "length > 0" + ) - # copy the raster:bands to assets - for inner_asset_name in obj["assets"]: - inner_asset = obj["assets"][inner_asset_name] - if "mlm:model" not in inner_asset["roles"]: - continue - inner_asset["raster:bands"] = raster_bands + # no need to perform the actions below if props_obj is not an asset + # this is checked by the presence of "roles" prop + if "roles" in props_obj: + return + + # move raster:bands to assets that contain "mlm:model" role + for inner_asset_name in obj["assets"]: + inner_asset = obj["assets"][inner_asset_name] + if "mlm:model" not in inner_asset["roles"]: + continue + inner_asset["raster:bands"] = raster_bands + props_obj.pop("raster:bands") + + # create new bands object from mlm:input.bands if none exist + if ( + "raster:bands" not in props_obj + and "eo:bands" not in props_obj + and "bands" not in props_obj + ): + i = bands_objs_present.index(True) + bands = [ + {"name": band if type(band) is str else band["name"]} + for band in props_obj["mlm:input"][i]["bands"] + ] + + # copy the raster:bands to assets + for inner_asset_name in obj["assets"]: + inner_asset = obj["assets"][inner_asset_name] + if "mlm:model" not in inner_asset["roles"]: + continue + inner_asset["raster:bands"] = bands if obj["type"] == "Feature" and "mlm:input" in obj["properties"]: migrate(obj["properties"]) @@ -2307,7 +2338,7 @@ def migrate(props_obj: dict[str, Any]) -> None: # add new REQUIRED proretie mlm:artifact_type to asset if "mlm:model" in obj["assets"][asset]["roles"]: - obj["assets"][asset]["mlm:artifact_type"] = "" + obj["assets"][asset]["mlm:artifact_type"] = "asdf" def migrate( self, obj: dict[str, Any], version: STACVersionID, info: STACJSONDescription From 91943831855aa802aacafcb1efaf0721d4edd627 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 2 May 2025 14:27:16 +0200 Subject: [PATCH 29/32] updated default artifact_type when migrating --- pystac/extensions/mlm.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pystac/extensions/mlm.py b/pystac/extensions/mlm.py index eba45cfe2..71c091229 100644 --- a/pystac/extensions/mlm.py +++ b/pystac/extensions/mlm.py @@ -2338,7 +2338,10 @@ def migrate(props_obj: dict[str, Any]) -> None: # add new REQUIRED proretie mlm:artifact_type to asset if "mlm:model" in obj["assets"][asset]["roles"]: - obj["assets"][asset]["mlm:artifact_type"] = "asdf" + obj["assets"][asset]["mlm:artifact_type"] = ( + "Placeholder string to satisfy requirements when migrating " + "from mlm v1.3 to v1.4" + ) def migrate( self, obj: dict[str, Any], version: STACVersionID, info: STACJSONDescription From 448dd9bf6ad3bf6aef26aca36e4542f5f4126258 Mon Sep 17 00:00:00 2001 From: = Date: Fri, 2 May 2025 14:57:09 +0200 Subject: [PATCH 30/32] added tests --- tests/extensions/test_mlm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/extensions/test_mlm.py b/tests/extensions/test_mlm.py index 50a9a8200..c091b13ac 100644 --- a/tests/extensions/test_mlm.py +++ b/tests/extensions/test_mlm.py @@ -1253,6 +1253,7 @@ def test_migration_1_1_to_1_2(asset_type: str) -> None: ], True, ), + (["B02", "B03"], None, True), ( ["B02", "B03"], [ @@ -1317,6 +1318,7 @@ def test_migration_1_2_to_1_3_item( ], True, ), + (["B02", "B03"], None, True), ( ["B02", "B03"], [ @@ -1381,6 +1383,7 @@ def test_migration_1_2_to_1_3_collection( ], True, ), + (["B02", "B03"], None, True), ( ["B02", "B03"], [ From 74144c26a4b7fad32352805515727c8e7391074b Mon Sep 17 00:00:00 2001 From: = Date: Fri, 2 May 2025 15:22:08 +0200 Subject: [PATCH 31/32] added mlm changes # Conflicts: # CHANGELOG.md --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f4783d08..52f1e8879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,13 @@ - Type of `proj:code` setter ([#1560](https://github.com/stac-utils/pystac/pull/1560)) - Use `urllib3` to fix parsing non-ascii in urls ([#1566](https://github.com/stac-utils/pystac/pull/1566)) - Some return types and other **mypy** nits ([#1569](https://github.com/stac-utils/pystac/pull/1569)) - +- `extensions.mlm` various fixes + - Fixed ResizeType typos `interpolation-nearest` and `interpolation-linear` + - Fixed displaying the correct property in error message for `ResultStructure.data_type` + - Fixed `ValueScaling.maximum` setter to pop when None is given + - Fixed `ModelInput.value_scaling` to be `list[ValueScaling]` instead of `ValueScaling` + - Fixed missing version migrations + ## [v1.13.0] - 2025-04-15 ### Added From e2eae921338ff3565d48f042730332399dd0f922 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 13 Aug 2025 18:00:47 +0200 Subject: [PATCH 32/32] added PR reference --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f1e8879..2ea70233c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Type of `proj:code` setter ([#1560](https://github.com/stac-utils/pystac/pull/1560)) - Use `urllib3` to fix parsing non-ascii in urls ([#1566](https://github.com/stac-utils/pystac/pull/1566)) - Some return types and other **mypy** nits ([#1569](https://github.com/stac-utils/pystac/pull/1569)) -- `extensions.mlm` various fixes +- `extensions.mlm` various fixes ([#1571](https://github.com/stac-utils/pystac/pull/1571)) - Fixed ResizeType typos `interpolation-nearest` and `interpolation-linear` - Fixed displaying the correct property in error message for `ResultStructure.data_type` - Fixed `ValueScaling.maximum` setter to pop when None is given